1//-----------------------------------------------------------------------------\dlo/ 2// ps!Ext.UI.Input Control v2.0 3// Jonas Software 2013, by Dmitry Lopyrev 4//----------------------------------------------------------------------------- 5// 6//----------------------------------------------------------------------------- 7// Note: Requires Prototype JS library (v.1.7.1 - modified) and Utility.js 8//----------------------------------------------------------------------------- 9 10//Note: all methods can be overriden by derived class 11//Changes: 12/* 13 April 1, 2015 14 - CMS-9149 : Client side modification: added support of new option "selectall" (as a text to show as a label to chekbox) to check/uncheck all items for control Type="Tree" and <cho:Option Text="checkbox" Value="true"/>" 15 - added call to "onBeforeChanged" to Selector control to do custom validation or custom business logic on before value is stored into input field 16 17 18*/ 19 20 21//Simple Data validation. Verifies if given data is matched following conditions 22Utility.UI.Validation = { 23 IsEmail: function (value) { 24 return /^(([\w.-]+@[\w.-]+\.[a-zA-Z]{2,6})[;,]?\s?)+$/gi.test(value); 25 //return /^[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?\\.)+[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?$/gi.test(value); 26 }, 27 IsNumber: function (value) { 28 return /^(\*?-?[\d]*(\.?[\d]+)?\*?;?)+$/gi.test(value); 29 }, 30 IsDate: function (value) { 31 return !isNaN(new Date(value)); 32 }, 33 IsTime: function (value) { 34 return /^((0?[1-9]|1[012])(:[0-5]\d){0,2}(\ ?[AaPp][Mm]*))$|^(0?\d|[1]\d|2[0-3])(:[0-5]\d){0,2}$/.test(value); 35 }, 36 IsBoolean: function (value) { 37 return /^0|1|true|false$/gi.test(value); 38 }, 39}; 40 41Utility.UI.Bit = Class.create({ 42 initialize: function (host, options) { 43 if (!$p(host)) 44 return undefined; 45 Object.extend(this, options || {}); 46 this.host = host.addClassName('bit'); 47 if (this.x) { 48 this.host.data = this.host.getActions({ camelize: true }); 49 this.host.insert(this.host.x = new Element('span', { className: 'x' })); 50 this.$click = this.host.x.on('click', function (e) { 51 e.stop(); 52 this.host.remove(); 53 this.Parent && this.Parent.fire(':delete', this.host.getActions({ camelize: true })); 54 }.bind(this)); 55 this.host.remove = this.host.remove.wrap(function (f) { f(); this.$click && this.$click.stop(); }.bind(this)); 56 } 57 return this; 58 } 59}); 60 61//Base input class 62Utility.UI.Base = Class.create(Utility.Base, { 63 defaults: function () { 64 return this.options = this.host.getActions({ camelize: true, cast: true }); 65 }, 66 initialize: function ($super) { 67 //Initialize a new instance and create base structure 68 //host - main input field: (<input ....>) 69 if (!$super.apply(this, $A(arguments).slice(1))) 70 return false; 71 //set refernce to current instance 72 this.host.$class = this; 73 74 //Find field containr 75 this.FieldContainer = this.host.up('[data-role^="field"]'); 76 //Find a contaner 77 this.InputContainer = this.host.up('[data-role="holder"]'); 78 //Find field Caption 79 this.FieldCaption = this.FieldContainer.down('[data-role="caption"]'); 80 81 this.FieldContainer.getActions({ cast: true }, this.options || this); 82 this.Name = this.host.readAttribute("name").replace(/!.+$/i, ""); 83 84 //Overrides/Wraps important methods of host to do customization 85 this.host.setValue = this.host.setValue.wrap(function (proceed, value, simulate) { 86 var old = this.host.value; 87 if (simulate) { 88 var disabled = this.Is('disabled'); 89 if (disabled) 90 this.host.disabled = false; 91 //call original 92 proceed(value); 93 if (disabled) 94 this.host.disabled = true; 95 } else 96 //call original 97 proceed(value); 98 this.onSetValue(value, old != value, simulate); 99 }.bind(this)); 100 this.host.getValue = this.host.getValue.wrap(function (f, opt) { return opt ? this.getValue(opt) : f(); }.bind(this)); 101 this.host.activate = this.Activate.bind(this); 102 this.host.deactivate = this.Deactivate.bind(this); 103 this.host.enable = this.enable.bind(this); 104 this.host.disable = this.disable.bind(this); 105 this.host.show = this.show.bind(this); 106 this.host.hide = this.hide.bind(this); 107 this.host.Run = this.run.bind(this);
108 this.host.isvalid = function () { return !this.Is('invalid'); }.bind(this); 109 this.host.simulate = this.host.simulate.wrap(function(proceed, name, memo) { 110 if (memo) { 111 var disabled = this.Is('disabled'); 112 if (disabled) 113 this.host.disabled = false; 114 proceed(name, memo); 115 if (disabled) 116 this.host.disabled = true; 117 } else 118 proceed(name); 119 120 }.bind(this)); 121 122 this.on('focus', function (e) { this.Activate(e); }.bind(this)); 123 this.on('blur', function (e) { this.Deactivate(e); }.bind(this)); 124 125 return this; 126 }, 127 onSetValue: function (value, changed, simulate) { 128 //validate 129 this.Validate(value); 130 //simulates the event to call custom handler 131 if (Object.isUndefined(simulate) ? changed : Boolean(simulate)) 132 this.host.simulate('change'); 133 }, 134 setValue: function (value, opt) { 135 //Setting value 136 this.host.setValue(value, opt); 137 }, 138 getValue: function () { 139 //Getting value 140 return this.host.getValue(); 141 }, 142 getText: function (text) { 143 var value = this.host.velue; 144 return value; 145 }, 146 enable: function () { 147 //Customize enable functionality. removes fake "cover" element 148 this.RemoveCss('disabled'); 149 this.host.disabled = false; 150 return this; 151 }, 152 disable: function () { 153 //Customize enable functionality: 154 //NOTE this is not actual disable. Instead, an new element is treated as "cover" to be placed after current field container and disables all user interaction 155 this.AddCss('disabled'); 156 this.host.disabled = true; 157 return this; 158 }, 159 show: function() { 160 this.FieldContainer.show(); 161 }, 162 hide: function() { 163 this.FieldContainer.hide(); 164 }, 165 Activate: function (e) { 166 //Field activation. Do not activate if specific css classes already set 167 if (this.Is('disabled')) 168 return this; 169 this.RemoveCss('invalid').AddCss('active'); 170 return this; 171 }, 172 Deactivate: function (e) { 173 //Field deactivation. A validation is required here 174 // this.stop('blur'); 175 this.RemoveCss('active'); 176 this.Validate(this.host.value); 177 178 if (this.IsChanged()) { 179 this.oldValue = this.getValue(); 180 } 181 182 return this; 183 }, 184 IsChanged: function () { 185 //Verifies if field value has changed () 186 //To be used in derived class 187 return this.oldValue != this.getValue(); 188 }, 189 Validate: function (value) { 190 //Validation. Call custom validation logic from derived class 191 this.RemoveCss('invalid'); 192 var result = Object.isFunction(this.onValidate) ? this.onValidate(value) : true; 193 !result && this.AddCss('invalid'); 194 return result; 195 }, 196 Create: Prototype.emptyFunction, 197 AddCss: function (attr) { 198 //Helper. appends Css class name 199 if (attr && Object.isString(attr)) 200 this.FieldContainer.addClassName(attr); 201 return this; 202 }, 203 RemoveCss: function (attr) { 204 //Helper. removes Css class name 205 this.FieldContainer.removeClassName(attr); 206 return this; 207 }, 208 Is: function (attr) { 209 //Helper. checks if given attribute is set (class or specific value) 210 if (attr == 'visible') 211 return this.FieldContainer.visible(); 212 return this.FieldContainer.hasClassName(attr); 213 }, 214 Submit: function () { 215 if (!Object.isFunction(self.__doPostBack) || !this.Name) 216 return; 217 self.__doPostBack(this.Name, ''); 218 } 219}); 220 221 222Utility.UI.Input = Class.create(Utility.UI.Base, { 223 defaults: function () { 224 return this.options = this.host.getActions({ camelize: true, cast: true }); 225 }, 226 initialize: function ($super) { 227 //Initialize a new instance and create base structure 228 //host - main input field: (<input ....>) 229 try { 230 if (!$super.apply(this, $A(arguments).slice(1))) 231 return false; 232 233 this.host.writeAttribute('autocomplete', 'off'); 234 235 if (this.ishidden = !this.FieldContainer.visible()) 236 this.FieldContainer.setStyle('visibility:hidden;display:inline-block'); 237 238 //calculate 239 this.InputContainer.dimensions = { 240 width: this.InputContainer.measure('border-box-width') || (this.InputContainer.getStyle('width') || '').toNumber(), 241 height: this.InputContainer.measure('border-box-height') || (this.InputContainer.getStyle('height') || '').toNumber(), 242 }; 243 this.InputContainer.setStyle({ position: 'relative' }); 244 245 this.ishidden && this.FieldContainer.setStyle('visibility:inherit;display:none;'); 246 247 248 this.host.insert({ before: this.Activator = new Element('span', {'data-activator': '' }).setStyle('width:100%; height:100%; min-height:#{height};'.interpolate(this.InputContainer.dimensions)) }); 249 250 this.Activator.$stopclick = this.Activator.on('click', function(e) {e.stop();}).stop(); 251 this.Activator.on('dblclick', function (e) { 252 e.stop(); 253 }).stop(); 254 this.on("::deactivate", Event.on(document, 'mousedown', function (e) { 255 var el = Event.element(e); 256 if (el !== this.InputContainer && !el.descendantOf(this.InputContainer)) { // && el !== this.host 257 this.Deactivate(); 258 } 259 }.bindAsEventListener(this))); 260 261 262 } catch (ex) { 263 $alert(ex.message, 'UI::Input Field'); 264 } 265 return this; 266 }, 267 Focus: function (e) { 268 this.host.activate(); 269 }, 270 onSetValue: function (value, changed, simulate) { 271 //validate 272 this.Validate(value); 273 //simulates the event to call custom handler 274 if (Object.isUndefined(simulate) ? changed : Boolean(simulate)) 275 this.host.simulate('change'); 276 this.UpdateActivator(); 277 }, 278 getText: function (text) { 279 var value = this.host.velue; 280 return value; 281 }, 282 Create: function () { 283 //Actual instance creator. To be called by derived class during initialization 284 //Adds base event handlers and options verifiers 285 this.FieldContainer.on('selectstart', function () { return false; }); 286 this.on("toggle", this.InputContainer.on('click', this.Activate.bind(this))); 287 this.on('keydown', this.KeyDown.bindAsEventListener(this)); 288 this.options.length && this.host.writeAttribute('maxlength', this.options.length); 289 if (this.host.disabled = this.host.readAttribute('disabled')) { 290 this.host.disable(); 291 } 292 293 this.setValue(this.oldValue = this.getValue()); 294 295 return this; 296 }, 297 onEnable: function () { 298 this.host.setStyle('visibility:inherit'); 299 this.UpdateActivator(); 300 }, 301 onDisable: function () { 302 this.host.setStyle('visibility:hidden'); 303 this.UpdateActivator(); 304 }, 305 enable: function ($super) { 306 //Customize enable functionality. removes fake "cover" element 307 $super(); 308 this.Activator.$stopclick.stop(); 309 this.onEnable($A(arguments).slice(1)); 310 return this; 311 }, 312 disable: function ($super) { 313 //Customize enable functionality: 314 //NOTE this is not actual disable. Instead, an new element is treated as "cover" to be placed after current field container and disables all user interaction 315 $super(); 316 this.Deactivate(); 317 this.Activator.$stopclick.start(); 318 this.onDisable.apply(this,$A(arguments).slice(1)); 319 return this; 320 }, 321 onActivate: function () { 322 this.UpdateActivator(true); 323 }, 324 onDeactivate: function () { 325 this.UpdateActivator(false); 326 }, 327 Activate: function ($super,e) { 328 $super(); 329 this.oldValue = this.getValue(); 330 this.onActivate(); 331 this.host.focus(); 332 return this; 333 }, 334 Deactivate: function ($super,e) { 335 $super(); 336 this.Validate(this.host.value); 337 this.onDeactivate(); 338 339 if (this.IsChanged()) { 340 this.oldValue = this.getValue(); 341 } 342 343 return this; 344 }, 345 UpdateActivator: Prototype.emptyFunction, 346 KeyDown: function (e) { 347 if (e.keyCode == Event.KEY_RETURN || e.keyCode == Event.KEY_TAB) { 348 e.stop(); 349 this.options.autopostback ? this.Submit() : this.Leave(e); 350 } 351 }, 352 Leave: function (e) { 353 this.Deactivate(e); 354 if (self.form && Object.isFunction(self.form.TabsHandler)) { 355 e.stop(); 356 self.form.TabsHandler(this.host); 357 return; 358 } 359 360 if (!Object.isArray(self.$$inputs)) 361 self.$$inputs = $$('input[tabindex]').collect(function(it) { 362 return it.tabIndex.toNumber() > 0 ? $p(it).identify() : null; 363 }).filter(function(it) { return it; });
364 365 if (!self.$$inputs.length) 366 return; 367 var idx = (e && e.shift) ? Math.max(self.$$inputs.indexOf(this.host.identify()) - 1, 0) : Math.min(self.$$inputs.indexOf(this.host.identify()) + 1, self.$$inputs.length - 1); 368 $p(self.$$inputs[idx]).activate(); 369 370 } 371}); 372 373Utility.UI.LabelField = Class.create(Utility.UI.Input, { 374 initialize: function ($super, host, options) { 375 try { 376 if (!$super.apply(this, $A(arguments).slice(1))) 377 return false; 378 this.Create(); 379 } catch (ex) { 380 $alert(ex.message, 'UI :: Label Field'); 381 } 382 return this; 383 }, 384 onActivate : function($super) { 385 $super(); 386 !this.Is('disabled') && this.host.fire(":activate"); 387 }, 388 UpdateActivator: function () { 389 this.Activator.update(this.getValue()); 390 }, 391}); 392 393Utility.UI.TextField = Class.create(Utility.UI.Input, { 394 initialize: function ($super, host, options) { 395 try { 396 if (!$super.apply(this, $A(arguments).slice(1))) 397 return false; 398 this.Create(); 399 !this.Is('disabled') && this.host.setStyle('visibility:inherit'); 400 this.Deactivate(); 401 } catch (ex) { 402 $alert(ex.message, 'UI :: Text Field'); 403 } 404 return this; 405 }, 406 onValidate: function (value) { 407 if (!value) 408 return true; 409 switch (String(this.options.validate).toLowerCase()) { 410 case "email": 411 return Utility.UI.Validation.IsEmail(value); 412 case "number": 413 return Utility.UI.Validation.IsNumber(value); 414 case "boolean": 415 return Utility.UI.Validation.IsNumber(value); 416 } 417 return true; 418 }, 419 UpdateActivator: function (isactive) { 420 var text = this.host.getValue(); 421 422 text = this.htmlEncode(text); 423 424 if (this.Is('disabled')) { 425 this.Activator.update('<span class="bit">' + text + '</span>').setStyle('visibility:inherit'); 426 return; 427 } 428 if (isactive) { 429 this.host.setStyle('visibility:inherit'); 430 this.Activator.hide(); 431 this.host.focus(); 432 } else { 433 this.host.setStyle('visibility:hidden'); 434 this.Activator.update('<span class="bit #{css}">#{text}</span>'.interpolate({ 435 text: text || this.options.prompt || '', 436 css : !text ? 'placeholder' : '' 437 })).show(); 438 } 439 }, 440 htmlEncode: function (str) { 441 if (typeof str !== "string") return str; 442 return str 443 .replace(/&/g, "&") 444 .replace(/</g, "<") 445 .replace(/>/g, ">") 446 .replace(/"/g, """) 447 .replace(/'/g, "'"); 448 } 449 450}); 451 452Utility.UI.NumberField = Class.create(Utility.UI.Input, { 453 defaults: function ($super) { 454 return this.options = Object.extend($super(), { 455 type: 'number', 456 format: 'N', 457 min: 0, 458 delta: 1, 459 defvalue: 0, 460 allowedit:true 461 }); 462 }, 463 initialize: function ($super, host, options) { 464 if (!$super.apply(this, $A(arguments).slice(1))) 465 return false; 466 this.Activator.writeAttribute('data-activator', 'spinner'); 467 //Assign custom event handlers 468 this.Create(); 469 this.Deactivate(); 470 return this; 471 }, 472 Create: function ($super) { 473 this.on('mousewheel', this.WheelScroll.bindAsEventListener(this)); 474 this.on('click', this.Activator.on('click', this.MouseDown.bind(this))); 475 476 this.min = this.SetLimit(this.options.min); 477 this.max = this.SetLimit(this.options.max); 478 479 $super(); 480 return this; 481 }, 482 getValue: function($super) { 483 var v = $super(); 484 if (v === '' && this.min) 485 v=String(this.min.value); 486 return v.toNumber(); 487 }, 488 setValue: function (value, delta, opt) { 489
490 value = String(value); 491 if (this.min && (value === '' || value == this.min.value || value.toLowerCase() == this.min.text.toLowerCase())) 492 value = this.min.value; 493 else if (this.max && (value == this.max.value || value.toLowerCase() == this.max.text.toLowerCase())) 494 value = this.max.value; 495 else 496 value = value.toNumber(this.min ? this.min.value : 0); 497 498 //value is a number, In case Delta is number inrease value by delta (might be negative) 499 if (Object.isNumber(delta)) { 500 value += delta; 501 } 502 503 this.min != null && (value = Math.max(value, this.min.value)); 504 this.max != null && (value = Math.min(value, this.max.value)); 505 506 this.host.setValue(value.toString()); 507 }, 508 onSetValue: function ($super,value, changed, simulate) { 509 $super(value, changed, simulate); 510 this.UpdateActivator(); 511 }, 512 onEnable: function ($super) { 513 $H(this.events).each(function (it) { 514 it.value.start(); 515 }); 516 this.UpdateActivator(false); 517 }, 518 onDisable: function ($super) { 519 this.UpdateActivator(false); 520 $H(this.events).each(function (it) { 521 it.value.stop(); 522 }); 523 }, 524 onActivate: function ($super) { 525 $super(); 526 527 if (this.options.allowedit) { 528 this.host.value = this.formatValue(this.getValue()); 529 this.Activator[this.Is('active') ? "hide" : "show"](); 530 this.host.setStyle("visibility:inherit" ); 531 this.host.select(); 532 } 533 534 }, 535 onDeactivate: function ($super) { 536 this.host.setStyle("visibility:hidden"); 537 $super(); 538 }, 539 UpdateActivator: function (state) { 540 var text = this.formatValue(this.host.getValue()); 541 if (this.Is('disabled')) { 542 this.Activator.update('<span class="bit">' + text + '</span>'); 543 return; 544 } 545 if (this.Is('active')) { 546 this.host.value = text; 547 this.Activator.hide(); 548 this.host.focus(); 549 550 } else { 551 this.Activator.update('<span class="bit #{css}">#{text}</span><span class="up"></span><span class="down"></span>'.interpolate({ 552 text: text || this.options.prompt || '', 553 css : !text ? 'placeholder' : '' 554 })).show(); 555 } 556 }, 557 SetLimit: function (v) { 558 v = String(v); 559 if (/^-?\d+(\:.*)?/.test(v)) 560 return { 561 value: (v.indexOf(':')>=0 ? v.split(':')[0] : v).toNumber(), 562 text: v.indexOf(':')>=0 ? v.split(':')[1] : v.toNumber().toString(this.options.format) 563 } 564 return null; 565 }, 566 KeyDown: function ($super, e) { 567 var key = e.keyCode; 568 switch (key) { 569 case Event.KEY_UP: 570 this.setValue(this.getValue(), this.options.delta); 571 this.host.select(); 572 e.stop(); 573 break; 574 case Event.KEY_DOWN: 575 this.setValue(this.getValue(), this.options.delta * -1); 576 this.host.select(); 577 e.stop(); 578 break; 579 default: 580 $super(e); 581 break; 582 } 583 }, 584 MouseDown: function (e) { 585 if (e.element().hasClassName('up')) { 586 this.setValue(this.getValue(), this.options.delta); 587 e.stop(); 588 } 589 else if (e.element().hasClassName('down')) { 590 this.setValue(this.getValue(), this.options.delta * -1); 591 e.stop(); 592 } 593 }, 594 WheelScroll: function (e) { 595 if (e.wheelDelta > 0) 596 this.setValue(this.getValue(), this.options.delta); 597 else if (e.wheelDelta < 0) 598 this.setValue(this.getValue(), this.options.delta * -1); 599 e.stop(); 600 }, 601 Validate: function(value) { 602 if (this.min && (value == this.min.value || value.toLowerCase() == this.min.text.toLowerCase())) 603 value = this.min.value; 604 else if (this.max && (value == this.max.value || value.toLowerCase() == this.max.text.toLowerCase())) 605 value = this.max.value; 606 else { 607 value = value.toNumber(this.min ? this.min.value : 0); 608 this.min != null && (value = Math.max(value, this.min.value)); 609 this.max != null && (value = Math.min(value, this.max.value)); 610 } 611 612 this.host.value = value; 613 }, 614 formatValue: function (value, b) { 615 if (this.min && (value == this.min.value || String(value).toLowerCase() == this.min.text.toLowerCase())) 616 value = this.min.text; 617 else if (this.max && (value == this.max.value || String(value).toLowerCase() == this.max.text.toLowerCase())) 618 value = this.max.text; 619 else if (this.options.format) 620 value = value.toNumber(this.min ? this.min.value : 0).toString(this.options.format); 621 return value; 622 } 623}); 624 625Utility.UI.Check = Class.create(Utility.UI.Base, { 626 initialize: function ($super, host, options) { 627 if (!$super.apply(this, $A(arguments).slice(1))) 628 return false; 629 this.host.insert({ after: this.Activator = new Element('label', { 'for': this.host.id }) }); 630 this.setValue(this.oldValue = this.getValue()); 631 632 //IE 5-8 fires the event when the checkbox or radio is blurred, and not when it is activated. 633 //See http://www.quirksmode.org/dom/events/change.html 634 if (/MSIE\s([\d.]+)/.test(navigator.userAgent) && new Number(RegExp.$1) <= 8) 635 this.host.on('click', function () { this.simulate.bind(this).defer('change'); }); 636 637 this.Activator.$stopclick = this.Activator.on('click', function (e) {e.stop();}).stop(); 638 if (this.FieldCaption) { 639 this.FieldCaption.writeAttribute('for', this.host.id); 640 this.FieldCaption.$stopclick = this.FieldCaption.on('click', function (e) { e.stop(); }).stop(); 641 } 642 643 if (this.host.disabled = this.host.readAttribute('disabled')) 644 this.host.disable(); 645 if (this.options.autopostback) { 646 this.on("change", function() { this.Submit(); }.bind(this)); 647 } 648 649 return this; 650 }, 651 getValue: function (opt) { 652 return opt ? { Value: this.host.checked, Text: this.host.getValue() } : this.host.checked; 653 }, 654 enable: function ($super) { 655 //Customize enable functionality. removes fake "cover" element 656 $super(); 657 658 this.Activator.$stopclick.stop(); 659 this.FieldCaption && this.FieldCaption.$stopclick.stop(); 660 return this; 661 }, 662 disable: function ($super) { 663 //Customize enable functionality: 664 $super(); 665 this.Deactivate(); 666 this.Activator.$stopclick.start(); 667 this.FieldCaption && this.FieldCaption.$stopclick.start(); 668 return this; 669 }, 670 671}); 672 673Utility.UI.SelectorInternal = Class.create(Utility.UI.Input, { 674 defaults: function ($super, o) { 675 return this.options = Object.extend($super(o), { 676 layout: 'popup', 677 allowedit: false, 678 allowremove: true, 679 // height: 200, 680 }); 681 }, 682 initialize: function ($super, host, options) { 683 try { 684 if (!$super.apply(this, $A(arguments).slice(1))) 685 return false; 686 this.Activator.writeAttribute('data-activator', 'arrow'); 687 //Add new Web Request object 688 this.WebRequest = new Utility.WebMethodRequest(this); 689 this.Create(); 690 return this; 691 } catch (ex) { 692 $alert(ex.message, 'UI::Field Selector'); 693 } 694 }, 695 onSetValue: function (value, changed, simulate) { 696 // $super(value, changed, simulate); 697 this.Validate(value); 698 //simulates the event to call custom handler 699 this.Selector && this.Selector.setValue(value); 700 this.UpdateActivator(); 701 if (Object.isUndefined(simulate) ? changed : Boolean(simulate)) 702 this.host.simulate('change'); 703 704 }, 705 getValue: function (opt) { 706 var v = this.Selector ? this.Selector.getValue() : { Value: this.host.getValue(), Text: this.host.getValue() }; 707 v = opt ? v : (Object.isArray(v) ? v.pluck('Value').join(',') : v.Value); 708 return v; 709 }, 710 addValue: function (value, opt) { 711 var o = this.getValue(); 712 var a = o.split(','); 713 if (a.include(value)) 714 return; 715 a.push(value); 716 value = a.compact().toString(); 717 o != value && this.setValue(value, opt); 718 }, 719 removeValue: function (value, opt) { 720 var o = this.getValue().toString(); 721 value = (o.split(",")).without(value).toString(); 722 o != value && this.setValue(value, opt); 723 }, 724 getText: function (text) { 725 return this.Selector ? this.Selector.getText(text, this.Is('disabled')) : ''; 726 }, 727 Create: function () { 728 this.FieldContainer.on('selectstart', function () { return false; }); 729 this.on("toggle", this.InputContainer.on('click', this.Activate.bind(this))); 730 this.on('keydown', this.KeyDown.bindAsEventListener(this)); 731 732 this.off('blur'); 733 734 this.Container = this.InputContainer.down('[data-role^="selector"]'); 735 if (!this.Container) 736 throw new Error("Invalid layout"); 737 738 //Move selector container to field fontainer 739 this.InputContainer.insert(this.Container); 740 741 this.host.on(':delete', function (e) { this.Delete(e.memo); }.bind(this)); 742 this.Container.on('click', function (e) { e.stop(); }); 743 744 this.Container.layout = this.Container.getLayout().toObject(); 745 746 747 if (this.options.layout != 'inline') { 748 // adding selector activator to container 749 this.Container.setStyle('position:absolute').hide(); 750 // modify activator 751 this.Activator.setStyle({ 'backgroundColor': this.InputContainer.getStyle('background-color') }); 752 } else { 753 this.InputContainer.addClassName('inline'); 754 this.Activator.hide(); 755 756 } 757 758 this.oldValue = this.getValue(); 759 this.onCreate(); 760 this.setValue(this.oldValue); 761 this.Deactivate(); 762 763 if (this.options.initload) 764 this.Load(this.options.data); 765 766 if (this.options.layout == 'inline') { 767 this.UpdatePosition(true); 768 this.Show(); 769 } 770 if (this.host.disabled = this.host.readAttribute('disabled')) { 771 this.host.disable(); 772 } 773 774 775 return this; 776 }, 777 onCreate: Prototype.emptyFunction, 778 onRequest: Prototype.emptyFunction, 779 onSelect: function (data, done) { 780 if (this.Is('disabled')) { 781 this.setValue(this.oldValue, false); 782 return false; 783 } 784 785 ///April 1, 2015: 786 //Call custom function to do custom validation and update value before value is stored to and input field 787 if (done && Object.isFunction(this.onBeforeChanged)) { 788 //update data only ir result is returned! 789 var ret = this.onBeforeChanged(data); 790 data = Object.isUndefined(ret) ? data : ret; 791 } 792 793 794 var v = ''; 795 if (Object.isArray(data)) { 796 v = data.pluck('Value').join(','); 797 } else if ('Value' in data) { 798 v = data.Value; 799 } 800 this.host.setValue(v, true); 801 802 if (done) { 803// this.Deactivate(); 804 this.options.autopostback ? this.Submit() : this.Leave(); 805 } else { 806 this.UpdateActivator(Object.get(data, 'Text', '')); 807 } 808 809 }, 810 onEnable: function ($super) { 811// this.host.setStyle('visibility:hidden'); 812 //Loads data and update selector 813 this.run("Selector.enable", $A(arguments).slice(1)); 814 815 }, 816 onDisable: function ($super) { 817 this.run("Selector.disable", $A(arguments).slice(1)); 818 }, 819 onActivate: function ($super) { $super(); this.Show(); }, 820 onDeactivate: function ($super) { $super(); this.Hide(); }, 821 Show: function (e) { 822 this.Container.setStyle("visibility:hidden").show(); 823 this.UpdatePosition(); 824 825 //Loads data and update selector 826 this.run("Selector.onShow", this.Container.layout); 827 828 //Check if a popup container is out of viewport area, Thus change its location to "ON TOP" of input field 829 if (this.options.layout != 'inline' && (this.Container.viewportOffset().top + this.Container.getHeight()) > $Screen.viewport.height) { 830 this.Container.setStyle({ top: (this.Container.getHeight() * -1) + 'px' }).addClassName('top'); 831 } 832 833 this.Container.setStyle("visibility:inherit"); 834// this.run("onShow"); 835 return this; 836 }, 837 Hide: function (e) { 838 if (this.Container && this.options.layout != 'inline') { 839 this.Container.removeClassName('top').setStyle("top:-1000px").hide(); 840 } 841 this.run("Selector.onHide"); 842 this.run("onHide"); 843 return this; 844 }, 845 Delete: function (it) { 846 this.removeValue(it.Value); 847 this.Deactivate(); 848 }, 849 Load: function (data, prms) { 850 try { 851 if (Object.isUndefined(data) || data == null) { 852 this.status = 'requesting'; 853 if (this.options.webmethod) { 854 this.Selector && this.Selector.Load('<div style="margin-top:10px;margin-left:10px;">Loading...</div>'); 855 this.WebRequest.Update(this.options.webmethod, Object.extend({ callback: this.Load.bind(this) }, prms || {})); 856 } else { 857 delete this.status; 858 } 859 return; 860 } 861 this.Selector && this.Selector.Load(data); 862 prms && this.setValue(prms.toString()); 863 } catch (ex) { 864 $alert(ex.message, 'Update Selector error.'); 865 } 866 }, 867 UpdatePosition: function (force) { 868 var layout = this.InputContainer.getLayout().toObject(); 869 870 var stylestring; 871 if (this.options.layout == 'inline'){ 872 stylestring = "top:0px;left:0;width:100%;height:100%;"; 873 } else { 874 stylestring = "top:#{top}px;width:#{width}px;height:#{height}px;left:-#{border-left}px;"; 875 layout.top = layout['padding-box-height'];// + layout['border-top']; 876 layout.width = this.options.width || (layout['border-box-width'] - (this.Container.layout['border-box-width'] - this.Container.layout['width'])); 877 layout.height = this.options.height || (layout['border-box-height']-(this.Container.layout['border-box-height'] - this.Container.layout['height'])); 878 } 879 880 this.Container.layout = layout; 881 this.Container.setStyle(stylestring.interpolate(layout)); 882 }, 883 KeyDown: function (e) { 884 if (!this.options.allowedit) { 885 e.stop(); 886 return; 887 } 888 889 //Handle Key Press event 890 switch (e.keyCode) { 891 case Event.KEY_ESC: 892 case Event.KEY_TAB: 893// 894 this.Leave(e); 895 break; 896 case Event.KEY_RETURN: 897 this.Deactivate(e); 898 this.Leave(e); 899 break; 900 } 901 }, 902 UpdateActivator: function (isactive) { 903 if (!this.Selector) 904 return; 905 if (this.options.layout == 'inline') { 906 this.Activator.setStyle('visibility:visible').update(''); 907 } else { 908 909 var text = this.getText(this.options.activator); 910 if (isactive && this.options.allowedit) { 911 this.host.setStyle('visibility:inherit;width:100%;'); 912 this.Activator.hide(); 913 this.host.focus(); 914 } else { 915 this.host.setStyle('visibility:hidden;width:0px;'); 916 this.Activator.updat
916e((text || '<span class="bit #{css}">#{text}</span>').interpolate({ 917 text: this.options.prompt || '', 918 css: !text ? 'placeholder' : '' 919 })).show(); 920 } 921 } 922 if (this.options.allowremove && this.getValue()) 923 this.Activator.childElements().each(function (it) { 924 new Utility.UI.Bit(it, { Parent: this, x: !this.Is('disabled') }); 925 }, this); 926 } 927}); 928 929Utility.UI.AutoComplete = Class.create(Utility.UI.SelectorInternal, { 930 defaults: function ($super) { 931 return this.options = Object.extend($super(), { 932 data: [], 933 delay: .5, 934 limit: 0, 935 visibleitems: 7, 936 ActiveIndex: -1, 937 allowedit: true, 938 height: 200 939 }); 940 }, 941 Change: Prototype.emptyFunction, 942 onCreate: function ($super) { 943 944 //Disable a progress message for web requests 945 this.progressMessage = undefined; 946 if (!(this.host.textfield = this.host.next('input[data-text]'))) 947 this.host.insert({ 948 after: this.host.textfield = new Element('input', { type: 'text', tabindex: -1, autocomplete: 'off' }) 949 .update(this.options.textvalue || '') 950 }); 951 this.host.writeAttribute('data-text', this.host.textfield.getValue()); 952 this.host.textfield.identify(); 953 this.host.textfield.setStyle('position:absolute;left:0;width:99%; width:#{0}px;'.interpolate([this.host.getWidth() - 4])); 954 this.host.textfield.writeAttribute('autocomplete', 'off'); 955 this.off('blur'); 956 //Keyboard events 957 this.host.textfield.on('keyup', this.KeyUp.bindAsEventListener(this)); 958 this.host.textfield.on(window.opera ? 'keypress' : 'keydown', this.KeyDown.bindAsEventListener(this)); 959 960 if (!Utility.UI.ListSelector) 961 return; 962 963 this.Selector = new Utility.UI.ListSelector(this.Container, this.options, { 964 Parent: this, 965 onSelect: this.onSelect.bind(this) 966 }); 967 this.oldValue = this.getValue(); 968 969 }, 970 onHide: function () { 971 this.run('Selector.Load', ''); 972 }, 973 onActivate: function () { 974 //Text box activation. Handle a case of hiding a prompt message 975 this.host.textfield.setStyle('visibility:inherit'); 976 this.host.textfield.data = this.getValue(); 977 this.UpdateActivator(true); 978 this.DoAction(this.host.textfield.getValue().length > this.options.limit); 979 }, 980 onDeactivate: function ($super) { 981 //Text box activation. Handle a case of hiding a prompt message 982 $super(); 983 this.host.textfield && this.host.textfield.setStyle('visibility:hidden'); 984 }, 985 onSetValue: function (value, changed, simulate) { 986 //simulates the event to call custom handler 987 if (Object.isUndefined(simulate) ? changed : Boolean(simulate)) 988 this.host.simulate('change'); 989 }, 990 onSelect: function (data, done) { 991 if (done) { 992 delete this.host.textfield.data; 993 this.setValue(data); 994 this.Deactivate(); 995 this.options.autopostback ? this.Submit() : this.Leave(); 996 } else { 997 this.host.textfield.data = data; 998 this.host.textfield.setValue(Object.get(data, 'Text', '')); 999 this.host.textfield.select(); 1000 } 1001 }, 1002 getValue: function ($super) { 1003 var data = { 1004 Value: this.host.getValue() 1005 }; 1006 if (this.Selector) 1007 data.Text = this.host.readAttribute('data-text'); 1008 return data; 1009 }, 1010 updateValue: function (value, text) { 1011 this.host.writeAttribute('data-text', text); 1012 this.host.setValue(value); 1013 }, 1014 setValue: function (data) { 1015 this.updateValue(Object.get(data, 'Value', ''), Object.get(data, 'Text', '')); 1016 this.host.textfield.setValue(Object.get(data, 'Text', '')); 1017 this.Validate(data || {}); 1018 this.UpdateActivator(); 1019 }, 1020 IsChanged: function () { 1021 var v = this.getValue(); 1022 return this.oldValue && (this.oldValue.Text != v.Text || this.oldValue.Value != v.Value); 1023 }, 1024 DoAction: function () { 1025 if (!this.options.webmethod) 1026 return; 1027 if (this.host.textfield.value.length >= Math.max(this.options.limit, 0)) { 1028 this.onActionInterval && clearInterval(this.onActionInterval); 1029 //Stops any other request 1030 this.WebRequest.Stop(); 1031 // see this.onRequest(this); to modify parameters 1032 this.WebRequest.Update(this.options.webmethod, Object.extend({ callback: 'Complete', filter: this.host.textfield.getValue() }, this.parameters || {})); 1033 } 1034 }, 1035 Delete: function () { 1036 this.onSelect(null, true); 1037 }, 1038 Complete: function () { 1039 //Override. Checks and updates popup container. If there is no items to select close popup with delay 1040 if (this.Selector.Load($A(arguments), this.host.textfield.value)) 1041 this.Show(); 1042 else 1043 this.Hide(); 1044 }, 1045 KeyUp: function (e) { 1046 //Handle KeyUp event 1047 var clear = false; 1048 switch (e.keyCode) { 1049 case Event.KEY_UP: 1050 case Event.KEY_DOWN: 1051 !this.Container.visible() && this.DoAction(); 1052 return; 1053 case Event.KEY_ESC: 1054 case Event.KEY_TAB: 1055 case Event.KEY_RETURN: 1056 return; 1057 case Event.KEY_DELETE: 1058 case Event.KEY_BACKSPACE: 1059 clear = true; 1060 break; 1061 default: 1062 clear = e.char; 1063 1064 } 1065 if (clear) { 1066 delete this.host.textfield.data;
1067 this.updateValue('', ''); 1068 } 1069 //delay is broken. set it to 1 second as user type. it's causing too many ajax requests killing server and db 1070 this.delay = 1; 1071 1072 if (Object.isNumber(this.delay) && this.delay) { 1073 this.onActionInterval = this.DoAction.bind(this).delay(this.delay); 1074 } else { 1075 this.DoAction(); 1076 } 1077 1078 }, 1079 KeyDown: function (e) { 1080 //Handle Key Press event (IE specific) 1081 // return will exit the function 1082 // and event will not fire 1083 switch (e.keyCode) { 1084 case Event.KEY_ESC: 1085 this.onSelect(this.oldValue, true); 1086 break; 1087 1088 case Event.KEY_TAB: 1089 case Event.KEY_RETURN: 1090 Event.stop(e); 1091 this.onSelect(this.host.textfield.data, true); 1092 break; 1093 1094 case Event.KEY_UP: 1095 Event.stop(e); 1096 this.run('Selector.Up'); 1097 break; 1098 case Event.KEY_DOWN: 1099 Event.stop(e); 1100 this.run('Selector.Down'); 1101 break; 1102 default: 1103 break; 1104 1105 } 1106 }, 1107 UpdateActivator: function (state) { 1108 var data = this.getValue(); 1109 if (this.Is('disabled')) { 1110 this.Activator.update('<span class="#{css}">#{text}</span>'.interpolate({ 1111 text: data.Text, 1112 css: (data.Value ? 'bit ' : '') 1113 })); 1114 return; 1115 } 1116 if (state) { 1117 this.Activator.setStyle('visibility:hidden'); 1118 this.host.textfield.select(); 1119 } else { 1120 this.Activator.setStyle('visibility:inherit'); 1121 this.Activator.update('<span class="#{css}">#{text}</span>'.interpolate({ 1122 text: data.Text || this.options.prompt || '', 1123 css: !data.Text ? 'placeholder' : (data.Value ? 'bit ':'') 1124 })); 1125 } 1126 if (this.options.allowremove && data.Value && data.Text) 1127 new Utility.UI.Bit(this.Activator.down(), { Parent: this, x: !this.Is('disabled') }); 1128 } 1129}); 1130 1131Utility.UI.ListField = Class.create(Utility.UI.SelectorInternal, { 1132 defaults: function ($super) { 1133 return this.options = Object.extend($super(), { 1134 type: 'list', 1135 height: 250, 1136 allowremove: false 1137 }); 1138 }, 1139 onCreate: function ($super) { 1140 if (!Utility.UI.ListSelector) 1141 return; 1142 // this.host.addClassName('hidden'); 1143 this.Selector = new Utility.UI.ListSelector(this.Container, this.options, { 1144 Parent: this, 1145 defaultValue: arguments[1], 1146 onSelect: this.onSelect.bind(this) 1147 }); 1148 } 1149}); 1150 1151Utility.UI.TreeField = Class.create(Utility.UI.SelectorInternal, { 1152 defaults: function ($super) { 1153 return this.options = Object.extend($super(), { 1154 type: 'selector', 1155 allowremove: false 1156 }); 1157 }, 1158 enable: function ($super) { 1159 //Customize enable functionality. removes fake "cover" element 1160 if (arguments.length == 1) 1161 $super(); 1162 else { 1163 this.onEnable($A(arguments).slice(1)); 1164 } 1165 return this; 1166 }, 1167 disable: function ($super) { 1168 if (arguments.length == 1) 1169 $super.apply(this, this.Selector.getValues()); 1170 else { 1171 this.onDisable($A(arguments).slice(1)); 1172 } 1173 return this; 1174 }, 1175 onSelect: function ($super,data, done) { 1176 $super(data, done); 1177 if (this.Is('disabled')) 1178 return; 1179 if (!done) 1180 this.UpdatePosition(this.options.layout != 'inline'); 1181 }, 1182 1183 onCreate: function (e) { 1184 this.options.active = []; 1185 if (!Utility.UI.TreeSelector) 1186 return; 1187 this.Selector = new Utility.UI.TreeSelector(this.Container, this.options, { 1188 Parent: this, 1189 onSelect: this.onSelect.bind(this) 1190 }); 1191 }, 1192 IsChanged: function () { 1193 return this.oldValue != this.getValue(); 1194 } 1195}); 1196 1197Utility.UI.DateField = Class.create(Utility.UI.SelectorInternal, { 1198 //options: 1199 //stick 1200 defaults: function ($super) { 1201 return this.options = Object.extend($super(), { 1202 type: 'date', 1203 allowedit: false, 1204 allowremove: false, 1205 height: 220, 1206 width: 220 1207 }); 1208 }, 1209 onCreate: function (value) { 1210 if (!Utility.UI.DatePicker) 1211 return; 1212 this.Selector = new Utility.UI.DatePicker(this.Container, this.options, { 1213 Parent: this, 1214 selected: this.getValue(), 1215 onSelect: this.onSelect.bind(this) 1216 }); 1217 if (this.options.allowedit) 1218 //Restore event handlers 1219 this.start('focus', 'toggle'); 1220 1221 }, 1222 onValidate: function (data) { 1223 if (!data) 1224 return true; 1225 return !isNaN(new Date(data)); 1226 } 1227}); 1228 1229Utility.UI.TimeField = Class.create(Utility.UI.SelectorInternal, { 1230 defaults: function ($super) { 1231 return this.options = Object.extend($super(), { 1232 type: 'time', 1233 allowedit: false, 1234 allowremove: false, 1235 height: 250, 1236 width: 250 1237 }); 1238 }, 1239 onCreate: function (value) { 1240 if (!Utility.UI.TimePicker) 1241 return; 1242 this.Selector = new Utility.UI.TimePicker(this.Container, this.options, { 1243 Parent: this, 1244 selected: this.getValue(), 1245 onSelect: this.onSelect.bind(this) 1246 }); 1247 if (this.options.allowedit) 1248 //Restore event handlers 1249 this.start('focus', 'toggle'); 1250 1251 }, 1252 onValidate: function (data) { 1253 if (!data) 1254 return true; 1255 var date = new Date(); 1256 // autocomplete entered value for different cases 1257 if (/^\d{1,2}$/.test(data)) 1258 date = date.add('h', data).add('min', '0'); 1259 else if (/^\d{3,4}$/.test(data)) { 1260 var a = (data.substring(0, data.length - 2) + ':' + data.substring(data.length - 2)).split(':'); 1261 date = date.add('h', a[0]).add('min', a[1]); 1262 } else if (/^\d{1,2}:\d{0,2}$/.test(data)) { 1263 var a = data.split(':'); 1264 date = date.add('h', a[0]).add('min', a[1]); 1265 } else if (/^(0?[1-9]|1[012])(\ ?[AaPp][Mm]*)$/.test(data)) { 1266 var a = data.toNumber() + (/p/.test(data) ? 12 : 0); 1267 date = date.add('h', a.toString()).add('min', '0'); 1268 } else if (/^(0?[1-9]|1[012])(:[0-5]\d){0,2}(\ ?[AaPp][Mm]*)$/.test(data)) { 1269 date = date.setTime((data + (/[Mm]$/.test(data) ? '' : 'M')).toUpperCase()); 1270 } else if (/^(0?\d|[1]\d|2[0-3])(:[0-5]\d){0,2}$/.test(data)) 1271 date = date.setTime(data); 1272 else 1273 return false; 1274 if (this.Selector) 1275 this.host.value = date = date.toString(this.Selector.options.format); 1276 return isNaN(date); 1277 }, 1278 onActivate: function ($super) { 1279 $super(); 1280 if (this.options.allowedit) { 1281 this.host.setStyle('visibility:inherit'); 1282 this.Activator.setStyle('visibility:hidden'); 1283 this.host.select(); 1284 } 1285 1286 }, 1287 onDeactivate: function ($super) { 1288 $super(); 1289 if (this.options.allowedit) { 1290 this.host.setStyle('visibility:hidden'); 1291 this.Activator.setStyle('visibility:inherit'); 1292 this.onSetValue(this.host.value, true); 1293 } 1294 } 1295}); 1296 1297 1298Utility.UI.ColorField = Class.create(Utility.UI.SelectorInternal, { 1299 defaults: function ($super) { 1300 return this.options = Object.extend($super(), { 1301 width: 250, 1302 height: 250 1303 /* 1304 tilewidth: 20, 1305 tileheight: 20, 1306 */ 1307 }); 1308 }, 1309 onCreate: function (e) { 1310 this.options.allowremove = false; //!IMPORTANT 1311 if (!Utility.UI.ColorPicker) 1312 return; 1313 1314 this.Selector = new Utility.UI.ColorPicker(this.Container, this.options, { 1315 Parent: this, 1316 onSelect: this.onSelect.bind(this) 1317 }); 1318 this.host.simulate('change'); 1319 } 1320}); 1321 1322/*Second version of inline edit. 1323NOTE::(Aug 29, 2013, (DL)) the old version used by PlayerSelector and will be updated to new verson after Events 2.0 release 1324*/ 1325Utility.UI.TextEdit = Class.create(Utility.Base, { 1326 initialize: function ($super) { 1327 if (!$super.apply(this, $A(arguments).slice(1))) 1328 return false; 1329 this.host.setStyle('visibility:hidden'); 1330 this.container = this.host.insert(this.Layout()).down('[data-role="textedit"]'); 1331 if (this.Input = this.container.down('input')) { 1332 if (this.SaveButton = this.container.down('[data-action="save"]')) { 1333 this.SaveButton[this.options.save ? 'show' : 'hide']().on('click', this.Close.bind(this)); 1334 } 1335 if (this.CancelButton = this.container.down('[data-action="cancel"')) 1336 this.CancelButton.on('click', this.Cancel.bind(this)); 1337 this.on(window.opera ? 'keypress' : 'keydown', this.keyDown.bindAsEventListener(this)); 1338 this.on(document.on("mousedown", this.Exit.bindAsEventListener(this))); 1339 this.container.clonePosition(this.host); 1340 this.Input.activate(); 1341 } 1342 return true; 1343 }, 1344 Layout: function () { 1345 return ('<div data-role="textedit" style="position:absolute;visibility:visible;">' + 1346 '<input type="text" value="#{value}" maxlength="#{options.length}" style="width:100%;height:100%;"/>' + 1347 '<span style="position:absolute; right:0px; top:0px;"><span data-role="button" data-action="save" class="icon save"></span><span data-role="button" data-action="cancel" class="icon cancel"></span></span>' + 1348 '</div>').interpolate(this); 1349 }, 1350 //Handle Key Press event (IE specific) 1351 keyDown: function (e) { 1352 // return will exit the function 1353 // and event will not fire 1354 switch (e.keyCode) { 1355 case Event.KEY_ESC: 1356 this.Cancel(); 1357 break; 1358 case Event.KEY_TAB: 1359 case Event.KEY_RETURN: 1360 this.Save(); 1361 return; 1362 default: 1363 return; 1364 } 1365 e.stop(); 1366 }, 1367 Save: function () { this.Close('save'); }, 1368 Cancel: function () { this.Close('cancel'); }, 1369 Exit: function (e) { 1370 var el = e.element(); 1371 if (el !== this.container && !el.descendantOf(this.container) && el !== this.host) { this.Save(); } 1372 }, 1373 onClose: function (data) { this.Parent.fire('edit:end', data); }, 1374 Close: function (state) { 1375 var data = { state: state || '', value: this.Input.getValue() }; 1376 this.off(); 1377 this.container.remove(); 1378 this.host.setStyle('visibility:inherit'); 1379 this.onClose(data); 1380 } 1381}); 1382 1383 1384Utility.UI.Collapsable = Class.create({ 1385 initialize: function (host) { 1386 this.host = $p(host); 1387 if (this.host && this.host.childElements().length > 1) { 1388 this.data = this.host.getActions(); 1389 1390 this.anchor = this.host.down(); 1391 this.state = this.anchor.siblings().first().visible(); 1392 this.anchor.text = this.anchor.getInnerText(); 1393 this.anchor.alttext = this.data.alttext || this.anchor.getInnerText(); 1394 1395 1396 this.host.toggle = this.host.toggle.wrap(function (proceed, state) { 1397 if (Object.isUndefined(state)) 1398 proceed(); 1399 else { 1400 this.host.removeClassName('collapsed').addClassName(Boolean(state) ? 'collapsed' : ''); 1401 this.anchor.update(Boolean(state) ? this.anchor.alttext : this.anchor.text); 1402 this.anchor.siblings().invoke(Boolean(state) ? 'show' : 'hide'); 1403 } 1404 }.bind(this)); 1405 this.host.toggle(Boolean(this.state)); 1406 this.anchor.on('click', function (e) { 1407 e.stop(); 1408 this.host.toggle(this.state = !this.state); 1409 }.bind(this)); 1410 } 1411 return this; 1412 1413 } 1414}); 1415 1416 1417Utility.UI.ColorPicker = Class.create(Utility.Base, { 1418 initialize: function ($super, host, options) { 1419 1420 if (!$super.apply(this, $A(arguments).slice(1))) 1421 return false; 1422 this.host.insert(this.Colours = new Element('div', { 'data-role': 'colorpicker' })); 1423 // this.Colours.on('mouseover', this.Select.bindAsEventListener(this)); 1424 this.Colours.on('click', this.Select.bindAsEventListener(this, true)); 1425 return this; 1426 }, 1427 Cell: function (r, g, b) { 1428 var css = { width: this.options.tilewidth + 'px', height: this.options.tileheight + 'px' }; 1429 css.backgroundColor = (r && g && b) ? "#" + r + g + b : (r && r[0] == "#" ? r : ''); 1430 var c = new Element('div').setStyle(css).writeAttribute("data-color", css.backgroundColor); 1431 return c; 1432 }, 1433 Create: function (data) { 1434 data = data || { schema: 'standard' }; 1435 this.Colours.update(); 1436 1437 if (Object.isArray(data.colors) && String(data.schema).include('custom')) { 1438 data.colors.push(''); 1439 data.colors = data.colors.uniq(); 1440 data.colors.each(function (it) { 1441 this.Colours.insert(this.Cell(it).setStyle(String(data.style))); 1442 }, this); 1443 this.Colours.insert(new Element('div', { className: 'clear' })); 1444 } 1445 if (String(data.schema).include('standard')) { 1446 var h = ["00", "00", "11", "22", "33", "44", "55", "66", "77", "88", "99", "AA", "BB", "CC", "DD", "EE", "FF", ""], 1447 d = ["00", "33", "66", "99", "CC", "FF"], r, g, b; 1448 for (r = 0; r < 18; r++) { 1449 this.Colours.insert(this.Cell(h[r], h[r], h[r])); 1450 } 1451 this.Colours.insert(new Element('div', { className: 'clear' })); 1452 1453 1454 for (b = 0; b < 6; b++) { 1455 for (r = 0; r < 3; r++) 1456 for (g = 0; g < 6; g++) 1457 this.Colours.insert(this.Cell(d[r], d[g], d[b])); 1458 this.Colours.insert(new Element('div', { className: 'clear' })); 1459 } 1460 this.Colours.insert(new Element('div', { className: 'clear' })); 1461 1462 for (b = 0; b < 6; b++) { 1463 for (r = 3; r < 6; r++) 1464 for (g = 0; g < 6; g++) 1465 this.Colours.insert(this.Cell(d[r], d[g], d[b])); 1466 this.Colours.insert(new Element('div', { className: 'clear' })); 1467 } 1468 } 1469 }, 1470 Load: function (data, opt) { 1471 this.data = data; 1472 this.Parent.setValue(Object.get(data, 'select', '')); 1473 }, 1474 Select: function (e, done) { 1475 this.selectedColor = e.element().readAttribute('data-color'); 1476 this.onSelect(this.getValue(), done); 1477 }, 1478 onSelect: Prototype.emptyFunction, 1479 onShow: function (dim) { 1480 //!!make container bigger!!!! to adjust by inner dimension after creation 1481 this.Parent.Container.setStyle('height: 1000px;width: 1000px'); 1482 this.Create(this.data); 1483 this.Parent.Container.setStyle({ 1484 height: this.Colours.measure('margin-box-height') + 'px', 1485 width: this.Colours.measure('margin-box-width') + 'px' 1486 }); 1487 }, 1488 onHide: function () { 1489 this.Colours.update(''); 1490 }, 1491 setValue: function (value) { 1492 this.selectedColor = value; 1493 }, 1494 getValue: function (def) { 1495 return { Value: this.selectedColor || '', Text: this.selectedColor || '' }; 1496 }, 1497 getText: function (msg) { 1498 var v = this.getValue(); 1499 v.Contrast = v.Value ? Utility.RGB.toContrast(v.Value) : "#000"; 1500 v.msg = msg || v.Value; 1501 return '<span class="bit" style="" data-value="#{Value}"><span style="background-color:
1501#{Value};color:#{Contrast};">#{msg}</span></span>'.interpolate(v); 1502 }, 1503}); 1504 1505 1506//-----------------------------------------------------------------------------\dlo/ 1507// CHO.Input.Tree Control v1.0 1508// Jonas Software © 2013, by Dmitry Lopyrev 1509//----------------------------------------------------------------------------- 1510// Shows UL structure as TreeView controld width node selection 1511//----------------------------------------------------------------------------- 1512// Note: Requires Prototype JS library (v.1.7.1 - modified) and Utility.js 1513//----------------------------------------------------------------------------- 1514 1515 1516 1517Utility.UI.TreeSelector = Class.create(Utility.Base, { 1518 defaults: function () { 1519 this.options = Object.extend({ 1520 horizontal: false, 1521 lines: false, 1522 collapsed: true, 1523 checkbox: '', 1524 bittemplate: '<span class="bit" style="#{style}" data-value="#{Value}" data-text="#{Text}">#{Text}</span>', 1525 multiple: false, 1526 text: '', 1527 selectall:'', //Text to use 'Select All' functionali 1528 }, this.host.getActions({ camelize: true, cast: true })); 1529 }, 1530 onSelect: Prototype.emptyFunction, 1531 initialize: function ($super, host, options) { 1532 try { 1533 1534 if (!$super.apply(this, $A(arguments).slice(1))) 1535 return false; 1536 1537 if (Object.isBoolean(this.options.checkbox)) 1538 this.options.checkbox = this.options.checkbox === true ? 'check' : 'radio'; 1539 if (this.options.checkbox === 'radio') 1540 this.options.multiple = false; 1541 else if (this.options.checkbox === 'check') 1542 this.options.multiple = true; 1543 1544// this.host.addClassName('ps-tree'); 1545 this.options.horizontal && this.host.addClassName('horizontal'); 1546 1547 if (!this.NameContainer) 1548 this.host.insert(this.NameContainer = new Element('ul')); 1549 1550 this.Load(); 1551 1552 this.Parent && this.setValue(this.Parent.host.getValue()); 1553 1554 return this; 1555 1556 } catch (er) { 1557 $alert(er.message, 'Tree Picker error'); 1558 } 1559 return this; 1560 }, 1561 getValues: function () { 1562 var data = this.Children.invoke("collectNodes", true).flatten().pluck('data').pluck('Value'); 1563 return data; 1564 }, 1565 1566 getValue: function () { 1567 var data = this.Children.invoke("collectNodes", true).flatten(); 1568 data = data.filter(function (it) { 1569// return !it.Children && it.data.Checked == 2; 1570 return it.data.Checked; 1571 }); 1572 return data.pluck('data'); 1573 }, 1574 setValue: function (values, state) { 1575 if (!Object.isArray(values)) { 1576 values = values ? String(values).split(',') : []; 1577 } 1578 (this.Children || []).invoke("setValue", values, state); 1579 1580 this.Refresh(values); 1581 }, 1582 formatBits: function (data, separator) { 1583 1584 var text = data.collect(function (it) { 1585 return this.options.bittemplate.interpolate(it).trim(); 1586 }, this); 1587 return text.join(this.options.allowremove ? '' : (separator || '')).toString(); 1588 }, 1589 getText: function (text, disabled) { 1590 var data = this.Children.invoke("collectNodes", true).flatten().filter(function (it) { return !it.Children; }).pluck('data'); 1591 var selected = data.filter(function (it) { return it.Checked == 2; }); 1592 1593 if (Object.isString(text)) 1594 if (text.startsWith('|')) { 1595 text = (text + '||').split('|'); 1596 var counter = 'none'; 1597 if (data.length > 0 && data.length == selected.length) 1598 return text[3] || 'All'; 1599 else if (selected.length) { 1600 var parts = /^(\d+:)?(.+)/.exec(text[2]); 1601 parts[1] = Object.isUndefined(parts[1]) ? '0' : parts[1]; 1602 if (selected.length > parts[1].toNumber()) { 1603 return this.formatBits(selected.slice(0, parts[1].toNumber()), ',') + parts[2]; 1604 } 1605 return this.formatBits(selected, ', '); 1606 } 1607 return text[1] || this.options.propmpt || ''; 1608 } else 1609 return text; 1610 1611 return this.formatBits(selected, disabled ? ',' : ''); 1612 },
1613 updateValue: function (state) { 1614 var selected = this.getValue(true); 1615 if (!Object.isUndefined(state)) 1616 this.onSelect(selected, this.options.autopostback || !state); 1617 }, 1618 1619 disable: function (values) { 1620 if (values) { 1621 values = Object.isArray(values) ? values : String(values).split(','); 1622 this.Children.invoke("collectNodes", true).flatten().filter(function(it) { 1623 return values.include(it.data.Value); 1624 }).invoke('disable'); 1625 } else { 1626 (this.Children || []).invoke("disable"); 1627 } 1628 }, 1629 enable: function(values) { 1630 if (values) { 1631 values = Object.isArray(values) ? values : String(values).split(','); 1632 this.Children.invoke("collectNodes", true).flatten().filter(function(it) { 1633 return values.include(it.data.Value); 1634 }).invoke('enable'); 1635 } else { 1636 (this.Children || []).invoke("enable"); 1637 } 1638 }, 1639 Load: function (html) { 1640 try { 1641 //accepts only a text (html) 1642 if (Object.isString(html)) { 1643 (this.Children || []).invoke('dispose'); 1644 delete this.Children; 1645 this.NameContainer.remove(); 1646 this.host.update(html); 1647 } 1648 if (!(this.NameContainer = this.host.down('ul'))) 1649 this.host.insert(this.NameContainer = new Element('ul')); 1650 1651 !this.Children && (this.Children = this.NameContainer.childElements().inject([], function (o, it) { 1652 if (it.tagName == 'LI') { 1653 var a = new Utility.UI.TreeSelector.Node(it, { options: this.options, Tree: this }); 1654 a.GUID = new Date(); 1655 o.push(a); 1656 } 1657 return o; 1658 }, this) || []); 1659 this.data = this.Children.invoke("collectNodes", true).flatten().filter(function (it) { return !it.Children; }).pluck('data'); 1660 1661 // April 1, 2015 1662 // Add "Select all" chekbox if needed 1663 if (this.options.multiple && this.options.selectall) { 1664 1665 this.NameContainer.insert({ before: '<div class="item all"><span class="xti check"></span><a href="javascript:void(0);" unselectable="on">#{selectall}</a></div>'.interpolate(this.options) }); 1666 //find an element 1667 if (this.ALL = this.host.down('.item.all')) { 1668 // WEB-426: add support for disabled items 1669 this.ALL.MaxItems = this.data.filter(function (it) { return !it.Disabled || it.Checked; }); 1670 this.ALL.MinItems = this.data.filter(function (it) { return it.Disabled && it.Checked; }); 1671 var maxItemsValue = this.ALL.MaxItems.pluck('Value').join(','); 1672 var minItemsValue = this.ALL.MinItems.pluck('Value').join(','); 1673 //assign onclick event 1674 this.ALL.on('click', function() { 1675 //get current state state 1676 var checked = this.ALL.hasClassName('partial|checked'); 1677 //toggle state 1678 this.setValue(checked ? minItemsValue : maxItemsValue); 1679 this.updateValue(true); 1680 }.bind(this)); 1681 } 1682 } 1683 1684 } catch (ex) { 1685 $alert(ex.message, 'Tree Selector load error.'); 1686 } 1687 1688 }, 1689 Refresh: function (selected) { 1690 //April 1, 2015 1691 //refreshes state of "Check All" checkbox if exists (unchecke, checked, partially checked) 1692 if (this.ALL) { 1693 this.ALL.removeClassName('checked|partial'); 1694 if (Object.isArray(selected) && selected.length) { 1695 // WEB-426: set state according to number of selected items 1696 if (selected.length == this.ALL.MaxItems.length) 1697 this.ALL.addClassName('checked'); 1698 else if (selected.length != this.ALL.MinItems.length) 1699 this.ALL.addClassName('partial'); 1700 } 1701 } 1702 }, 1703}); 1704Utility.UI.TreeSelector.Node = Class.create(Utility.Base, { 1705 initialize: function ($super) { 1706 1707 if (!$super.apply(this, $A(arguments).slice(1))) 1708 return false; 1709 1710 this.Text = this.host.down('a'); //first child 1711 this.data = this.host.getActions({ camelize: true, cast: true }, { Text: this.Text.getInnerText() }); 1712 //if data contains "Indpendent" - the item can be check/unckeck without changing its parent 1713 if ('Independent' in this.data) { 1714 this.Independent = this.data.Independent; 1715 delete this.data.Independent; 1716 } 1717 1718 if ('Color' in this.data) { 1719 this.data.style = "background-color:#{0}; color:#{1};".interpolate([this.data.Color, Utility.RGB.toContrast(this.data.Color)]); 1720 } 1721 1722 //Validate and convert data 1723 this.data.Checked = /true/i.test(String(this.data.Checked)) ? 2 : 0; 1724 1725 if (this.Children = this.collectChildren(this.host.down('ul'))) { 1726 if (!this.options.multiple) 1727 this.data.group = true; 1728 } 1729 this.NameContainer = this.buildContainer(this.host.down(), !this.options.multiple && this.Children ? null : this.options.checkbox, this.data.Disabled); 1730 1731 //hide item if 'hidden' state is set 1732 this.host.toggle(!Boolean(this.data.Hidden)); 1733 1734 this.on(this.NameContainer.on('click', this.mouseAction.bind(this))); 1735 this.NameContainer.on('dblclick', function(e) { e.stop(); }); 1736 1737 1738 return this; 1739 }, 1740 dispose: function () { 1741 this.off(); 1742 (this.Children || []).invoke('dispose'); 1743 }, 1744 collectChildren: function (container) { 1745 // Collects all children (<LI> element) and create Node instances and Trees 1746 if ((container = $p(container), !container || container.tagName != 'UL')) 1747 return null; 1748 1749 this.GroupContainer = container; 1750 1751 var collection = container.childElements().inject([], function (o, it) { 1752 if (it.tagName == 'LI') { 1753 o.push(new Utility.UI.TreeSelector.Node(it, { Parent: this, options: this.options, Tree: this.Tree })); 1754 } 1755 return o; 1756 }, this); 1757 1758 return collection.length ? collection : undefined; 1759 }, 1760 buildContainer: function (it, check, disabled) { 1761 //Create container and all connectors 1762 it.writeAttribute("unselectable", "on"); 1763 this.Container = new Element('span', { className: 'item ' + (disabled ? 'disabled' : '') }); 1764 check && this.Container.insert({ top: this.Checkbox = new Element('span', { className: 'xti ' + check }) }); 1765 var node = this; 1766 //NOTE:: create image connectors 1767 do { 1768 var siblings = node.host.up().childElements() || []; 1769 var hasChildren = node.host.down('ul'); 1770 var cls = "X"; 1771 var isLast = siblings.indexOf(node.host) == siblings.length - 1; 1772 if (this.options.lines) { 1773 if (node.host === this.host) 1774 cls = (isLast ? "L" : "T") + (hasChildren ? "-group" : ""); 1775 else 1776 cls = isLast ? "B" : "I"; 1777 } 1778 1779 var img = new Element('span', { className: 'xti ' + cls }); 1780 this.Container.insert({ top: img }); 1781 if (/-group/i.test(cls)) { 1782 this.Connector = img; 1783 this.host.addClassName(this.data.collapsed || this.options.collapsed ? "collapsed" : ""); 1784 } 1785 node = node.Parent; 1786 } while (node) 1787 1788 it.wrap(this.Container); 1789 if (this.data.style) { 1790 it.setStyle(this.data.style); 1791 } 1792 1793 return this.Container; 1794 }, 1795 collectNodes: function (opt) { //true 1796 // Recursively collects all children. 1797 // Parameters: (optional): opt : "false" - olny children; "true" - children and their parents 1798 // Returns flat array 1799 var result = []; 1800 if (opt || !this.Children) 1801 result = [this].concat(result); 1802 if (this.Children) 1803 result = result.concat(this.Children.invoke("collectNodes", opt).flatten()); 1804 return result; 1805 }, 1806 getState: function () { 1807 var states = this.collectNodes().collect(function (it) { return it.data.Checked; }); 1808 var sum = states.inject(0, function (o, it) { return (o = o + it, o); }); 1809 var state = (sum > 0 && sum < states.length * 2) ? 1 : (sum == 0) ? 0 : 2; 1810 if (this.Independent) { 1811 return state || this.data.Checked; 1812 } 1813 return state; 1814 }, 1815 getValues: function (opt) { 1816 return this.collectNodes().collect(function (it) { 1817 return opt ? (it.data.Checked ? it.data.Value : null) : it.data.Value; 1818 }); 1819 }, 1820 getValue: function (opt) { 1821 // Gets a list of selected nodes 1822 // Parameters: (optional): opt : "false" - olny checked; "true" - checked and partially checked 1823 // Returns flat array 1824 return this.collectNodes(opt).collect(function (it) { 1825 return it.data.Checked ? it.data : null; 1826 }); 1827 }, 1828 setParentValue : function() { 1829 1830 }, 1831 setValue: function (values, state, flag) { 1832 //Select nodes by its values 1833 //values = Object.isArray(values) ? values : (values || '').split(','); 1834 //no state passed in, set Checked if value exists in value list 1835 if (Object.isUndefined(state)) 1836 this.data.Checked = values.include(this.data.Value) ? 2 : 0; 1837 else if (values) 1838 values.include(this.data.Value) && (this.data.Checked = state ? 2 : 0); 1839 1840 if (!flag && this.Children) 1841 if (Object.isUndefined(state)) 1842 this.Children.invoke('setValue', values, state); 1843 else //if (!this.Independent) 1844 this.Children.invoke('setValue', this.getValues(), this.data.Checked); 1845 1846 //Modify "Checked" state to full(2) or partial(1) 1847 if (this.Children)
1848 this.data.Checked = this.getState(); 1849 1850 //Update Parent state only (passing flag=true) 1851 if (this.Parent) 1852 this.Parent.setValue("", this.data.Checked, true); 1853 1854 this.update(this.data); 1855 }, 1856 Is: function (attr) { 1857 //Helper. checks if given attribute is set (class or specific value) 1858 return this.Container.hasClassName(attr); 1859 }, 1860 disable: function() { 1861 this.Container.addClassName('disabled'); 1862 (this.Children ||[]).invoke('disable'); 1863 }, 1864 enable: function () { 1865 this.Container.removeClassName('disabled'); 1866 (this.Children || []).invoke('enable'); 1867 }, 1868 update: function (data) { 1869 this.data = Object.extend(data || {}); 1870 this.Text.update(data.Text); 1871 this.NameContainer.removeClassName('checked').removeClassName('partial'); 1872 this.data.Checked && this.NameContainer.addClassName('checked'); 1873 this.data.Checked == 1 && this.NameContainer.addClassName('partial'); 1874 }, 1875 mouseAction: function (e) { 1876 //Click handler for connector. Detects action based on active element 1877 e.stop(); 1878 var el = e.element(); 1879 if (el && e.type == 'dblclick') 1880 el = this.Connector; 1881 if (this.Connector && el === this.Connector) { 1882 this.host.toggleClassName('collapsed'); 1883 } else if (el && (el === this.Text || el === this.Checkbox)) { 1884 if (!this.Is('disabled')) { 1885 if (!this.options.multiple) { 1886 if (this.Children) { 1887 this.toggleGroup(e); 1888 return; 1889 } 1890 this.Tree.setValue(); 1891 } 1892 this.setValue(this.data.Value.toString(), this.data.Checked == 2 ? 0 : 2); 1893 this.Tree.updateValue(e.CtrlKey || this.options.multiple); 1894 } 1895 } 1896 }, 1897}); 1898 1899 1900Utility.UI.ListSelector = Class.create(Utility.Base, { 1901 defaults: function () { 1902 this.options = Object.extend({ 1903 Delimiter: ',', 1904 maxitems: 5, 1905 itemheight: 20, 1906 itemproperties: 'Value,Text' 1907 }, this.host.getActions({ camelize: true, cast: true })); 1908 }, 1909 initialize: function ($super, host, options) { 1910 try { 1911 if (!$super.apply(this, $A(arguments).slice(1))) 1912 return false; 1913 if (!(this.Container = this.host.down('ul'))) 1914 this.host.insert(this.Container = new Element('ul')); 1915 this.Collect(this.defaultValue); 1916 1917 1918 return this; 1919 1920 } catch (er) { 1921 $alert(er.message); 1922 } 1923 return this; 1924 }, 1925 onSelect: Prototype.emptyFunction, 1926 getValue: function () { 1927 return this.ActiveItem ? this.ActiveItem.data : { Value: '', Text: '' }; 1928 }, 1929 setValue: function (value) { 1930 this.ActivateItem(this.Items.find(function (it) { 1931 return it.data.Value == value; 1932 })); 1933 }, 1934 getText: function (text) { 1935 var v = this.getValue(); 1936 v.text = text || v.Text; 1937 return '<span class="bit" data-value="#{Value}" data-text="#{Text}">#{text}</span>'.interpolate(v); 1938 }, 1939 onShow: function (dim) { 1940 if (!this.Items.length) 1941 return; 1942 dim = this.Items.inject(dim, function (o, it,idx) { 1943 o.width = Math.max(it.getWidth(), o.width); 1944 o.height = Math.min((it.getHeight() * Math.min(this.Items.length, this.options.maxitems)), o.height); 1945 return o; 1946 }, this); 1947 this.Parent.Container.setStyle({ 1948 height: dim.height + 'px', 1949 width: (dim.width) + 'px' 1950 }); 1951 }, 1952 CreateItem: function (item, highlight, keys) { 1953 //check keys: Array[2] - 0- value, 1-text 1954 var v = keys[0], t = keys[1]; 1955 item.DisplayName = highlight ? item[keys[1]].replace(new RegExp(highlight, 'gi'), function ($1) { return '<span class="highlight">' + $1 + '</span>'; }) : item[keys[1]];
1956 item[t] = escape(item[t]); // escape 'text' properties 1957 return ('<li data-index="#{index}" data-' + v + '="#{' + v + '}"data-' + t + '="#{' + t + '}"><a>#{DisplayName}<a></li>').interpolate(item); 1958 }, 1959 Collect: function (def) { 1960 this.DeactivateItem(); 1961 delete this.Items; 1962 this.itemWidth = this.Container.getWidth(); 1963 this.itemHeight = this.Container.getHeight() / this.options.itemheight; 1964 this.Items = this.Container.select('li').collect(function (item, index) { 1965 item.data = item.getActions({ cast: true, camelize: true }); 1966 item.data.Text = item.getInnerText(); 1967 item.empty() && item.update(" "); 1968 item.index = index; 1969 item.on("mousedown", this.Select.bind(this, item, true)); 1970 this.itemWidth = Math.max(item.getWidth(), this.itemWidth); 1971 this.itemHeight = Math.max(item.getHeight(), this.itemHeight); 1972 return item; 1973 }, this); 1974 if (def = this.Items.detect(function (it) { return it.data.Value == def; })) 1975 this.ActivateItem(def); 1976 1977 }, 1978 Load: function (data, value) { 1979 1980 if (Object.isArray(data)) { 1981 this.Container.update(''); 1982 //transform and add options to container 1983 data.each(function (it) { 1984 //call transformation function with two parameters: current item data and text box value 1985 this.Container.insert(this.CreateItem.call(this.Container, it, value, String(this.options.itemproperties).split(','))); 1986 }, this); 1987 } else if (Object.isString(data)) { 1988 this.Container.update(data); 1989 } 1990 this.Collect(); 1991 return this.Items.length > 0; 1992 }, 1993 Select: function (it, done) { 1994 this.ActivateItem(it); 1995 this.onSelect(this.getValue(), true); 1996 //done && this.run('Parent.Deactivate'); 1997 }, 1998 DeactivateItem: function () { 1999 Object.isArray(this.Items) && this.Items.invoke('removeClassName', "selected"); 2000 delete this.ActiveItem; 2001 }, 2002 ActivateItem: function (it) { 2003 this.DeactivateItem(); 2004 it && (this.ActiveItem = it.addClassName('selected')); 2005 return this; 2006 }, 2007 Up: function (e) { 2008 if (this.Items && this.Items.length) { 2009 var index = this.Items.length - 1; 2010 if (this.ActiveItem) 2011 index = this.ActiveItem.index == 0 ? this.ActiveItem.index : this.ActiveItem.index - 1; 2012 this.ActivateItem(this.Items[index]); 2013 this.onSelect(this.getValue()); 2014 this.Scroll(); 2015 } 2016 }, 2017 Down: function (e) { 2018 if (this.Items && this.Items.length) { 2019 var index = 0; 2020 if (this.ActiveItem) 2021 index = this.ActiveItem.index == this.Items.length - 1 ? this.ActiveItem.index : this.ActiveItem.index + 1; 2022 this.ActivateItem(this.Items[index]); 2023 this.onSelect(this.getValue()); 2024 this.Scroll(); 2025 } 2026 }, 2027 Scroll: function (i) { 2028 var offsetTop = this.ActiveItem.offsetTop; 2029 var upperBound = this.host.scrollTop; 2030 var lowerBound = upperBound + (this.host.measure('border-box-height') - this.ActiveItem.measure('border-box-height')); 2031 if (offsetTop < upperBound) { 2032 this.host.scrollTop = offsetTop; 2033 } else if (offsetTop > lowerBound) { 2034 this.host.scrollTop = offsetTop - (this.host.measure('border-box-height') - this.ActiveItem.measure('border-box-height')); 2035 } 2036 }, 2037 2038}); 2039 2040 2041 2042//-----------------------------------------------------------------------------\dlo/ 2043// CHO.Input Control v1.0 2044// Jonas Software © 2013, by Dmitry Lopyrev 2045//----------------------------------------------------------------------------- 2046// 2047//----------------------------------------------------------------------------- 2048// Note: Requires Prototype JS library (v.1.7.1 - modified) and Utility.js 2049//----------------------------------------------------------------------------- 2050 2051Utility.UI.DateTime = Class.create(Utility.Base, { 2052 defaults: function () { 2053 return this.options = this.host.getActions({ camelize: true, cast: true }, { 2054 views: 'days,months' 2055 }); 2056 2057 }, 2058 initialize: function ($super, host, options) { 2059 2060 if (!$super.apply(this, $A(arguments).slice(1))) 2061 return false; 2062 2063 this.GlobalContainer = this.host; 2064 this.current = new Date(); 2065 this.options.views = this.options.views.split(',').invoke('capitalize').inject({}, function (o, it) { 2066 o[it] = true; 2067 return o; 2068 }, this); 2069 2070 /* 2071 //Assign custom event handlers 2072 this.on('on:show', this.onShow.bindAsEventListener(this)); 2073 this.on('on:hide', this.onHide.bindAsEventListener(this)); 2074 this.on('on:load', this.onLoad.bindAsEventListener(this)); 2075 */ 2076 return this; 2077 2078 }, 2079 getValue: function () { 2080 return { 2081 Value: this.selected ? this.selected.CustomFormat(this._format) : '', 2082 Text: this.selected ? this.selected.CustomFormat(this.options.format) : '' 2083 }; 2084 }, 2085 getText: function (text) { 2086 var v = this.getValue(); 2087 v.text = Object.isString(text) ? text : v.Text; 2088 return '<span class="bit" data-value="#{Value}" data-text="#{Text}">#{text}</span>'.interpolate(v); 2089 }, 2090 setOptions: function (opt) { 2091 Object.extend(this.options, opt || {}); 2092 this.Create(); 2093 }, 2094 onSelect: Prototype.emptyFunction, 2095 Create: function () { 2096 this.GlobalContainer.writeAttribute("data-type", "datetime"); 2097 }, 2098 onShow: function (e) { 2099 this.UpdateLayout(); 2100 }, 2101 onLoad: function (e) { 2102 this.options.data = e.memo; 2103 this.status = 'ready'; 2104 }, 2105 ValidateRange: function (dt) { 2106 return true; 2107 } 2108}); 2109 2110 2111Utility.UI.DatePicker = Class.create(Utility.UI.DateTime, { 2112 defaults: function ($super) { 2113 this._format = 'yyyy/MM/dd'; 2114 2115 this.WeekDays = [], this.Days = [], this.Months = [], this.Years = []; 2116 2117 return this.options = Object.extend($super(), {
2118 format: 'MM/dd/yyyy', 2119 full: 'w, MMMM d, yyyy', 2120 today: "Today: ", 2121 firstday: 0, 2122 delta: 6, 2123 min: true 2124 }); 2125 }, 2126 initialize: function ($super, host, options) { 2127 2128 if (!$super.apply(this, $A(arguments).slice(1))) 2129 return false; 2130 this.selected = Date.parse(this.selected) ? new Date(this.selected) : null; 2131 this.picked = new Date(this.selected || this.current); 2132 2133 if (this.options.min) 2134 this.options.min = Date.parse(this.options.min) ? new Date(this.options.min) : this.current.setTime(); 2135 if (this.options.max) 2136 this.options.max = Date.parse(this.options.max) ? new Date(this.options.max) : null; 2137 2138 this.Create(); 2139 return this; 2140 2141 }, 2142 Layout: function ($super, id, data) { 2143 switch (id) { 2144 case 'days': 2145 return ('<table style="width: 100%; height: 100%;" data-view="days"><tbody>' + 2146 '<tr class="navi">' + 2147 '<td><div title="Previous" class="icon prev"></div></td>' + 2148 '<td colspan="5" style="white-space: nowrap;"><span class="title" title="Click to select month and year"></span><br/><span class="subtitle" title="Today. Click to select" ></span></td>' + 2149 '<td><div title="Next" class="icon next"></div></td>' + 2150 '</tr>' + 2151 '</tbody></table>').interpolate(data); 2152 case 'months': 2153 return ('<table style="width: 100%; height: 100%;" data-view="months"><tbody>' + 2154 '<tr class="header">' + 2155 '<th colspan="2" style="width:50%">Months</th>' + 2156 '<th rowspan="7"></td>' + 2157 '<th colspan="2" style="width:50%">' + 2158 '<span data-year-nav="prev"></span>Years<span data-year-nav="next"></span></th>' + 2159 '</tr>' + 2160 '</tbody></table>').interpolate(data); 2161 2162 case 'dayofweek': 2163 return '<td width="14.28%" title="#{title}" class="#{class}">#{1}</td>'.interpolate(data); 2164 case 'day': 2165 return '<td class="day disabled"></td>'.interpolate(data); 2166 default: 2167 return $super(id, data); 2168 } 2169 }, 2170 CreateCell: function (host, type, value, tag) { 2171 var cell = new Element(tag || "td"); 2172 switch (type) { 2173 case 'weekday': 2174 cell.addClassName(value.weekend() ? 'weekend' : 'weekday').update(value.CustomFormat("w").substr(0, 2)).setStyle("width:14.28%"); 2175 break; 2176 case 'month': 2177 cell.addClassName("month").update(value.CustomFormat("MMM"))._value = value.getMonth(); 2178 break; 2179 case 'year': 2180 cell.addClassName("year")._value = 0; 2181 break; 2182 case 'day': 2183 cell.addClassName("day"); 2184 break; 2185 } 2186 cell.on('click', this.Pick.bindAsEventListener(this)); 2187 return host.appendChild(cell); 2188 }, 2189 Create: function ($super) { 2190 2191 $super(); 2192 var d = this.current.toObject(); 2193 this.GlobalContainer.update(''); 2194 2195 if (this.options.views.Days) { 2196 this.GlobalContainer.insert(this.Layout('days')); 2197 2198 this.GlobalContainer.down('.subtitle').update(this.current.CustomFormat('w, MMM d, yyyy')).on('click', this.Pick.bindAsEventListener(this, this.current)); 2199 this.options.views.Days = this.GlobalContainer.down('[data-view="days"]'); 2200 this.Prev = this.GlobalContainer.down('.prev'); 2201 this.Prev.on('click', this.Navigate.bindAsEventListener(this)); 2202 2203 this.Header = this.GlobalContainer.down('.title'); 2204 2205 this.Next = this.GlobalContainer.down('.next'); 2206 this.Next.on('click', this.Navigate.bindAsEventListener(this)); 2207 2208 var row = $p(this.options.views.Days.insertRow(-1)).addClassName('header'); 2209 var start = new Date(d.year, d.month, 1).getDay() - this.options.firstday; 2210 if (start < 0) start += 7; 2211 for (var i = 0; i < 7; i++) { 2212 this.WeekDays.push(this.CreateCell(row, 'weekday', new Date(d.year, d.month, (i - start + 1)),'th')); 2213 } 2214 for (var i = 0; i < 42; i++) { 2215 (i % 7 == 0) && (row = $p(this.options.views.Days.insertRow(-1))); 2216 this.Days.push(this.CreateCell(row, 'day')); 2217 } 2218 this.options.views.Days.hide(); 2219 } 2220 if (this.options.views.Months) { 2221 this.GlobalContainer.insert(this.Layout('months')); 2222 this.options.views.Months = this.GlobalContainer.down('[data-view="months"]'); 2223 for (var i = 0; i < 6; i++) { 2224 row = this.options.views.Months.insertRow(-1); 2225 this.Months.push(this.CreateCell(row, 'month', new Date(d.year, i * 2, 1))); 2226 this.Months.push(this.CreateCell(row, 'month', new Date(d.year, i * 2 + 1, 1))); 2227 this.Years.push(this.CreateCell(row, 'year', d.year)); 2228 this.Years.push(this.CreateCell(row, 'year', d.year)); 2229 } 2230 if (this.options.views.Days) { 2231 this.Header.on('click', function (e) { e.stop(); this.Toggle('Months'); }.bind(this)); 2232 } 2233 this.options.views.Months.hide(); 2234 2235 } 2236 this.Toggle(); 2237 2238 }, 2239 setValue: function ($super, value) { 2240 if (Utility.UI.Validation.IsDate(value)) 2241 this.selected = new Date(value); 2242 else 2243 this.selected = null; 2244 this.picked = new Date(this.selected || this.current); 2245 this.UpdateLayout(); 2246 2247 }, 2248 getValue: function ($super) { 2249 var v = $super(); 2250 v.Value && (v.Date = this.selected); 2251 return v; 2252 }, 2253 Toggle: function (view) { 2254 for (var it in this.options.views) { 2255 !view && (view = it); 2256 this.options.views[it][it == view ? 'show' : 'hide'](); 2257 } 2258 return this; 2259 }, 2260 UpdateDays: function () { 2261 if (!this.options.views.Days) 2262 return; 2263 var o = this.picked.toObject('YM'); 2264 this.Header.update(this.picked.CustomFormat('MMMM, yyyy')); 2265 this.Prev.setStyle('visibility:#{0}'.interpolate([this.ValidateMin(new Date(o.year, o.month, 0)) ? 'visible' : 'hidden'])); 2266 // this.Next.setStyle('visibility:#{0}'.interpolate([this.ValidateRange(new Date(o.year, o.month + 1, 0)) ? 'visible' : 'hidden'])); 2267 this.Next.setStyle('visibility:#{0}'.interpolate([this.ValidateMax(new Date(o.year, o.month, 0)) ? 'visible' : 'hidden'])); 2268 2269 var start = new Date(o.year, o.month, 1).getDay() - this.options.firstday; 2270 if (start < 0) start += 7; 2271 for (var i = 0, cell; cell = this.Days[i]; i++) { 2272 2273 var cellValue = (cell._value = new Date(o.year, o.month, (i - start + 1))).CustomFormat(this._format); 2274 2275 cell.update(cell._value.getDate()); 2276 cell.className = 'day'; 2277 2278 cell.title = cell._value.CustomFormat(this.options.full); 2279 cell.addClassName(cell._value.getMonth() == o.month ? '' : 'out'); 2280 2281 if (cellValue == this.current.CustomFormat(this._format)) { 2282 cell.addClassName('today'); 2283 cell.title = this.options.today + cell.title; 2284 } 2285 2286 2287 if (Object.isArray(this.options.data) && this.options.data.include(cellValue) && cell._value >= curentDateOnly) { 2288 cell.addClassName('special'); 2289 cell.title += ". Special date"; 2290 } 2291
2292 if (this.selected && cellValue == this.selected.CustomFormat(this._format)) 2293 cell.addClassName('selected'); 2294 2295 if (!this.ValidateRange(cell._value)) 2296 cell.addClassName('disabled'); 2297 2298 } 2299 2300 }, 2301 UpdateMonths: function (dim) { 2302 if (!this.options.views.Months) 2303 return; 2304 2305 var d = this.picked.toObject(); 2306 2307 this.Months.invoke('removeClassName', 'selected|selected-over|disabled'); 2308 2309 this.Months[this.picked.getMonth()].addClassName('selected'); 2310 for (var i = 0, cell; cell = this.Months[i++];) { 2311 cell._value == d.month && cell.addClassName('selected'); 2312 if (!this.ValidateRange(new Date(d.year, cell._value + 1, 0))) 2313 cell.addClassName('disabled'); 2314 } 2315 2316 this.Years.invoke('removeClassName', 'selected|selected-over|disabled'); 2317 var delta = this.options.delta; 2318 var b = (this.Years[0]._value == 0 || this.Years[0]._value == d.year || this.Years[this.Years.length - 1]._value == d.year) 2319 for (var i = 0, cell; cell = this.Years[i++];) { 2320 b && (cell.update(cell._value = d.year - delta + i)); 2321 if (b && i == 1) cell.update("« " + cell.innerHTML); 2322 if (b && i == this.Years.length) cell.update(cell.innerHTML + " »"); 2323 (cell._value == d.year) && (cell.addClassName("selected")); 2324 if (!this.ValidateRange(new Date(cell._value + 1, 0, 0))) 2325 cell.addClassName('disabled'); 2326 2327 } 2328 }, 2329 UpdateLayout: function (dim) { 2330 2331 var curentDateOnly = new Date(this.current.CustomFormat(this._format)); 2332 this.UpdateDays(); 2333 this.UpdateMonths(); 2334 2335 return this; 2336 }, 2337 Navigate: function (e) { 2338 Event.stop(e); 2339 var delta = 1, id; 2340 switch (Event.element(e)) { 2341 case this.Prev: delta *= -1; id = e.ctrlKey ? "y" : "m"; break; 2342 case this.TPrev: delta *= -1; id = e.ctrlKey ? "h" : "min"; break; 2343 case this.Next: id = e.ctrlKey ? "y" : "m"; break; 2344 case this.TNext: id = e.ctrlKey ? "h" : "min"; break; 2345 default: 2346 if (this.startPos > 0 && e.type == 'touchend') { 2347 delta *= (e.changedTouches[0].pageX - this.startPos) > 0 ? -1 : 1; 2348 id = 'm'; 2349 } 2350 break; 2351 } 2352 this.picked = this.picked.add(id, delta); 2353 this.UpdateLayout(); 2354 }, 2355 GetDateValue: function (o) { 2356 var dt = new Date((this.picked || this.current)).toObject(); 2357 2358 if (/^(day|out)/i.test(o.className) && o._value instanceof Date) { 2359 dt = new Date(o._value).toObject(); 2360 } 2361 else if (/month/i.test(o.className) && typeof (o._value) == 'number') 2362 dt.month = o._value; 2363 else if (/year/i.test(o.className) && typeof (o._value) == 'number') 2364 dt.year = o._value; 2365 2366 return new Date(dt.year, dt.month, dt.day); 2367 }, 2368 Pick: function (e, dt) { 2369 2370 var element = Event.element(e), done = true; 2371 dt = dt ? dt : this.GetDateValue(element); 2372 2373 if (element.hasClassName('disabled')) { 2374 e.stop(); 2375 return; 2376 } 2377 if (!e.ctrlKey) { 2378 if (/(month|year)/i.test(element.className)) { 2379 if (this.options.views.Days) { 2380 (this.Toggle('Days')); 2381 done = false; 2382 } 2383 } 2384 } else { 2385 done = false; 2386 } 2387 2388 if (!this.ValidateRange(dt)) 2389 return false; 2390 2391 this.selected = dt; 2392 this.picked = this.selected.clone(); 2393 this.UpdateLayout(); 2394 e.stop(); 2395 this.onSelect(this.getValue(), Object.isBoolean(this.options.stick) ? !this.options.stick : done);//this.Refresh(true); 2396 2397 }, 2398 ValidateRange: function (dt) { 2399 var d = dt.clone().setTime(); 2400 if (this.options.min && dt < this.options.min) 2401 return false; 2402 if (this.options.max && dt > this.options.max) 2403 return false; 2404 return true; 2405 }, 2406 ValidateMin: function (dt) { 2407 if (this.options.min && dt < this.options.min) 2408 return false; 2409 2410 return true; 2411 }, 2412 ValidateMax: function (dt) { 2413 if (this.options.max && dt > this.options.max) 2414 return false; 2415 2416 return true; 2417 }, 2418}); 2419 2420 2421Utility.UI.TimePicker = Class.create(Utility.UI.DateTime, { 2422 defaults: function ($super) { 2423 this._format = 'hh:mm'; 2424 return this.options = Object.extend($super(), { 2425 format: 'h:mm tt', 2426 group: 'p', 2427 delta: 15 2428 }); 2429 }, 2430 initialize: function ($super, host, options) { 2431 2432 if (!$super.apply(this, $A(arguments).slice(1))) 2433 return false; 2434 this.selected = this.current.setTime(this.selected || '') || null; 2435 this.picked = new Date(this.selected || this.current); 2436 2437 if (this.options.min) 2438 this.options.min = this.current.setTime(this.options.min); 2439 if (this.options.max) 2440 this.options.max = this.current.setTime(this.options.max); 2441 2442 2443 this.Times = []; 2444 this.Create(); 2445 return this; 2446 2447 }, 2448 setValue: function ($super, value) { 2449 if (Utility.UI.Validation.IsTime(value)) 2450 this.selected = new Date(this.current.setTime(value)); 2451 else 2452 this.selected = null; 2453 this.picked = new Date(this.selected || this.current).round(this.options.delta); 2454 this.UpdateLayout(); 2455 }, 2456 getValue: function ($super) { 2457 var v = $super(); 2458 v.Value && (v.Time = this.selected); 2459 return v; 2460 }, 2461 Layout: function ($super, id, data) { 2462 switch (id) { 2463 case 'main': 2464 return ('<table style="width: 100%; height: 100%;"></table>').interpolate(data); 2465 case 'timecell': 2466 return '<td class="time">#{0}</td>'.interpolate(data); 2467 case 'group': 2468 return '<th class="header" colspan="#{0}">#{1}</th>'.interpolate(data); 2469 default: 2470 return $super(id, data); 2471 } 2472 }, 2473 CreateCell: function (host, type, value) { 2474 var cell; 2475 switch (type) { 2476 case 'group': 2477 cell = this.Layout(type, [4, value.toString(String(this.options.group).strip())]); 2478 break; 2479 case 'timecell': 2480 cell = this.Layout(type, [value.toString('h:mmtt')]); 2481 break; 2482 }
2483 cell = host.insert(cell).childElements().last(); 2484 cell.on('click', this.Pick.bindAsEventListener(this, cell._value = value)); 2485 return cell; 2486 }, 2487 Create: function ($super) { 2488 2489 $super(); 2490 2491 var tbody, row; 2492 var total = 1440 / this.options.delta; 2493 var ind = 4; 2494 2495 2496 this.GlobalContainer.insert(this.Layout('main')).addClassName("f10"); //, { height: this.options.height } 2497 2498 this.TimeContainer = this.GlobalContainer.down('table'); 2499 var p, dt = this.picked.setTime(); 2500 2501 for (var i = 0; i < total; i++) { 2502 var value = dt.add('min', i * this.options.delta); 2503 if (i % ind == 0) { 2504 2505 if (this.options.group && p != value.CustomFormat('p')) { 2506 //tbody = $p(this.TimeContainer.createTBody()); 2507 this.TimeContainer.insert(tbody = new Element('tbody')); 2508 2509 row = tbody.insertRow(-1).addClassName('header'); 2510 this.CreateCell(row, 'group', value); 2511 p = value.CustomFormat('p'); 2512 } 2513 row = tbody.insertRow(-1); 2514 } 2515 this.Times.push(this.CreateCell(row, 'timecell', value)); 2516 } 2517 2518 }, 2519 UpdateLayout: function () { 2520 this.picked = this.picked.setTime(); 2521 delete this.selectedTime; 2522 this.Times.each(function (it, index) { 2523 var cellValue = it._value.toString(this._format); 2524 it.className = 'time'; 2525 if (this.selected && cellValue == this.selected.CustomFormat(this._format)) { 2526 it.addClassName('selected'); 2527 this.selectedTime = it; 2528 } 2529 2530 if (!this.ValidateRange(it._value)) 2531 it.addClassName('disabled'); 2532 2533 }.bind(this)); 2534 if (!this.options.inactive) 2535 this.TimeContainer.select('tbody').each(function (tb) { 2536 var v = tb.select('tr').inject(0, function (result, row) { 2537 if (row.select('td.disabled').length != 4) 2538 return result + 1; 2539 row.hide(); 2540 return result; 2541 }); 2542 v <= (this.options.group ? 1 : 0) && tb.hide(); 2543 }, this); 2544 2545 }, 2546 GetDateValue: function (o) { 2547 var dt = new Date((this.picked || this.current)).toObject(); 2548 2549 if (/^(day|out)/i.test(o.className) && o._value instanceof Date) { 2550 dt = new Date(o._value).toObject(); 2551 } 2552 else if (/month/i.test(o.className) && typeof (o._value) == 'number') 2553 dt.month = o._value; 2554 else if (/year/i.test(o.className) && typeof (o._value) == 'number') 2555 dt.year = o._value; 2556 2557 return new Date(dt.year, dt.month, dt.day); 2558 }, 2559 Pick: function (e, dt) { 2560 var element = Event.element(e), done = true; 2561 2562 if (e.ctrlKey) { 2563 done = false; 2564 } 2565 2566 dt = dt ? dt : this.GetDateValue(element); 2567 2568 if (!this.ValidateRange(dt)) 2569 return false; 2570 2571 this.selected = dt; 2572 this.picked = this.selected.clone(); 2573 e.stop(); 2574 this.onSelect(this.getValue(), Object.isBoolean(this.options.stick) ? !this.options.stick : done);//this.Refresh(true); 2575 }, 2576 ValidateRange: function (dt) { 2577 2578 if (this.options.min && dt < dt.setTime(this.options.min)) 2579 return false; 2580 if (this.options.max && dt > dt.setTime(this.options.max)) 2581 return false; 2582 return true; 2583 }, 2584 onShow: function ($super) { 2585 $super(); 2586 this.selectedTime && (this.GlobalContainer.scrollTop = this.selectedTime.offsetTop); 2587 }, 2588 2589}); 2590 2591 2592 2593Utility.UI.OptionList = Class.create(Utility.Base, { 2594 initialize: function ($super) { 2595 try { 2596 if (!$super.apply(this, $A(arguments).slice(1))) 2597 return false; 2598 this.host.$class = this; 2599 this.options = this.host.select('input[type][data-field-option="#{field}"]'.interpolate(this)); 2600 this.host.getValue = this.getValue.bind(this); 2601 this.host.setValue = this.setValue.bind(this); 2602 this.host.disable = this.disable.bind(this); 2603 this.host.enable = this.enable.bind(this); 2604 this.host.on = this.on.bind(this); 2605 this.host.Run = this.run.bind(this); 2606 this.host.simulate = this.simulate.bind(this); 2607 if (this.host.disabled = this.host.readAttribute('disabled')) { 2608 this.host.disabled = false; 2609 this.host.disable(); 2610 } 2611 } catch (ex) { 2612 $alert(ex.message, 'UI::Option List'); 2613 } 2614 return this; 2615 }, 2616 getValue: function () { 2617 if (!this.options.length) 2618 return ''; 2619 return this.options.inject([], function (list, it) { 2620 it.checked && list.push(it.value); 2621 return list; 2622 }).toString(); 2623 }, 2624 setValue: function (value) { 2625 if (!this.options.length) 2626 return; 2627 var i = 0;
2628 value = String(value).split(','); 2629 this.options.each(function (it) { 2630 var disabled = it.disabled; 2631 if (disabled) 2632 it.enable(); 2633 if (it.checked = value.indexOf(it.value) != -1) { 2634 it.simulate('change'), i++; 2635 } 2636 if (disabled) 2637 it.disable(); 2638 }); 2639 if (i == 0) { 2640 this.simulate('change'); 2641 } 2642 }, 2643 on: function () { 2644 if (!this.options.length) 2645 this.host.on.apply(this.host, $A(arguments)); 2646 else { 2647 var args = $A(arguments); 2648 this.options.each(function (it) { 2649 it.on.apply(it, args); 2650 }); 2651 } 2652 }, 2653 simulate: function () { 2654 if (!this.options.length) 2655 this.host.simulate.apply(this.host, $A(arguments)); 2656 else { 2657 var args = $A(arguments); 2658 this.options.each(function (it) { 2659 var disabled = it.disabled; 2660 if (disabled) 2661 it.enable(); 2662 it.simulate.apply(it, args); 2663 if (disabled) 2664 it.disable(); 2665 }); 2666 } 2667 }, 2668 disable: function () { 2669 if (!this.overlay) { 2670 this.host.setStyle('position:relative;display:inline-block;'); 2671 (this.host.insert(this.overlay = new Element('div', { className: 'overlay' }))); 2672 this.overlay.$click = this.overlay.on('click', function (e) { e.stop(); }); 2673 2674 } 2675 this.options.invoke('disable'); 2676 this.overlay.setStyle('visibility:inherit').clonePosition(this.host); 2677 this.host.addClassName('disabled'); 2678 this.overlay.$click.start(); 2679 return this; 2680 }, 2681 enable: function () { 2682 if (this.overlay) { 2683 this.overlay.$click.stop(); 2684 this.overlay.setStyle('visibility:hidden'); 2685 } 2686 this.options.invoke('enable'); 2687 this.host.removeClassName('disabled'); 2688 return this; 2689 } 2690}); 2691 2692 2693
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.