Changeset 7855
- Timestamp:
- 03/13/08 10:12:37 (1 year ago)
- Files:
-
- branches/1.1/data/web/sf/prototype/js/builder.js (modified) (5 diffs)
- branches/1.1/data/web/sf/prototype/js/controls.js (modified) (19 diffs)
- branches/1.1/data/web/sf/prototype/js/dragdrop.js (modified) (29 diffs)
- branches/1.1/data/web/sf/prototype/js/effects.js (modified) (50 diffs)
- branches/1.1/data/web/sf/prototype/js/prototype.js (modified) (84 diffs)
- branches/1.1/data/web/sf/prototype/js/scriptaculous.js (modified) (3 diffs)
- branches/1.1/data/web/sf/prototype/js/slider.js (modified) (18 diffs)
- branches/1.1/data/web/sf/prototype/js/sound.js (added)
- branches/1.1/data/web/sf/prototype/js/unittest.js (modified) (2 diffs)
- branches/1.1/lib/helper/JavascriptHelper.php (modified) (15 diffs)
- branches/1.1/licenses/LICENSE.prototype (modified) (2 diffs)
- branches/1.1/licenses/LICENSE.script.aculo.us (modified) (1 diff)
- doc/branches/1.1/book/11-Ajax-Integration.txt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/1.1/data/web/sf/prototype/js/builder.js
r3316 r7855 1 // script.aculo.us builder.js v1. 7.0, Fri Jan 19 19:16:36 CET 20071 // script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008 2 2 3 // Copyright (c) 2005 , 2006Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)3 // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 4 4 // 5 5 // script.aculo.us is freely distributable under the terms of an MIT-style license. … … 49 49 if(arguments[1]) 50 50 if(this._isStringOrNumber(arguments[1]) || 51 (arguments[1] instanceof Array)) { 51 (arguments[1] instanceof Array) || 52 arguments[1].tagName) { 52 53 this._children(element, arguments[1]); 53 54 } else { … … 67 68 if(element.tagName.toUpperCase() != elementName) 68 69 element = parentElement.getElementsByTagName(elementName)[0]; 69 }70 } 70 71 } 71 72 … … 89 90 for(attribute in attributes) 90 91 attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) + 91 '="' + attributes[attribute].toString().escapeHTML() + '"');92 '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'"') + '"'); 92 93 return attrs.join(" "); 93 94 }, 94 95 _children: function(element, children) { 96 if(children.tagName) { 97 element.appendChild(children); 98 return; 99 } 95 100 if(typeof children=='object') { // array can hold nodes and text 96 101 children.flatten().each( function(e) { … … 102 107 }); 103 108 } else 104 if(Builder._isStringOrNumber(children)) 105 element.appendChild(Builder._text(children));109 if(Builder._isStringOrNumber(children)) 110 element.appendChild(Builder._text(children)); 106 111 }, 107 112 _isStringOrNumber: function(param) { branches/1.1/data/web/sf/prototype/js/controls.js
r3316 r7855 1 // script.aculo.us controls.js v1. 7.0, Fri Jan 19 19:16:36 CET 20072 3 // Copyright (c) 2005 , 2006Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)4 // (c) 2005 , 2006Ivan Krstic (http://blogs.law.harvard.edu/ivan)5 // (c) 2005 , 2006Jon Tirsen (http://www.tirsen.com)1 // script.aculo.us controls.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008 2 3 // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 4 // (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan) 5 // (c) 2005-2007 Jon Tirsen (http://www.tirsen.com) 6 6 // Contributors: 7 7 // Richard Livsey … … 40 40 throw("controls.js requires including script.aculo.us' effects.js library"); 41 41 42 var Autocompleter = {} 43 Autocompleter.Base = function() {}; 44 Autocompleter.Base.prototype = { 42 var Autocompleter = { } 43 Autocompleter.Base = Class.create({ 45 44 baseInitialize: function(element, update, options) { 46 this.element = $(element); 45 element = $(element) 46 this.element = element; 47 47 this.update = $(update); 48 48 this.hasFocus = false; … … 51 51 this.index = 0; 52 52 this.entryCount = 0; 53 this.oldElementValue = this.element.value; 53 54 54 55 if(this.setOptions) 55 56 this.setOptions(options); 56 57 else 57 this.options = options || { };58 this.options = options || { }; 58 59 59 60 this.options.paramName = this.options.paramName || this.element.name; … … 77 78 if(typeof(this.options.tokens) == 'string') 78 79 this.options.tokens = new Array(this.options.tokens); 80 // Force carriage returns as token delimiters anyway 81 if (!this.options.tokens.include('\n')) 82 this.options.tokens.push('\n'); 79 83 80 84 this.observer = null; … … 84 88 Element.hide(this.update); 85 89 86 Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this));87 Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this));90 Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); 91 Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this)); 88 92 }, 89 93 … … 91 95 if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); 92 96 if(!this.iefix && 93 (navigator.appVersion.indexOf('MSIE')>0) && 94 (navigator.userAgent.indexOf('Opera')<0) && 97 (Prototype.Browser.IE) && 95 98 (Element.getStyle(this.update, 'position')=='absolute')) { 96 99 new Insertion.After(this.update, … … 142 145 this.markPrevious(); 143 146 this.render(); 144 if(navigator.appVersion.indexOf('AppleWebKit')>0)Event.stop(event);147 Event.stop(event); 145 148 return; 146 149 case Event.KEY_DOWN: 147 150 this.markNext(); 148 151 this.render(); 149 if(navigator.appVersion.indexOf('AppleWebKit')>0)Event.stop(event);152 Event.stop(event); 150 153 return; 151 154 } 152 155 else 153 156 if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || 154 ( navigator.appVersion.indexOf('AppleWebKit')> 0 && event.keyCode == 0)) return;157 (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; 155 158 156 159 this.changed = true; … … 198 201 Element.addClassName(this.getEntry(i),"selected") : 199 202 Element.removeClassName(this.getEntry(i),"selected"); 200 201 203 if(this.hasFocus) { 202 204 this.show(); … … 241 243 var value = ''; 242 244 if (this.options.select) { 243 var nodes = document.getElementsByClassName(this.options.select, selectedElement) || [];245 var nodes = $(selectedElement).select('.' + this.options.select) || []; 244 246 if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); 245 247 } else 246 248 value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); 247 249 248 var lastTokenPos = this.findLastToken();249 if ( lastTokenPos!= -1) {250 var newValue = this.element.value.substr(0, lastTokenPos + 1);251 var whitespace = this.element.value.substr( lastTokenPos + 1).match(/^\s+/);250 var bounds = this.getTokenBounds(); 251 if (bounds[0] != -1) { 252 var newValue = this.element.value.substr(0, bounds[0]); 253 var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); 252 254 if (whitespace) 253 255 newValue += whitespace[0]; 254 this.element.value = newValue + value ;256 this.element.value = newValue + value + this.element.value.substr(bounds[1]); 255 257 } else { 256 258 this.element.value = value; 257 259 } 260 this.oldElementValue = this.element.value; 258 261 this.element.focus(); 259 262 … … 299 302 onObserverEvent: function() { 300 303 this.changed = false; 304 this.tokenBounds = null; 301 305 if(this.getToken().length>=this.options.minChars) { 302 this.startIndicator();303 306 this.getUpdatedChoices(); 304 307 } else { … … 306 309 this.hide(); 307 310 } 311 this.oldElementValue = this.element.value; 308 312 }, 309 313 310 314 getToken: function() { 311 var tokenPos = this.findLastToken(); 312 if (tokenPos != -1) 313 var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,''); 314 else 315 var ret = this.element.value; 316 317 return /\n/.test(ret) ? '' : ret; 318 }, 319 320 findLastToken: function() { 321 var lastTokenPos = -1; 322 323 for (var i=0; i<this.options.tokens.length; i++) { 324 var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]); 325 if (thisTokenPos > lastTokenPos) 326 lastTokenPos = thisTokenPos; 327 } 328 return lastTokenPos; 315 var bounds = this.getTokenBounds(); 316 return this.element.value.substring(bounds[0], bounds[1]).strip(); 317 }, 318 319 getTokenBounds: function() { 320 if (null != this.tokenBounds) return this.tokenBounds; 321 var value = this.element.value; 322 if (value.strip().empty()) return [-1, 0]; 323 var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); 324 var offset = (diff == this.oldElementValue.length ? 1 : 0); 325 var prevTokenPos = -1, nextTokenPos = value.length; 326 var tp; 327 for (var index = 0, l = this.options.tokens.length; index < l; ++index) { 328 tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); 329 if (tp > prevTokenPos) prevTokenPos = tp; 330 tp = value.indexOf(this.options.tokens[index], diff + offset); 331 if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp; 332 } 333 return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]); 329 334 } 330 } 331 332 Ajax.Autocompleter = Class.create(); 333 Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), { 335 }); 336 337 Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { 338 var boundary = Math.min(newS.length, oldS.length); 339 for (var index = 0; index < boundary; ++index) 340 if (newS[index] != oldS[index]) 341 return index; 342 return boundary; 343 }; 344 345 Ajax.Autocompleter = Class.create(Autocompleter.Base, { 334 346 initialize: function(element, update, url, options) { 335 347 this.baseInitialize(element, update, options); … … 341 353 342 354 getUpdatedChoices: function() { 343 entry = encodeURIComponent(this.options.paramName) + '=' + 355 this.startIndicator(); 356 357 var entry = encodeURIComponent(this.options.paramName) + '=' + 344 358 encodeURIComponent(this.getToken()); 345 359 … … 349 363 if(this.options.defaultParams) 350 364 this.options.parameters += '&' + this.options.defaultParams; 351 365 352 366 new Ajax.Request(this.url, this.options); 353 367 }, … … 356 370 this.updateChoices(request.responseText); 357 371 } 358 359 372 }); 360 373 … … 394 407 // you support them. 395 408 396 Autocompleter.Local = Class.create(); 397 Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), { 409 Autocompleter.Local = Class.create(Autocompleter.Base, { 398 410 initialize: function(element, update, array, options) { 399 411 this.baseInitialize(element, update, options); … … 451 463 return "<ul>" + ret.join('') + "</ul>"; 452 464 } 453 }, options || { });465 }, options || { }); 454 466 } 455 467 }); 456 468 457 // AJAX in-place editor 458 // 459 // see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor 469 // AJAX in-place editor and collection editor 470 // Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007). 460 471 461 472 // Use this if you notice weird scrolling problems on some browsers, … … 468 479 } 469 480 470 Ajax.InPlaceEditor = Class.create(); 471 Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99"; 472 Ajax.InPlaceEditor.prototype = { 481 Ajax.InPlaceEditor = Class.create({ 473 482 initialize: function(element, url, options) { 474 483 this.url = url; 475 this.element = $(element); 476 477 this.options = Object.extend({ 478 paramName: "value", 479 okButton: true, 480 okText: "ok", 481 cancelLink: true, 482 cancelText: "cancel", 483 savingText: "Saving...", 484 clickToEditText: "Click to edit", 485 okText: "ok", 486 rows: 1, 487 onComplete: function(transport, element) { 488 new Effect.Highlight(element, {startcolor: this.options.highlightcolor}); 489 }, 490 onFailure: function(transport) { 491 alert("Error communicating with the server: " + transport.responseText.stripTags()); 492 }, 493 callback: function(form) { 494 return Form.serialize(form); 495 }, 496 handleLineBreaks: true, 497 loadingText: 'Loading...', 498 savingClassName: 'inplaceeditor-saving', 499 loadingClassName: 'inplaceeditor-loading', 500 formClassName: 'inplaceeditor-form', 501 highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor, 502 highlightendcolor: "#FFFFFF", 503 externalControl: null, 504 submitOnBlur: false, 505 ajaxOptions: {}, 506 evalScripts: false 507 }, options || {}); 508 509 if(!this.options.formId && this.element.id) { 510 this.options.formId = this.element.id + "-inplaceeditor"; 511 if ($(this.options.formId)) { 512 // there's already a form with that name, don't specify an id 513 this.options.formId = null; 514 } 515 } 516 517 if (this.options.externalControl) { 484 this.element = element = $(element); 485 this.prepareOptions(); 486 this._controls = { }; 487 arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!! 488 Object.extend(this.options, options || { }); 489 if (!this.options.formId && this.element.id) { 490 this.options.formId = this.element.id + '-inplaceeditor'; 491 if ($(this.options.formId)) 492 this.options.formId = ''; 493 } 494 if (this.options.externalControl) 518 495 this.options.externalControl = $(this.options.externalControl); 519 } 520 521 this.originalBackground = Element.getStyle(this.element, 'background-color'); 522 if (!this.originalBackground) { 523 this.originalBackground = "transparent"; 524 } 525 496 if (!this.options.externalControl) 497 this.options.externalControlOnly = false; 498 this._originalBackground = this.element.getStyle('background-color') || 'transparent'; 526 499 this.element.title = this.options.clickToEditText; 527 528 this.onclickListener = this.enterEditMode.bindAsEventListener(this); 529 this.mouseoverListener = this.enterHover.bindAsEventListener(this); 530 this.mouseoutListener = this.leaveHover.bindAsEventListener(this); 531 Event.observe(this.element, 'click', this.onclickListener); 532 Event.observe(this.element, 'mouseover', this.mouseoverListener); 533 Event.observe(this.element, 'mouseout', this.mouseoutListener); 534 if (this.options.externalControl) { 535 Event.observe(this.options.externalControl, 'click', this.onclickListener); 536 Event.observe(this.options.externalControl, 'mouseover', this.mouseoverListener); 537 Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener); 538 } 539 }, 540 enterEditMode: function(evt) { 541 if (this.saving) return; 542 if (this.editing) return; 543 this.editing = true; 544 this.onEnterEditMode(); 545 if (this.options.externalControl) { 546 Element.hide(this.options.externalControl); 547 } 548 Element.hide(this.element); 500 this._boundCancelHandler = this.handleFormCancellation.bind(this); 501 this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); 502 this._boundFailureHandler = this.handleAJAXFailure.bind(this); 503 this._boundSubmitHandler = this.handleFormSubmission.bind(this); 504 this._boundWrapperHandler = this.wrapUp.bind(this); 505 this.registerListeners(); 506 }, 507 checkForEscapeOrReturn: function(e) { 508 if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; 509 if (Event.KEY_ESC == e.keyCode) 510 this.handleFormCancellation(e); 511 else if (Event.KEY_RETURN == e.keyCode) 512 this.handleFormSubmission(e); 513 }, 514 createControl: function(mode, handler, extraClasses) { 515 var control = this.options[mode + 'Control']; 516 var text = this.options[mode + 'Text']; 517 if ('button' == control) { 518 var btn = document.createElement('input'); 519 btn.type = 'submit'; 520 btn.value = text; 521 btn.className = 'editor_' + mode + '_button'; 522 if ('cancel' == mode) 523 btn.onclick = this._boundCancelHandler; 524 this._form.appendChild(btn); 525 this._controls[mode] = btn; 526 } else if ('link' == control) { 527 var link = document.createElement('a'); 528 link.href = '#'; 529 link.appendChild(document.createTextNode(text)); 530 link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; 531 link.className = 'editor_' + mode + '_link'; 532 if (extraClasses) 533 link.className += ' ' + extraClasses; 534 this._form.appendChild(link); 535 this._controls[mode] = link; 536 } 537 }, 538 createEditField: function() { 539 var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); 540 var fld; 541 if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { 542 fld = document.createElement('input'); 543 fld.type = 'text'; 544 var size = this.options.size || this.options.cols || 0; 545 if (0 < size) fld.size = size; 546 } else { 547 fld = document.createElement('textarea'); 548 fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); 549 fld.cols = this.options.cols || 40; 550 } 551 fld.name = this.options.paramName; 552 fld.value = text; // No HTML breaks conversion anymore 553 fld.className = 'editor_field'; 554 if (this.options.submitOnBlur) 555 fld.onblur = this._boundSubmitHandler; 556 this._controls.editor = fld; 557 if (this.options.loadTextURL) 558 this.loadExternalText(); 559 this._form.appendChild(this._controls.editor); 560 }, 561 createForm: function() { 562 var ipe = this; 563 function addText(mode, condition) { 564 var text = ipe.options['text' + mode + 'Controls']; 565 if (!text || condition === false) return; 566 ipe._form.appendChild(document.createTextNode(text)); 567 }; 568 this._form = $(document.createElement('form')); 569 this._form.id = this.options.formId; 570 this._form.addClassName(this.options.formClassName); 571 this._form.onsubmit = this._boundSubmitHandler; 572 this.createEditField(); 573 if ('textarea' == this._controls.editor.tagName.toLowerCase()) 574 this._form.appendChild(document.createElement('br')); 575 if (this.options.onFormCustomization) 576 this.options.onFormCustomization(this, this._form); 577 addText('Before', this.options.okControl || this.options.cancelControl); 578 this.createControl('ok', this._boundSubmitHandler); 579 addText('Between', this.options.okControl && this.options.cancelControl); 580 this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); 581 addText('After', this.options.okControl || this.options.cancelControl); 582 }, 583 destroy: function() { 584 if (this._oldInnerHTML) 585 this.element.innerHTML = this._oldInnerHTML; 586 this.leaveEditMode(); 587 this.unregisterListeners(); 588 }, 589 enterEditMode: function(e) { 590 if (this._saving || this._editing) return; 591 this._editing = true; 592 this.triggerCallback('onEnterEditMode'); 593 if (this.options.externalControl) 594 this.options.externalControl.hide(); 595 this.element.hide(); 549 596 this.createForm(); 550 this.element.parentNode.insertBefore(this.form, this.element); 551 if (!this.options.loadTextURL) Field.scrollFreeActivate(this.editField); 552 // stop the event to avoid a page refresh in Safari 553 if (evt) { 554 Event.stop(evt); 555 } 556 return false; 557 }, 558 createForm: function() { 559 this.form = document.createElement("form"); 560 this.form.id = this.options.formId; 561 Element.addClassName(this.form, this.options.formClassName) 562 this.form.onsubmit = this.onSubmit.bind(this); 563 564 this.createEditField(); 565 566 if (this.options.textarea) { 567 var br = document.createElement("br"); 568 this.form.appendChild(br); 569 } 570 571 if (this.options.okButton) { 572 okButton = document.createElement("input"); 573 okButton.type = "submit"; 574 okButton.value = this.options.okText; 575 okButton.className = 'editor_ok_button'; 576 this.form.appendChild(okButton); 577 } 578 579 if (this.options.cancelLink) { 580 cancelLink = document.createElement("a"); 581 cancelLink.href = "#"; 582 cancelLink.appendChild(document.createTextNode(this.options.cancelText)); 583 cancelLink.onclick = this.onclickCancel.bind(this); 584 cancelLink.className = 'editor_cancel'; 585 this.form.appendChild(cancelLink); 586 } 587 }, 588 hasHTMLLineBreaks: function(string) { 589 if (!this.options.handleLineBreaks) return false; 590 return string.match(/<br/i) || string.match(/<p>/i); 591 }, 592 convertHTMLLineBreaks: function(string) { 593 return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<p>/gi, ""); 594 }, 595 createEditField: function() { 596 var text; 597 if(this.options.loadTextURL) { 598 text = this.options.loadingText; 599 } else { 600 text = this.getText(); 601 } 602 603 var obj = this; 604 605 if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) { 606 this.options.textarea = false; 607 var textField = document.createElement("input"); 608 textField.obj = this; 609 textField.type = "text"; 610 textField.name = this.options.paramName; 611 textField.value = text; 612 textField.style.backgroundColor = this.options.highlightcolor; 613 textField.className = 'editor_field'; 614 var size = this.options.size || this.options.cols || 0; 615 if (size != 0) textField.size = size; 616 if (this.options.submitOnBlur) 617 textField.onblur = this.onSubmit.bind(this); 618 this.editField = textField; 619 } else { 620 this.options.textarea = true; 621 var textArea = document.createElement("textarea"); 622 textArea.obj = this; 623 textArea.name = this.options.paramName; 624 textArea.value = this.convertHTMLLineBreaks(text); 625 textArea.rows = this.options.rows; 626 textArea.cols = this.options.cols || 40; 627 textArea.className = 'editor_field'; 628 if (this.options.submitOnBlur) 629 textArea.onblur = this.onSubmit.bind(this); 630 this.editField = textArea; 631 } 632 633 if(this.options.loadTextURL) { 634 this.loadExternalText(); 635 } 636 this.form.appendChild(this.editField); 597 this.element.parentNode.insertBefore(this._form, this.element); 598 if (!this.options.loadTextURL) 599 this.postProcessEditField(); 600 if (e) Event.stop(e); 601 }, 602 enterHover: function(e) { 603 if (this.options.hoverClassName) 604 this.element.addClassName(this.options.hoverClassName); 605 if (this._saving) return; 606 this.triggerCallback('onEnterHover'); 637 607 }, 638 608 getText: function() { 639 609 return this.element.innerHTML; 640 610 }, 611 handleAJAXFailure: function(transport) { 612 this.triggerCallback('onFailure', transport); 613 if (this._oldInnerHTML) { 614 this.element.innerHTML = this._oldInnerHTML; 615 this._oldInnerHTML = null; 616 } 617 }, 618 handleFormCancellation: function(e) { 619 this.wrapUp(); 620 if (e) Event.stop(e); 621 }, 622 handleFormSubmission: function(e) { 623 var form = this._form; 624 var value = $F(this._controls.editor); 625 this.prepareSubmission(); 626 var params = this.options.callback(form, value) || ''; 627 if (Object.isString(params)) 628 params = params.toQueryParams(); 629 params.editorId = this.element.id; 630 if (this.options.htmlResponse) { 631 var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); 632 Object.extend(options, { 633 parameters: params, 634 onComplete: this._boundWrapperHandler, 635 onFailure: this._boundFailureHandler 636 }); 637 new Ajax.Updater({ success: this.element }, this.url, options); 638 } else { 639 var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); 640 Object.extend(options, { 641 parameters: params, 642 onComplete: this._boundWrapperHandler, 643 onFailure: this._boundFailureHandler 644 }); 645 new Ajax.Request(this.url, options); 646 } 647 if (e) Event.stop(e); 648 }, 649 leaveEditMode: function() { 650 this.element.removeClassName(this.options.savingClassName); 651 this.removeForm(); 652 this.leaveHover(); 653 this.element.style.backgroundColor = this._originalBackground; 654 this.element.show(); 655 if (this.options.externalControl) 656 this.options.externalControl.show(); 657 this._saving = false; 658 this._editing = false; 659 this._oldInnerHTML = null; 660 this.triggerCallback('onLeaveEditMode'); 661 }, 662 leaveHover: function(e) { 663 if (this.options.hoverClassName) 664 this.element.removeClassName(this.options.hoverClassName); 665 if (this._saving) return; 666 this.triggerCallback('onLeaveHover'); 667 }, 641 668 loadExternalText: function() { 642 Element.addClassName(this.form, this.options.loadingClassName); 643 this.editField.disabled = true; 644 new Ajax.Request( 645 this.options.loadTextURL, 646 Object.extend({ 647 asynchronous: true, 648 onComplete: this.onLoadedExternalText.bind(this) 649 }, this.options.ajaxOptions) 650 ); 651 }, 652 onLoadedExternalText: function(transport) { 653 Element.removeClassName(this.form, this.options.loadingClassName); 654 this.editField.disabled = false; 655 this.editField.value = transport.responseText.stripTags(); 656 Field.scrollFreeActivate(this.editField); 657 }, 658 onclickCancel: function() { 659 this.onComplete(); 660 this.leaveEditMode(); 661 return false; 662 }, 663 onFailure: function(transport) { 664 this.options.onFailure(transport); 665 if (this.oldInnerHTML) { 666 this.element.innerHTML = this.oldInnerHTML; 667 this.oldInnerHTML = null; 668 } 669 return false; 670 }, 671 onSubmit: function() { 672 // onLoading resets these so we need to save them away for the Ajax call 673 var form = this.form; 674 var value = this.editField.value; 675 676 // do this first, sometimes the ajax call returns before we get a chance to switch on Saving... 677 // which means this will actually switch on Saving... *after* we've left edit mode causing Saving... 678 // to be displayed indefinitely 679 this.onLoading(); 680 681 if (this.options.evalScripts) { 682 new Ajax.Request( 683 this.url, Object.extend({ 684 parameters: this.options.callback(form, value), 685 onComplete: this.onComplete.bind(this), 686 onFailure: this.onFailure.bind(this), 687 asynchronous:true, 688 evalScripts:true 689 }, this.options.ajaxOptions)); 690 } else { 691 new Ajax.Updater( 692 { success: this.element, 693 // don't update on failure (this could be an option) 694 failure: null }, 695 this.url, Object.extend({ 696 parameters: this.options.callback(form, value), 697 onComplete: this.onComplete.bind(this), 698 onFailure: this.onFailure.bind(this) 699 }, this.options.ajaxOptions)); 700 } 701 // stop the event to avoid a page refresh in Safari 702 if (arguments.length > 1) { 703 Event.stop(arguments[0]); 704 } 705 return false; 706 }, 707 onLoading: function() { 708 this.saving = true; 669 this._form.addClassName(this.options.loadingClassName); 670 this._controls.editor.disabled = true; 671 var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); 672 Object.extend(options, { 673 parameters: 'editorId=' + encodeURIComponent(this.element.id), 674 onComplete: Prototype.emptyFunction, 675 onSuccess: function(transport) { 676 this._form.removeClassName(this.options.loadingClassName); 677 var text = transport.responseText; 678 if (this.options.stripLoadedTextTags) 679 text = text.stripTags(); 680 this._controls.editor.value = text; 681 this._controls.editor.disabled = false; 682 this.postProcessEditField(); 683 }.bind(this), 684 onFailure: this._boundFailureHandler 685 }); 686 new Ajax.Request(this.options.loadTextURL, options); 687 }, 688 postProcessEditField: function() { 689 var fpc = this.options.fieldPostCreation; 690 if (fpc) 691 $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate'](); 692 }, 693 prepareOptions: function() { 694 this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); 695 Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); 696 [this._extraDefaultOptions].flatten().compact().each(function(defs) { 697 Object.extend(this.options, defs); 698 }.bind(this)); 699 }, 700 prepareSubmission: function() { 701 this._saving = true; 709 702 this.removeForm(); 710 703 this.leaveHover(); 711 704 this.showSaving(); 712 705 }, 706 registerListeners: function() { 707 this._listeners = { }; 708 var listener; 709 $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { 710 listener = this[pair.value].bind(this); 711 this._listeners[pair.key] = listener; 712 if (!this.options.externalControlOnly) 713 this.element.observe(pair.key, listener); 714 if (this.options.externalControl) 715 this.options.externalControl.observe(pair.key, listener); 716 }.bind(this)); 717 }, 718 removeForm: function() { 719 if (!this._form) return; 720 this._form.remove(); 721 this._form = null; 722 this._controls = { }; 723 }, 713 724 showSaving: function() { 714 this. oldInnerHTML = this.element.innerHTML;725 this._oldInnerHTML = this.element.innerHTML; 715 726 this.element.innerHTML = this.options.savingText; 716 Element.addClassName(this.element, this.options.savingClassName); 717 this.element.style.backgroundColor = this.originalBackground; 718 Element.show(this.element); 719 }, 720 removeForm: function() { 721 if(this.form) { 722 if (this.form.parentNode) Element.remove(this.form); 723 this.form = null; 724 } 725 }, 726 enterHover: function() { 727 if (this.saving) return; 728 this.element.style.backgroundColor = this.options.highlightcolor; 729 if (this.effect) { 730 this.effect.cancel(); 731 } 732 Element.addClassName(this.element, this.options.hoverClassName) 733 }, 734 leaveHover: function() { 735 if (this.options.backgroundColor) { 736 this.element.style.backgroundColor = this.oldBackground; 737 } 738 Element.removeClassName(this.element, this.options.hoverClassName) 739 if (this.saving) return; 740 this.effect = new Effect.Highlight(this.element, { 741 startcolor: this.options.highlightcolor, 742 endcolor: this.options.highlightendcolor, 743 restorecolor: this.originalBackground 744 }); 745 }, 746 leaveEditMode: function() { 747 Element.removeClassName(this.element, this.options.savingClassName); 748 this.removeForm(); 749 this.leaveHover(); 750 this.element.style.backgroundColor = this.originalBackground; 751 Element.show(this.element); 752 if (this.options.externalControl) { 753 Element.show(this.options.externalControl); 754 } 755 this.editing = false; 756 this.saving = false; 757 this.oldInnerHTML = null; 758 this.onLeaveEditMode(); 759 }, 760 onComplete: function(transport) { 727 this.element.addClassName(this.options.savingClassName); 728 this.element.style.backgroundColor = this._originalBackground; 729 this.element.show(); 730 }, 731 triggerCallback: function(cbName, arg) { 732 if ('function' == typeof this.options[cbName]) { 733 this.options[cbName](this, arg); 734 } 735 }, 736 unregisterListeners: function() { 737 $H(this._listeners).each(function(pair) { 738 if (!this.options.externalControlOnly) 739 this.element.stopObserving(pair.key, pair.value); 740 if (this.options.externalControl) 741 this.options.externalControl.stopObserving(pair.key, pair.value); 742 }.bind(this)); 743 }, 744 wrapUp: function(transport) { 761 745 this.leaveEditMode(); 762 this.options.onComplete.bind(this)(transport, this.element); 763 }, 764 onEnterEditMode: function() {}, 765 onLeaveEditMode: function() {}, 766 dispose: function() { 767 if (this.oldInnerHTML) { 768 this.element.innerHTML = this.oldInnerHTML; 769 } 770 this.leaveEditMode(); 771 Event.stopObserving(this.element, 'click', this.onclickListener); 772 Event.stopObserving(this.element, 'mouseover', this.mouseoverListener); 773 Event.stopObserving(this.element, 'mouseout', this.mouseoutListener); 774 if (this.options.externalControl) { 775 Event.stopObserving(this.options.externalControl, 'click', this.onclickListener); 776 Event.stopObserving(this.options.externalControl, 'mouseover', this.mouseoverListener); 777 Event.stopObserving(this.options.externalControl, 'mouseout', this.mouseoutListener); 778 } 779 } 780 }; 781 782 Ajax.InPlaceCollectionEditor = Class.create(); 783 Object.extend(Ajax.InPlaceCollectionEditor.prototype, Ajax.InPlaceEditor.prototype); 784 Object.extend(Ajax.InPlaceCollectionEditor.prototype, { 785 createEditField: function() { 786 if (!this.cached_selectTag) { 787 var selectTag = document.createElement("select"); 788 var collection = this.options.collection || []; 789 var optionTag; 790 collection.each(function(e,i) { 791 optionTag = document.createElement("option"); 792 optionTag.value = (e instanceof Array) ? e[0] : e; 793 if((typeof this.options.value == 'undefined') && 794 ((e instanceof Array) ? this.element.innerHTML == e[1] : e == optionTag.value)) optionTag.selected = true; 795 if(this.options.value==optionTag.value) optionTag.selected = true; 796 optionTag.appendChild(document.createTextNode((e instanceof Array) ? e[1] : e)); 797 selectTag.appendChild(optionTag); 798 }.bind(this)); 799 this.cached_selectTag = selectTag; 800 } 801 802 this.editField = this.cached_selectTag; 803 if(this.options.loadTextURL) this.loadExternalText(); 804 this.form.appendChild(this.editField); 805 this.options.callback = function(form, value) { 806 return "value=" + encodeURIComponent(value); 807 } 746 // Can't use triggerCallback due to backward compatibility: requires 747 // binding + direct element 748 this._boundComplete(transport, this.element); 808 749 } 809 750 }); 751 752 Object.extend(Ajax.InPlaceEditor.prototype, { 753 dispose: Ajax.InPlaceEditor.prototype.destroy 754 }); 755 756 Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { 757 initialize: function($super, element, url, options) { 758 this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; 759 $super(element, url, options); 760 }, 761 762 createEditField: function() { 763 var list = document.createElement('select'); 764 list.name = this.options.paramName; 765 list.size = 1; 766 this._controls.editor = list; 767 this._collection = this.options.collection || []; 768 if (this.options.loadCollectionURL) 769 this.loadCollection(); 770 else 771 this.checkForExternalText(); 772 this._form.appendChild(this._controls.editor); 773 }, 774 775 loadCollection: function() { 776 this._form.addClassName(this.options.loadingClassName); 777 this.showLoadingText(this.options.loadingCollectionText); 778 var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); 779 Object.extend(options, { 780 parameters: 'editorId=' + encodeURIComponent(this.element.id), 781 onComplete: Prototype.emptyFunction, 782 onSuccess: function(transport) { 783 var js = transport.responseText.strip(); 784 if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check 785 throw 'Server returned an invalid collection representation.'; 786 this._collection = eval(js); 787 this.checkForExternalText(); 788 }.bind(this), 789 onFailure: this.onFailure 790 }); 791 new Ajax.Request(this.options.loadCollectionURL, options); 792 }, 793 794 showLoadingText: function(text) { 795 this._controls.editor.disabled = true; 796 var tempOption = this._controls.editor.firstChild; 797 if (!tempOption) { 798 tempOption = document.createElement('option'); 799 tempOption.value = ''; 800 this._controls.editor.appendChild(tempOption); 801 tempOption.selected = true; 802 } 803 tempOption.update((text || '').stripScripts().stripTags()); 804 }, 805 806 checkForExternalText: function() { 807 this._text = this.getText(); 808 if (this.options.loadTextURL) 809 this.loadExternalText(); 810 else 811 this.buildOptionList(); 812 }, 813 814 loadExternalText: function() { 815 this.showLoadingText(this.options.loadingText); 816 var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); 817 Object.extend(options, { 818 parameters: 'editorId=' + encodeURIComponent(this.element.id), 819 onComplete: Prototype.emptyFunction, 820 onSuccess: function(transport) { 821 this._text = transport.responseText.strip(); 822 this.buildOptionList(); 823 }.bind(this), 824 onFailure: this.onFailure 825 }); 826 new Ajax.Request(this.options.loadTextURL, options); 827 }, 828 829 buildOptionList: function() { 830 this._form.removeClassName(this.options.loadingClassName); 831 this._collection = this._collection.map(function(entry) { 832 return 2 === entry.length ? entry : [entry, entry].flatten(); 833 }); 834 var marker = ('value' in this.options) ? this.options.value : this._text; 835 var textFound = this._collection.any(function(entry) { 836 return entry[0] == marker; 837 }.bind(this)); 838 this._controls.editor.update(''); 839 var option; 840 this._collection.each(function(entry, index) { 841 option = document.createElement('option'); 842 option.value = entry[0]; 843 option.selected = textFound ? entry[0] == marker : 0 == index; 844 option.appendChild(document.createTextNode(entry[1])); 845 this._controls.editor.appendChild(option); 846 }.bind(this)); 847 this._controls.editor.disabled = false; 848 Field.scrollFreeActivate(this._controls.editor); 849 } 850 }); 851 852 //**** DEPRECATION LAYER FOR InPlace[Collection]Editor! **** 853 //**** This only exists for a while, in order to let **** 854 //**** users adapt to the new API. Read up on the new **** 855 //**** API and convert your code to it ASAP! **** 856 857 Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { 858 if (!options) return; 859 function fallback(name, expr) { 860 if (name in options || expr === undefined) return; 861 options[name] = expr; 862 }; 863 fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : 864 options.cancelLink == options.cancelButton == false ? false : undefined))); 865 fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : 866 options.okLink == options.okButton == false ? false : undefined))); 867 fallback('highlightColor', options.highlightcolor); 868 fallback('highlightEndColor', options.highlightendcolor); 869 }; 870 871 Object.extend(Ajax.InPlaceEditor, { 872 DefaultOptions: { 873 ajaxOptions: { }, 874 autoRows: 3, // Use when multi-line w/ rows == 1 875 cancelControl: 'link', // 'link'|'button'|false 876 cancelText: 'cancel', 877 clickToEditText: 'Click to edit', 878 externalControl: null, // id|elt 879 externalControlOnly: false, 880 fieldPostCreation: 'activate', // 'activate'|'focus'|false 881 formClassName: 'inplaceeditor-form', 882 formId: null, // id|elt 883 highlightColor: '#ffff99', 884 highlightEndColor: '#ffffff', 885 hoverClassName: '', 886 htmlResponse: true, 887 loadingClassName: 'inplaceeditor-loading', 888 loadingText: 'Loading...', 889 okControl: 'button', // 'link'|'button'|false 890 okText: 'ok', 891 paramName: 'value', 892 rows: 1, // If 1 and multi-line, uses autoRows 893 savingClassName: 'inplaceeditor-saving', 894 savingText: 'Saving...', 895 size: 0, 896 stripLoadedTextTags: false, 897 submitOnBlur: false, 898 textAfterControls: '', 899 textBeforeControls: '', 900 textBetweenControls: '' 901 }, 902 DefaultCallbacks: { 903 callback: function(form) { 904 return Form.serialize(form); 905 }, 906 onComplete: function(transport, element) { 907 // For backward compatibility, this one is bound to the IPE, and passes 908 // the element directly. It was too often customized, so we don't break it. 909 new Effect.Highlight(element, { 910 startcolor: this.options.highlightColor, keepBackgroundImage: true }); 911 }, 912 onEnterEditMode: null, 913 onEnterHover: function(ipe) { 914 ipe.element.style.backgroundColor = ipe.options.highlightColor; 915 if (ipe._effect) 916 ipe._effect.cancel(); 917 }, 918 onFailure: function(transport, ipe) { 919 alert('Error communication with the server: ' + transport.responseText.stripTags()); 920 }, 921 onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls. 922 onLeaveEditMode: null, 923 onLeaveHover: function(ipe) { 924 ipe._effect = new Effect.Highlight(ipe.element, { 925 startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, 926 restorecolor: ipe._originalBackground, keepBackgroundImage: true 927 }); 928 } 929 }, 930 Listeners: { 931 click: 'enterEditMode', 932 keydown: 'checkForEscapeOrReturn', 933 mouseover: 'enterHover', 934 mouseout: 'leaveHover' 935 } 936 }); 937 938 Ajax.InPlaceCollectionEditor.DefaultOptions = { 939 loadingCollectionText: 'Loading options...' 940 }; 810 941 811 942 // Delayed observer, like Form.Element.Observer, … … 813 944 // Ideal for live-search fields 814 945 815 Form.Element.DelayedObserver = Class.create(); 816 Form.Element.DelayedObserver.prototype = { 946 Form.Element.DelayedObserver = Class.create({ 817 947 initialize: function(element, delay, callback) { 818 948 this.delay = delay || 0.5; … … 833 963 this.callback(this.element, $F(this.element)); 834 964 } 835 } ;965 }); branches/1.1/data/web/sf/prototype/js/dragdrop.js
r3316 r7855 1 // script.aculo.us dragdrop.js v1. 7.0, Fri Jan 19 19:16:36 CET 20072 3 // Copyright (c) 2005 , 2006Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)4 // (c) 2005 , 2006Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)1 // script.aculo.us dragdrop.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008 2 3 // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 4 // (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) 5 5 // 6 6 // script.aculo.us is freely distributable under the terms of an MIT-style license. 7 7 // For details, see the script.aculo.us web site: http://script.aculo.us/ 8 8 9 if( typeof Effect == 'undefined')9 if(Object.isUndefined(Effect)) 10 10 throw("dragdrop.js requires including script.aculo.us' effects.js library"); 11 11 … … 23 23 hoverclass: null, 24 24 tree: false 25 }, arguments[1] || { });25 }, arguments[1] || { }); 26 26 27 27 // cache containers … … 29 29 options._containers = []; 30 30 var containment = options.containment; 31 if((typeof containment == 'object') && 32 (containment.constructor == Array)) { 31 if(Object.isArray(containment)) { 33 32 containment.each( function(c) { options._containers.push($(c)) }); 34 33 } else { … … 90 89 show: function(point, element) { 91 90 if(!this.drops.length) return; 92 var affected = []; 93 94 if(this.last_active) this.deactivate(this.last_active); 91 var drop, affected = []; 92 95 93 this.drops.each( function(drop) { 96 94 if(Droppables.isAffected(point, element, drop)) … … 98 96 }); 99 97 100 if(affected.length>0) {98 if(affected.length>0) 101 99 drop = Droppables.findDeepestChild(affected); 100 101 if(this.last_active && this.last_active != drop) this.deactivate(this.last_active); 102 if (drop) { 102 103 Position.within(drop.element, point[0], point[1]); 103 104 if(drop.onHover) 104 105 drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); 105 106 106 Droppables.activate(drop);107 if (drop != this.last_active) Droppables.activate(drop); 107 108 } 108 109 }, … … 113 114 114 115 if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) 115 if (this.last_active.onDrop) 116 this.last_active.onDrop(element, this.last_active.element, event); 116 if (this.last_active.onDrop) { 117 this.last_active.onDrop(element, this.last_active.element, event); 118 return true; 119 } 117 120 }, 118 121 … … 222 225 /*--------------------------------------------------------------------------*/ 223 226 224 var Draggable = Class.create(); 225 Draggable._dragging = {}; 226 227 Draggable.prototype = { 227 var Draggable = Class.create({ 228 228 initialize: function(element) { 229 229 var defaults = { … … 236 236 }, 237 237 endeffect: function(element) { 238 var toOpacity = typeof element._opacity == 'number'? element._opacity : 1.0;238 var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0; 239 239 new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, 240 240 queue: {scope:'_draggable', position:'end'}, … … 246 246 zindex: 1000, 247 247 revert: false, 248 quiet: false, 248 249 scroll: false, 249 250 scrollSensitivity: 20, … … 253 254 }; 254 255 255 if(!arguments[1] || typeof arguments[1].endeffect == 'undefined')256 if(!arguments[1] || Object.isUndefined(arguments[1].endeffect)) 256 257 Object.extend(defaults, { 257 258 starteffect: function(element) { … … 262 263 }); 263 264 264 var options = Object.extend(defaults, arguments[1] || { });265 var options = Object.extend(defaults, arguments[1] || { }); 265 266 266 267 this.element = $(element); 267 268 268 if(options.handle && (typeof options.handle == 'string'))269 if(options.handle && Object.isString(options.handle)) 269 270 this.handle = this.element.down('.'+options.handle, 0); 270 271 … … 279 280 Element.makePositioned(this.element); // fix IE 280 281 281 this.delta = this.currentDelta();282 282 this.options = options; 283 283 this.dragging = false; … … 301 301 302 302 initDrag: function(event) { 303 if( typeof Draggable._dragging[this.element] != 'undefined'&&303 if(!Object.isUndefined(Draggable._dragging[this.element]) && 304 304 Draggable._dragging[this.element]) return; 305 305 if(Event.isLeftClick(event)) { … … 324 324 startDrag: function(event) { 325 325 this.dragging = true; 326 if(!this.delta) 327 this.delta = this.currentDelta(); 326 328 327 329 if(this.options.zindex) { … … 332 334 if(this.options.ghosting) { 333 335 this._clone = this.element.cloneNode(true); 334 Position.absolutize(this.element); 336 this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute'); 337 if (!this.element._originallyAbsolute) 338 Position.absolutize(this.element); 335 339 this.element.parentNode.insertBefore(this._clone, this.element); 336 340 } … … 354 358 updateDrag: function(event, pointer) { 355 359 if(!this.dragging) this.startDrag(event); 356 Position.prepare(); 357 Droppables.show(pointer, this.element); 360 361 if(!this.options.quiet){ 362 Position.prepare(); 363 Droppables.show(pointer, this.element); 364 } 365 358 366 Draggables.notify('onDrag', this, event); 359 367 … … 383 391 384 392 // fix AppleWebKit rendering 385 if( navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);393 if(Prototype.Browser.WebKit) window.scrollBy(0,0); 386 394 387 395 Event.stop(event); … … 390 398 finishDrag: function(event, success) { 391 399 this.dragging = false; 400 401 if(this.options.quiet){ 402 Position.prepare(); 403 var pointer = [Event.pointerX(event), Event.pointerY(event)]; 404 Droppables.show(pointer, this.element); 405 } 392 406 393 407 if(this.options.ghosting) { 394 Position.relativize(this.element); 408 if (!this.element._originallyAbsolute) 409 Position.relativize(this.element); 410 delete this.element._originallyAbsolute; 395 411 Element.remove(this._clone); 396 412 this._clone = null; 397 413 } 398 414 399 if(success) Droppables.fire(event, this.element); 415 var dropped = false; 416 if(success) { 417 dropped = Droppables.fire(event, this.element); 418 if (!dropped) dropped = false; 419 } 420 if(dropped && this.options.onDropped) this.options.onDropped(this.element); 400 421 Draggables.notify('onEnd', this, event); 401 422 402 423 var revert = this.options.revert; 403 if(revert && typeof revert == 'function') revert = revert(this.element);424 if(revert && Object.isFunction(revert)) revert = revert(this.element); 404 425 405 426 var d = this.currentDelta(); 406 427 if(revert && this.options.reverteffect) { 407 this.options.reverteffect(this.element, 408 d[1]-this.delta[1], d[0]-this.delta[0]); 428 if (dropped == 0 || revert != 'failure') 429 this.options.reverteffect(this.element, 430 d[1]-this.delta[1], d[0]-this.delta[0]); 409 431 } else { 410 432 this.delta = d; … … 454 476 455 477 if(this.options.snap) { 456 if( typeof this.options.snap == 'function') {478 if(Object.isFunction(this.options.snap)) { 457 479 p = this.options.snap(p[0],p[1],this); 458 480 } else { 459 if( this.options.snap instanceof Array) {481 if(Object.isArray(this.options.snap)) { 460 482 p = p.map( function(v, i) { 461 return Math.round(v/this.options.snap[i])*this.options.snap[i] }.bind(this))483 return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this)) 462 484 } else { 463 485 p = p.map( function(v) { 464 return Math.round(v/this.options.snap)*this.options.snap }.bind(this))486 return (v/this.options.snap).round()*this.options.snap }.bind(this)) 465 487 } 466 488 }} … … 546 568 return { top: T, left: L, width: W, height: H }; 547 569 } 548 } 570 }); 571 572 Draggable._dragging = { }; 549 573 550 574 /*--------------------------------------------------------------------------*/ 551 575 552 var SortableObserver = Class.create(); 553 SortableObserver.prototype = { 576 var SortableObserver = Class.create({ 554 577 initialize: function(element, observer) { 555 578 this.element = $(element); … … 567 590 this.observer(this.element) 568 591 } 569 } 592 }); 570 593 571 594 var Sortable = { 572 595 SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/, 573 596 574 sortables: { },597 sortables: { }, 575 598 576 599 _findRootElement: function(element) { … … 615 638 hoverclass: null, 616 639 ghosting: false, 640 quiet: false, 617 641 scroll: false, 618 642 scrollSensitivity: 20, 619 643 scrollSpeed: 15, 620 644 format: this.SERIALIZE_RULE, 645 646 // these take arrays of elements or ids and can be 647 // used for better initialization performance 648 elements: false, 649 handles: false, 650 621 651 onChange: Prototype.emptyFunction, 622 652 onUpdate: Prototype.emptyFunction 623 }, arguments[1] || { });653 }, arguments[1] || { }); 624 654 625 655 // clear any old sortable with same element … … 629 659 var options_for_draggable = { 630 660 revert: true, 661 quiet: options.quiet, 631 662 scroll: options.scroll, 632 663 scrollSpeed: options.scrollSpeed, … … 682 713 } 683 714 684 (this.findElements(element, options) || []).each( function(e) { 685 // handles are per-draggable 686 var handle = options.handle ? 687 $(e).down('.'+options.handle,0) : e; 715 (options.elements || this.findElements(element, options) || []).each( function(e,i) { 716 var handle = options.handles ? $(options.handles[i]) : 717 (options.handle ? $(e).select('.' + options.handle)[0] : e); 688 718 options.draggables.push( 689 719 new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); … … 845 875 name: element.id, 846 876 format: sortableOptions.format 847 }, arguments[1] || { });877 }, arguments[1] || { }); 848 878 849 879 var root = { … … 869 899 sequence: function(element) { 870 900 element = $(element); 871 var options = Object.extend(this.options(element), arguments[1] || { });901 var options = Object.extend(this.options(element), arguments[1] || { }); 872 902 873 903 return $(this.findElements(element, options) || []).map( function(item) { … … 878 908 setSequence: function(element, new_sequence) { 879 909 element = $(element); 880 var options = Object.extend(this.options(element), arguments[2] || { });881 882 var nodeMap = { };910 var options = Object.extend(this.options(element), arguments[2] || { }); 911 912 var nodeMap = { }; 883 913 this.findElements(element, options).each( function(n) { 884 914 if (n.id.match(options.format)) … … 898 928 serialize: function(element) { 899 929 element = $(element); 900 var options = Object.extend(Sortable.options(element), arguments[1] || { });930 var options = Object.extend(Sortable.options(element), arguments[1] || { }); 901 931 var name = encodeURIComponent( 902 932 (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); … … 922 952 } 923 953 924 Element.findChildren = function(element, only, recursive, tagName) { 954 Element.findChildren = function(element, only, recursive, tagName) { 925 955 if(!element.hasChildNodes()) return null; 926 956 tagName = tagName.toUpperCase(); branches/1.1/data/web/sf/prototype/js/effects.js
r3316 r7855 1 // script.aculo.us effects.js v1. 7.0, Fri Jan 19 19:16:36 CET 20072 3 // Copyright (c) 2005 , 2006Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)1 // script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008 2 3 // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 4 4 // Contributors: 5 5 // Justin Palmer (http://encytemedia.com/) … … 14 14 String.prototype.parseColor = function() { 15 15 var color = '#'; 16 if (this.slice(0,4) == 'rgb(') {16 if (this.slice(0,4) == 'rgb(') { 17 17 var cols = this.slice(4,this.length-1).split(','); 18 18 var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); 19 19 } else { 20 if (this.slice(0,1) == '#') {21 if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();22 if (this.length==7) color = this.toLowerCase();20 if (this.slice(0,1) == '#') { 21 if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); 22 if (this.length==7) color = this.toLowerCase(); 23 23 } 24 24 } 25 return (color.length==7 ? color : (arguments[0] || this));26 } 25 return (color.length==7 ? color : (arguments[0] || this)); 26 }; 27 27 28 28 /*--------------------------------------------------------------------------*/ … … 33 33 (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); 34 34 }).flatten().join(''); 35 } 35 }; 36 36 37 37 Element.collectTextNodesIgnoreClass = function(element, className) { … … 41 41 Element.collectTextNodesIgnoreClass(node, className) : '')); 42 42 }).flatten().join(''); 43 } 43 }; 44 44 45 45 Element.setContentZoom = function(element, percent) { 46 46 element = $(element); 47 47 element.setStyle({fontSize: (percent/100) + 'em'}); 48 if (navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);48 if (Prototype.Browser.WebKit) window.scrollBy(0,0); 49 49 return element; 50 } 51 52 Element.getOpacity = function(element){ 53 return $(element).getStyle('opacity'); 54 } 55 56 Element.setOpacity = function(element, value){ 57 return $(element).setStyle({opacity:value}); 58 } 50 }; 59 51 60 52 Element.getInlineOpacity = function(element){ 61 53 return $(element).style.opacity || ''; 62 } 54 }; 63 55 64 56 Element.forceRerendering = function(element) { … … 73 65 /*--------------------------------------------------------------------------*/ 74 66 75 Array.prototype.call = function() {76 var args = arguments;77 this.each(function(f){ f.apply(this, args) });78 }79 80 /*--------------------------------------------------------------------------*/81 82 67 var Effect = { 83 68 _elementDoesNotExistError: { … … 85 70 message: 'The specified DOM element does not exist, but is required for this effect to operate' 86 71 }, 72 Transitions: { 73 linear: Prototype.K, 74 sinoidal: function(pos) { 75 return (-Math.cos(pos*Math.PI)/2) + 0.5; 76 }, 77 reverse: function(pos) { 78 return 1-pos; 79 }, 80 flicker: function(pos) { 81 var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; 82 return pos > 1 ? 1 : pos; 83 }, 84 wobble: function(pos) { 85 return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; 86 }, 87 pulse: function(pos, pulses) { 88 pulses = pulses || 5; 89 return ( 90 ((pos % (1/pulses)) * pulses).round() == 0 ? 91 ((pos * pulses * 2) - (pos * pulses * 2).floor()) : 92 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor()) 93 ); 94 }, 95 spring: function(pos) { 96 return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); 97 }, 98 none: function(pos) { 99 return 0; 100 }, 101 full: function(pos) { 102 return 1; 103 } 104 }, 105 DefaultOptions: { 106 duration: 1.0, // seconds 107 fps: 100, // 100= assume 66fps max. 108 sync: false, // true for combining 109 from: 0.0, 110 to: 1.0, 111 delay: 0.0, 112 queue: 'parallel' 113 }, 87 114 tagifyText: function(element) { 88 if(typeof Builder == 'undefined')89 throw("Effect.tagifyText requires including script.aculo.us' builder.js library");90 91 115 var tagifyStyle = 'position:relative'; 92 if (/MSIE/.test(navigator.userAgent) && !window.opera) tagifyStyle += ';zoom:1';116 if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; 93 117 94 118 element = $(element); 95 119 $A(element.childNodes).each( function(child) { 96 if (child.nodeType==3) {120 if (child.nodeType==3) { 97 121 child.nodeValue.toArray().each( function(character) { 98 122 element.insertBefore( 99 Builder.node('span',{style: tagifyStyle},123 new Element('span', {style: tagifyStyle}).update( 100 124 character == ' ' ? String.fromCharCode(160) : character), 101 125 child); … … 107 131 multiple: function(element, effect) { 108 132 var elements; 109 if (((typeof element == 'object') ||110 (typeof element == 'function')) &&133 if (((typeof element == 'object') || 134 Object.isFunction(element)) && 111 135 (element.length)) 112 136 elements = element; … … 117 141 speed: 0.1, 118 142 delay: 0.0 119 }, arguments[2] || { });143 }, arguments[2] || { }); 120 144 var masterDelay = options.delay; 121 145 … … 134 158 var options = Object.extend({ 135 159 queue: { position:'end', scope:(element.id || 'global'), limit: 1 } 136 }, arguments[2] || { });160 }, arguments[2] || { }); 137 161 Effect[element.visible() ? 138 162 Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); … … 140 164 }; 141 165 142 var Effect2 = Effect; // deprecated 143 144 /* ------------- transitions ------------- */ 145 146 Effect.Transitions = { 147 linear: Prototype.K, 148 sinoidal: function(pos) { 149 return (-Math.cos(pos*Math.PI)/2) + 0.5; 150 }, 151 reverse: function(pos) { 152 return 1-pos; 153 }, 154 flicker: function(pos) { 155 return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; 156 }, 157 wobble: function(pos) { 158 return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; 159 }, 160 pulse: function(pos, pulses) { 161 pulses = pulses || 5; 162 return ( 163 Math.round((pos % (1/pulses)) * pulses) == 0 ? 164 ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) : 165 1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) 166 ); 167 }, 168 none: function(pos) { 169 return 0; 170 }, 171 full: function(pos) { 172 return 1; 173 } 174 }; 166 Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; 175 167 176 168 /* ------------- core effects ------------- */ 177 169 178 Effect.ScopedQueue = Class.create(); 179 Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { 170 Effect.ScopedQueue = Class.create(Enumerable, { 180 171 initialize: function() { 181 172 this.effects = []; 182 this.interval = null; 173 this.interval = null; 183 174 }, 184 175 _each: function(iterator) { … … 188 179 var timestamp = new Date().getTime(); 189 180 190 var position = (typeof effect.options.queue == 'string') ?181 var position = Object.isString(effect.options.queue) ? 191 182 effect.options.queue : effect.options.queue.position; 192 183 … … 211 202 effect.finishOn += timestamp; 212 203 213 if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))204 if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) 214 205 this.effects.push(effect); 215 206 216 if (!this.interval)207 if (!this.interval) 217 208 this.interval = setInterval(this.loop.bind(this), 15); 218 209 }, 219 210 remove: function(effect) { 220 211 this.effects = this.effects.reject(function(e) { return e==effect }); 221 if (this.effects.length == 0) {212 if (this.effects.length == 0) { 222 213 clearInterval(this.interval); 223 214 this.interval = null; … … 227 218 var timePos = new Date().getTime(); 228 219 for(var i=0, len=this.effects.length;i<len;i++) 229 if(this.effects[i])this.effects[i].loop(timePos);220 this.effects[i] && this.effects[i].loop(timePos); 230 221 } 231 222 }); … … 234 225 instances: $H(), 235 226 get: function(queueName) { 236 if(typeof queueName != 'string') return queueName; 237 238 if(!this.instances[queueName]) 239 this.instances[queueName] = new Effect.ScopedQueue(); 240 241 return this.instances[queueName]; 242 } 243 } 227 if (!Object.isString(queueName)) return queueName; 228 229 return this.instances.get(queueName) || 230 this.instances.set(queueName, new Effect.ScopedQueue()); 231 } 232 }; 244 233 Effect.Queue = Effect.Queues.get('global'); 245 234 246 Effect.DefaultOptions = { 247 transition: Effect.Transitions.sinoidal, 248 duration: 1.0, // seconds 249 fps: 60.0, // max. 60fps due to Effect.Queue implementation 250 sync: false, // true for combining 251 from: 0.0, 252 to: 1.0, 253 delay: 0.0, 254 queue: 'parallel' 255 } 256 257 Effect.Base = function() {}; 258 Effect.Base.prototype = { 235 Effect.Base = Class.create({ 259 236 position: null, 260 237 start: function(options) { 261 this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {}); 238 function codeForEvent(options,eventName){ 239 return ( 240 (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') + 241 (options[eventName] ? 'this.options.'+eventName+'(this);' : '') 242 ); 243 } 244 if (options && options.transition === false) options.transition = Effect.Transitions.linear; 245 this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { }); 262 246 this.currentFrame = 0; 263 247 this.state = 'idle'; 264 248 this.startOn = this.options.delay*1000; 265 this.finishOn = this.startOn + (this.options.duration*1000); 249 this.finishOn = this.startOn+(this.options.duration*1000); 250 this.fromToDelta = this.options.to-this.options.from; 251 this.totalTime = this.finishOn-this.startOn; 252 this.totalFrames = this.options.fps*this.options.duration; 253 254 eval('this.render = function(pos){ '+ 255 'if (this.state=="idle"){this.state="running";'+ 256 codeForEvent(this.options,'beforeSetup')+ 257 (this.setup ? 'this.setup();':'')+ 258 codeForEvent(this.options,'afterSetup')+ 259 '};if (this.state=="running"){'+ 260 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+ 261 'this.position=pos;'+ 262 codeForEvent(this.options,'beforeUpdate')+ 263 (this.update ? 'this.update(pos);':'')+ 264 codeForEvent(this.options,'afterUpdate')+ 265 '}}'); 266 266 267 this.event('beforeStart'); 267 if (!this.options.sync)268 Effect.Queues.get( typeof this.options.queue == 'string'?268 if (!this.options.sync) 269 Effect.Queues.get(Object.isString(this.options.queue) ? 269 270 'global' : this.options.queue.scope).add(this); 270 271 }, 271 272 loop: function(timePos) { 272 if (timePos >= this.startOn) {273 if (timePos >= this.finishOn) {273 if (timePos >= this.startOn) { 274 if (timePos >= this.finishOn) { 274 275 this.render(1.0); 275 276 this.cancel(); 276 277 this.event('beforeFinish'); 277 if (this.finish) this.finish();278 if (this.finish) this.finish(); 278 279 this.event('afterFinish'); 279 280 return; 280 281 } 281 var pos = (timePos - this.startOn) / (this.finishOn - this.startOn);282 var frame = Math.round(pos * this.options.fps * this.options.duration);283 if (frame > this.currentFrame) {282 var pos = (timePos - this.startOn) / this.totalTime, 283 frame = (pos * this.totalFrames).round(); 284 if (frame > this.currentFrame) { 284 285 this.render(pos); 285 286 this.currentFrame = frame; … … 287 288 } 288 289 }, 289 render: function(pos) {290 if(this.state == 'idle') {291 this.state = 'running';292 this.event('beforeSetup');293 if(this.setup) this.setup();294 this.event('afterSetup');295 }296 if(this.state == 'running') {297 if(this.options.transition) pos = this.options.transition(pos);298 pos *= (this.options.to-this.options.from);299 pos += this.options.from;300 this.position = pos;301 this.event('beforeUpdate');302 if(this.update) this.update(pos);303 this.event('afterUpdate');304 }305 },306 290 cancel: function() { 307 if (!this.options.sync)308 Effect.Queues.get( typeof this.options.queue == 'string'?291 if (!this.options.sync) 292 Effect.Queues.get(Object.isString(this.options.queue) ? 309 293 'global' : this.options.queue.scope).remove(this); 310 294 this.state = 'finished'; 311 295 }, 312 296 event: function(eventName) { 313 if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);314 if (this.options[eventName]) this.options[eventName](this);297 if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); 298 if (this.options[eventName]) this.options[eventName](this); 315 299 }, 316 300 inspect: function() { 317 301 var data = $H(); 318 302 for(property in this) 319 if (typeof this[property] != 'function') data[property] = this[property];303 if (!Object.isFunction(this[property])) data.set(property, this[property]); 320 304 return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>'; 321 305 } 322 } 323 324 Effect.Parallel = Class.create(); 325 Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), { 306 }); 307 308 Effect.Parallel = Class.create(Effect.Base, { 326 309 initialize: function(effects) { 327 310 this.effects = effects || []; … … 336 319 effect.cancel(); 337 320 effect.event('beforeFinish'); 338 if (effect.finish) effect.finish(position);321 if (effect.finish) effect.finish(position); 339 322 effect.event('afterFinish'); 340 323 }); … … 342 325 }); 343 326 344 Effect.Event = Class.create(); 345 Object.extend(Object.extend(Effect.Event.prototype, Effect.Base.prototype), { 327 Effect.Tween = Class.create(Effect.Base, { 328 initialize: function(object, from, to) { 329 object = Object.isString(object) ? $(object) : object; 330 var args = $A(arguments), method = args.last(), 331 options = args.length == 5 ? args[3] : null; 332 this.method = Object.isFunction(method) ? method.bind(object) : 333 Object.isFunction(object[method]) ? object[method].bind(object) : 334 function(value) { object[method] = value }; 335 this.start(Object.extend({ from: from, to: to }, options || { })); 336 }, 337 update: function(position) { 338 this.method(position); 339 } 340 }); 341 342 Effect.Event = Class.create(Effect.Base, { 346 343 initialize: function() { 347 var options = Object.extend({ 348 duration: 0 349 }, arguments[0] || {}); 350 this.start(options); 344 this.start(Object.extend({ duration: 0 }, arguments[0] || { })); 351 345 }, 352 346 update: Prototype.emptyFunction 353 347 }); 354 348 355 Effect.Opacity = Class.create(); 356 Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), { 349 Effect.Opacity = Class.create(Effect.Base, { 357 350 initialize: function(element) { 358 351 this.element = $(element); 359 if (!this.element) throw(Effect._elementDoesNotExistError);352 if (!this.element) throw(Effect._elementDoesNotExistError); 360 353 // make this work on IE on elements without 'layout' 361 if (/MSIE/.test(navigator.userAgent) && !window.opera&& (!this.element.currentStyle.hasLayout))354 if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) 362 355 this.element.setStyle({zoom: 1}); 363 356 var options = Object.extend({ 364 357 from: this.element.getOpacity() || 0.0, 365 358 to: 1.0 366 }, arguments[1] || { });359 }, arguments[1] || { }); 367 360 this.start(options); 368 361 }, … … 372 365 }); 373 366 374 Effect.Move = Class.create(); 375 Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), { 367 Effect.Move = Class.create(Effect.Base, { 376 368 initialize: function(element) { 377 369 this.element = $(element); 378 if (!this.element) throw(Effect._elementDoesNotExistError);370 if (!this.element) throw(Effect._elementDoesNotExistError); 379 371 var options = Object.extend({ 380 372 x: 0, 381 373 y: 0, 382 374 mode: 'relative' 383 }, arguments[1] || { });375 }, arguments[1] || { }); 384 376 this.start(options); 385 377 }, 386 378 setup: function() { 387 // Bug in Opera: Opera returns the "real" position of a static element or388 // relative element that does not have top/left explicitly set.389 // ==> Always set top and left for position relative elements in your stylesheets390 // (to 0 if you do not need them)391 379 this.element.makePositioned(); 392 380 this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); 393 381 this.originalTop = parseFloat(this.element.getStyle('top') || '0'); 394 if(this.options.mode == 'absolute') { 395 // absolute movement, so we need to calc deltaX and deltaY 382 if (this.options.mode == 'absolute') { 396 383 this.options.x = this.options.x - this.originalLeft; 397 384 this.options.y = this.options.y - this.originalTop; … … 400 387 update: function(position) { 401 388 this.element.setStyle({ 402 left: Math.round(this.options.x * position + this.originalLeft) + 'px',403 top: Math.round(this.options.y * position + this.originalTop) + 'px'389 left: (this.options.x * position + this.originalLeft).round() + 'px', 390 top: (this.options.y * position + this.originalTop).round() + 'px' 404 391 }); 405 392 } … … 409 396 Effect.MoveBy = function(element, toTop, toLeft) { 410 397 return new Effect.Move(element, 411 Object.extend({ x: toLeft, y: toTop }, arguments[3] || {})); 412 }; 413 414 Effect.Scale = Class.create(); 415 Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), { 398 Object.extend({ x: toLeft, y: toTop }, arguments[3] || { })); 399 }; 400 401 Effect.Scale = Class.create(Effect.Base, { 416 402 initialize: function(element, percent) { 417 403 this.element = $(element); 418 if (!this.element) throw(Effect._elementDoesNotExistError);404 if (!this.element) throw(Effect._elementDoesNotExistError); 419 405 var options = Object.extend({ 420 406 scaleX: true, … … 422 408 scaleContent: true, 423 409 scaleFromCenter: false, 424 scaleMode: 'box', // 'box' or 'contents' or { } with provided values410 scaleMode: 'box', // 'box' or 'contents' or { } with provided values 425 411 scaleFrom: 100.0, 426 412 scaleTo: percent 427 }, arguments[2] || { });413 }, arguments[2] || { }); 428 414 this.start(options); 429 415 }, … … 432 418 this.elementPositioning = this.element.getStyle('position'); 433 419 434 this.originalStyle = { };420 this.originalStyle = { }; 435 421 ['top','left','width','height','fontSize'].each( function(k) { 436 422 this.originalStyle[k] = this.element.style[k]; … … 442 428 var fontSize = this.element.getStyle('font-size') || '100%'; 443 429 ['em','px','%','pt'].each( function(fontSizeType) { 444 if (fontSize.indexOf(fontSizeType)>0) {430 if (fontSize.indexOf(fontSizeType)>0) { 445 431 this.fontSize = parseFloat(fontSize); 446 432 this.fontSizeType = fontSizeType; … … 451 437 452 438 this.dims = null; 453 if (this.options.scaleMode=='box')439 if (this.options.scaleMode=='box') 454 440 this.dims = [this.element.offsetHeight, this.element.offsetWidth]; 455 if (/^content/.test(this.options.scaleMode))441 if (/^content/.test(this.options.scaleMode)) 456 442 this.dims = [this.element.scrollHeight, this.element.scrollWidth]; 457 if (!this.dims)443 if (!this.dims) 458 444 this.dims = [this.options.scaleMode.originalHeight, 459 445 this.options.scaleMode.originalWidth]; … … 461 447 update: function(position) { 462 448 var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); 463 if (this.options.scaleContent && this.fontSize)449 if (this.options.scaleContent && this.fontSize) 464 450 this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); 465 451 this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); 466 452 }, 467 453 finish: function(position) { 468 if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);454 if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); 469 455 }, 470 456 setDimensions: function(height, width) { 471 var d = { };472 if (this.options.scaleX) d.width = Math.round(width) + 'px';473 if (this.options.scaleY) d.height = Math.round(height) + 'px';474 if (this.options.scaleFromCenter) {457 var d = { }; 458 if (this.options.scaleX) d.width = width.round() + 'px'; 459 if (this.options.scaleY) d.height = height.round() + 'px'; 460 if (this.options.scaleFromCenter) { 475 461 var topd = (height - this.dims[0])/2; 476 462 var leftd = (width - this.dims[1])/2; 477 if (this.elementPositioning == 'absolute') {478 if (this.options.scaleY) d.top = this.originalTop-topd + 'px';479 if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';463 if (this.elementPositioning == 'absolute') { 464 if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; 465 if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; 480 466 } else { 481 if (this.options.scaleY) d.top = -topd + 'px';482 if (this.options.scaleX) d.left = -leftd + 'px';467 if (this.options.scaleY) d.top = -topd + 'px'; 468 if (this.options.scaleX) d.left = -leftd + 'px'; 483 469 } 484 470 } … … 487 473 }); 488 474 489 Effect.Highlight = Class.create(); 490 Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), { 475 Effect.Highlight = Class.create(Effect.Base, { 491 476 initialize: function(element) { 492 477 this.element = $(element); 493 if (!this.element) throw(Effect._elementDoesNotExistError);494 var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });478 if (!this.element) throw(Effect._elementDoesNotExistError); 479 var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); 495 480 this.start(options); 496 481 }, 497 482 setup: function() { 498 483 // Prevent executing on elements not in the layout flow 499 if (this.element.getStyle('display')=='none') { this.cancel(); return; }484 if (this.element.getStyle('display')=='none') { this.cancel(); return; } 500 485 // Disable background image during the effect 501 this.oldStyle = { };486 this.oldStyle = { }; 502 487 if (!this.options.keepBackgroundImage) { 503 488 this.oldStyle.backgroundImage = this.element.getStyle('background-image'); 504 489 this.element.setStyle({backgroundImage: 'none'}); 505 490 } 506 if (!this.options.endcolor)491 if (!this.options.endcolor) 507 492 this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); 508 if (!this.options.restorecolor)493 if (!this.options.restorecolor) 509 494 this.options.restorecolor = this.element.getStyle('background-color'); 510 495 // init color calculations … … 514 499 update: function(position) { 515 500 this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ 516 return m+( Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });501 return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) }); 517 502 }, 518 503 finish: function() { … … 523 508 }); 524 509 525 Effect.ScrollTo = Class.create(); 526 Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), { 527 initialize: function(element) { 528 this.element = $(element); 529 this.start(arguments[1] || {}); 530 }, 531 setup: function() { 532 Position.prepare(); 533 var offsets = Position.cumulativeOffset(this.element); 534 if(this.options.offset) offsets[1] += this.options.offset; 535 var max = window.innerHeight ? 536 window.height - window.innerHeight : 537 document.body.scrollHeight - 538 (document.documentElement.clientHeight ? 539 document.documentElement.clientHeight : document.body.clientHeight); 540 this.scrollStart = Position.deltaY; 541 this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart; 542 }, 543 update: function(position) { 544 Position.prepare(); 545 window.scrollTo(Position.deltaX, 546 this.scrollStart + (position*this.delta)); 547 } 548 }); 510 Effect.ScrollTo = function(element) { 511 var options = arguments[1] || { }, 512 scrollOffsets = document.viewport.getScrollOffsets(), 513 elementOffsets = $(element).cumulativeOffset(), 514 max = (window.height || document.body.scrollHeight) - document.viewport.getHeight(); 515 516 if (options.offset) elementOffsets[1] += options.offset; 517 518 return new Effect.Tween(null, 519 scrollOffsets.top, 520 elementOffsets[1] > max ? max : elementOffsets[1], 521 options, 522 function(p){ scrollTo(scrollOffsets.left, p.round()) } 523 ); 524 }; 549 525 550 526 /* ------------- combination effects ------------- */ … … 554 530 var oldOpacity = element.getInlineOpacity(); 555 531 var options = Object.extend({ 556 from: element.getOpacity() || 1.0, 557 to: 0.0, 558 afterFinishInternal: function(effect) { 559 if(effect.options.to!=0) return; 560 effect.element.hide().setStyle({opacity: oldOpacity}); 561 }}, arguments[1] || {}); 532 from: element.getOpacity() || 1.0, 533 to: 0.0, 534 afterFinishInternal: function(effect) { 535 if (effect.options.to!=0) return; 536 effect.element.hide().setStyle({opacity: oldOpacity}); 537 } 538 }, arguments[1] || { }); 562 539 return new Effect.Opacity(element,options); 563 } 540 }; 564 541 565 542 Effect.Appear = function(element) { … … 574 551 beforeSetup: function(effect) { 575 552 effect.element.setOpacity(effect.options.from).show(); 576 }}, arguments[1] || { });553 }}, arguments[1] || { }); 577 554 return new Effect.Opacity(element,options); 578 } 555 }; 579 556 580 557 Effect.Puff = function(element) { … … 598 575 afterFinishInternal: function(effect) { 599 576 effect.effects[0].element.hide().setStyle(oldStyle); } 600 }, arguments[1] || { })577 }, arguments[1] || { }) 601 578 ); 602 } 579 }; 603 580 604 581 Effect.BlindUp = function(element) { … … 612 589 effect.element.hide().undoClipping(); 613 590 } 614 }, arguments[1] || { })591 }, arguments[1] || { }) 615 592 ); 616 } 593 }; 617 594 618 595 Effect.BlindDown = function(element) { … … 631 608 effect.element.undoClipping(); 632 609 } 633 }, arguments[1] || { }));634 } 610 }, arguments[1] || { })); 611 }; 635 612 636 613 Effect.SwitchOff = function(element) { … … 653 630 }) 654 631 } 655 }, arguments[1] || { }));656 } 632 }, arguments[1] || { })); 633 }; 657 634 658 635 Effect.DropOut = function(element) { … … 673 650 effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); 674 651 } 675 }, arguments[1] || { }));676 } 652 }, arguments[1] || { })); 653 }; 677 654 678 655 Effect.Shake = function(element) { 679 656 element = $(element); 657 var options = Object.extend({ 658 distance: 20, 659 duration: 0.5 660 }, arguments[1] || {}); 661 var distance = parseFloat(options.distance); 662 var split = parseFloat(options.duration) / 10.0; 680 663 var oldStyle = { 681 664 top: element.getStyle('top'), 682 665 left: element.getStyle('left') }; 683 return new Effect.Move(element, 684 { x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {666 return new Effect.Move(element, 667 { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { 685 668 new Effect.Move(effect.element, 686 { x: - 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {669 { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { 687 670 new Effect.Move(effect.element, 688 { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {671 { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { 689 672 new Effect.Move(effect.element, 690 { x: - 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {673 { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { 691 674 new Effect.Move(effect.element, 692 { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {675 { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { 693 676 new Effect.Move(effect.element, 694 { x: - 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {677 { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { 695 678 effect.element.undoPositioned().setStyle(oldStyle); 696 679 }}) }}) }}) }}) }}) }}); 697 } 680 }; 698 681 699 682 Effect.SlideDown = function(element) { … … 711 694 effect.element.makePositioned(); 712 695 effect.element.down().makePositioned(); 713 if (window.opera) effect.element.setStyle({top: ''});696 if (window.opera) effect.element.setStyle({top: ''}); 714 697 effect.element.makeClipping().setStyle({height: '0px'}).show(); 715 698 }, … … 721 704 effect.element.undoClipping().undoPositioned(); 722 705 effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } 723 }, arguments[1] || { })706 }, arguments[1] || { }) 724 707 ); 725 } 708 }; 726 709 727 710 Effect.SlideUp = function(element) { 728 711 element = $(element).cleanWhitespace(); 729 712 var oldInnerBottom = element.down().getStyle('bottom'); 713 var elementDimensions = element.getDimensions(); 730 714 return new Effect.Scale(element, window.opera ? 0 : 1, 731 715 Object.extend({ scaleContent: false, … … 733 717 scaleMode: 'box', 734 718 scaleFrom: 100, 719 scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, 735 720 restoreAfterFinish: true, 736 beforeStartInternal: function(effect) {721 afterSetup: function(effect) { 737 722 effect.element.makePositioned(); 738 723 effect.element.down().makePositioned(); 739 if (window.opera) effect.element.setStyle({top: ''});724 if (window.opera) effect.element.setStyle({top: ''}); 740 725 effect.element.makeClipping().show(); 741 726 }, … … 745 730 }, 746 731 afterFinishInternal: function(effect) { 747 effect.element.hide().undoClipping().undoPositioned() .setStyle({bottom: oldInnerBottom});748 effect.element.down().undoPositioned() ;749 } 750 }, arguments[1] || { })732 effect.element.hide().undoClipping().undoPositioned(); 733 effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); 734 } 735 }, arguments[1] || { }) 751 736 ); 752 } 737 }; 753 738 754 739 // Bug in opera makes the TD containing this element expand for a instance after finish … … 763 748 } 764 749 }); 765 } 750 }; 766 751 767 752 Effect.Grow = function(element) { … … 772 757 scaleTransition: Effect.Transitions.sinoidal, 773 758 opacityTransition: Effect.Transitions.full 774 }, arguments[1] || { });759 }, arguments[1] || { }); 775 760 var oldStyle = { 776 761 top: element.style.top, … … 837 822 } 838 823 }); 839 } 824 }; 840 825 841 826 Effect.Shrink = function(element) { … … 846 831 scaleTransition: Effect.Transitions.sinoidal, 847 832 opacityTransition: Effect.Transitions.none 848 }, arguments[1] || { });833 }, arguments[1] || { }); 849 834 var oldStyle = { 850 835 top: element.style.top, … … 891 876 }, options) 892 877 ); 893 } 878 }; 894 879 895 880 Effect.Pulsate = function(element) { 896 881 element = $(element); 897 var options = arguments[1] || { };882 var options = arguments[1] || { }; 898 883 var oldOpacity = element.getInlineOpacity(); 899 884 var transition = options.transition || Effect.Transitions.sinoidal; … … 904 889 afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } 905 890 }, options), {transition: reverser})); 906 } 891 }; 907 892 908 893 Effect.Fold = function(element) { … … 924 909 effect.element.hide().undoClipping().setStyle(oldStyle); 925 910 } }); 926 }}, arguments[1] || {})); 927 }; 928 929 Effect.Morph = Class.create(); 930 Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), { 911 }}, arguments[1] || { })); 912 }; 913 914 Effect.Morph = Class.create(Effect.Base, { 931 915 initialize: function(element) { 932 916 this.element = $(element); 933 if (!this.element) throw(Effect._elementDoesNotExistError);917 if (!this.element) throw(Effect._elementDoesNotExistError); 934 918 var options = Object.extend({ 935 style: {} 936 }, arguments[1] || {}); 937 if (typeof options.style == 'string') { 938 if(options.style.indexOf(':') == -1) { 939 var cssText = '', selector = '.' + options.style; 940 $A(document.styleSheets).reverse().each(function(styleSheet) { 941 if (styleSheet.cssRules) cssRules = styleSheet.cssRules; 942 else if (styleSheet.rules) cssRules = styleSheet.rules; 943 $A(cssRules).reverse().each(function(rule) { 944 if (selector == rule.selectorText) { 945 cssText = rule.style.cssText; 946 throw $break; 947 } 948 }); 949 if (cssText) throw $break; 919 style: { } 920 }, arguments[1] || { }); 921 922 if (!Object.isString(options.style)) this.style = $H(options.style); 923 else { 924 if (options.style.include(':')) 925 this.style = options.style.parseStyle(); 926 else { 927 this.element.addClassName(options.style); 928 this.style = $H(this.element.getStyles()); 929 this.element.removeClassName(options.style); 930 var css = this.element.getStyles(); 931 this.style = this.style.reject(function(style) { 932 return style.value == css[style.key]; 950 933 }); 951 this.style = cssText.parseStyle(); 952 options.afterFinishInternal = function(effect){ 934 options.afterFinishInternal = function(effect) { 953 935 effect.element.addClassName(effect.options.style); 954 936 effect.transforms.each(function(transform) { 955 if(transform.style != 'opacity') 956 effect.element.style[transform.style.camelize()] = ''; 937 effect.element.style[transform.style] = ''; 957 938 }); 958 939 } 959 } else this.style = options.style.parseStyle();960 } else this.style = $H(options.style)940 } 941 } 961 942 this.start(options); 962 943 }, 944 963 945 setup: function(){ 964 946 function parseColor(color){ 965 if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';947 if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; 966 948 color = color.parseColor(); 967 949 return $R(0,2).map(function(i){ … … 970 952 } 971 953 this.transforms = this.style.map(function(pair){ 972 var property = pair[0] .underscore().dasherize(), value = pair[1], unit = null;973 974 if (value.parseColor('#zzzzzz') != '#zzzzzz') {954 var property = pair[0], value = pair[1], unit = null; 955 956 if (value.parseColor('#zzzzzz') != '#zzzzzz') { 975 957 value = value.parseColor(); 976 958 unit = 'color'; 977 } else if (property == 'opacity') {959 } else if (property == 'opacity') { 978 960 value = parseFloat(value); 979 if (/MSIE/.test(navigator.userAgent) && !window.opera&& (!this.element.currentStyle.hasLayout))961 if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) 980 962 this.element.setStyle({zoom: 1}); 981 } else if(Element.CSS_LENGTH.test(value)) 982 var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/), 983 value = parseFloat(components[1]), unit = (components.length == 3) ? components[2] : null; 963 } else if (Element.CSS_LENGTH.test(value)) { 964 var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); 965 value = parseFloat(components[1]); 966 unit = (components.length == 3) ? components[2] : null; 967 } 984 968 985 969 var originalValue = this.element.getStyle(property); 986 return $H({987 style: property ,970 return { 971 style: property.camelize(), 988 972 originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), 989 973 targetValue: unit=='color' ? parseColor(value) : value, 990 974 unit: unit 991 } );975 }; 992 976 }.bind(this)).reject(function(transform){ 993 977 return ( … … 1001 985 }, 1002 986 update: function(position) { 1003 var style = $H(), value = null; 1004 this.transforms.each(function(transform){ 1005 value = transform.unit=='color' ? 1006 $R(0,2).inject('#',function(m,v,i){ 1007 return m+(Math.round(transform.originalValue[i]+ 1008 (transform.targetValue[i] - transform.originalValue[i])*position)).toColorPart() }) : 1009 transform.originalValue + Math.round( 1010 ((transform.targetValue - transform.originalValue) * position) * 1000)/1000 + transform.unit; 1011 style[transform.style] = value; 1012 }); 1013 this.element.setStyle(style); 987 var style = { }, transform, i = this.transforms.length; 988 while(i--) 989 style[(transform = this.transforms[i]).style] = 990 transform.unit=='color' ? '#'+ 991 (Math.round(transform.originalValue[0]+ 992 (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + 993 (Math.round(transform.originalValue[1]+ 994 (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + 995 (Math.round(transform.originalValue[2]+ 996 (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : 997 (transform.originalValue + 998 (transform.targetValue - transform.originalValue) * position).toFixed(3) + 999 (transform.unit === null ? '' : transform.unit); 1000 this.element.setStyle(style, true); 1014 1001 } 1015 1002 }); 1016 1003 1017 Effect.Transform = Class.create(); 1018 Object.extend(Effect.Transform.prototype, { 1004 Effect.Transform = Class.create({ 1019 1005 initialize: function(tracks){ 1020 1006 this.tracks = []; 1021 this.options = arguments[1] || { };1007 this.options = arguments[1] || { }; 1022 1008 this.addTracks(tracks); 1023 1009 }, 1024 1010 addTracks: function(tracks){ 1025 1011 tracks.each(function(track){ 1026 var data = $H(track).values().first(); 1012 track = $H(track); 1013 var data = track.values().first(); 1027 1014 this.tracks.push($H({ 1028 ids: $H(track).keys().first(),1015 ids: track.keys().first(), 1029 1016 effect: Effect.Morph, 1030 1017 options: { style: data } … … 1036 1023 return new Effect.Parallel( 1037 1024 this.tracks.map(function(track){ 1038 var elements = [$(track.ids) || $$(track.ids)].flatten(); 1039 return elements.map(function(e){ return new track.effect(e, Object.extend({ sync:true }, track.options)) }); 1025 var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); 1026 var elements = [$(ids) || $$(ids)].flatten(); 1027 return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) }); 1040 1028 }).flatten(), 1041 1029 this.options … … 1057 1045 Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; 1058 1046 1047 String.__parseStyleElement = document.createElement('div'); 1059 1048 String.prototype.parseStyle = function(){ 1060 var element = Element.extend(document.createElement('div')); 1061 element.innerHTML = '<div style="' + this + '"></div>'; 1062 var style = element.down().style, styleRules = $H(); 1049 var style, styleRules = $H(); 1050 if (Prototype.Browser.WebKit) 1051 style = new Element('div',{style:this}).style; 1052 else { 1053 String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>'; 1054 style = String.__parseStyleElement.childNodes[0].style; 1055 } 1063 1056 1064 1057 Element.CSS_PROPERTIES.each(function(property){ 1065 if (style[property]) styleRules[property] = style[property];1058 if (style[property]) styleRules.set(property, style[property]); 1066 1059 }); 1067 if(/MSIE/.test(navigator.userAgent) && !window.opera && this.indexOf('opacity') > -1) { 1068 styleRules.opacity = this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]; 1069 } 1060 1061 if (Prototype.Browser.IE && this.include('opacity')) 1062 styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); 1063 1070 1064 return styleRules; 1071 1065 }; 1072 1066 1073 Element.morph = function(element, style) { 1074 new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || {})); 1075 return element; 1076 }; 1077 1078 ['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom', 1079 'collectTextNodes','collectTextNodesIgnoreClass','morph'].each( 1080 function(f) { Element.Methods[f] = Element[f]; } 1067 if (document.defaultView && document.defaultView.getComputedStyle) { 1068 Element.getStyles = function(element) { 1069 var css = document.defaultView.getComputedStyle($(element), null); 1070 return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { 1071 styles[property] = css[property]; 1072 return styles; 1073 }); 1074 }; 1075 } else { 1076 Element.getStyles = function(element) { 1077 element = $(element); 1078 var css = element.currentStyle, styles; 1079 styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) { 1080 results[property] = css[property]; 1081 return results; 1082 }); 1083 if (!styles.opacity) styles.opacity = element.getOpacity(); 1084 return styles; 1085 }; 1086 }; 1087 1088 Effect.Methods = { 1089 morph: function(element, style) { 1090 element = $(element); 1091 new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); 1092 return element; 1093 }, 1094 visualEffect: function(element, effect, options) { 1095 element = $(element) 1096 var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); 1097 new Effect[klass](element, options); 1098 return element; 1099 }, 1100 highlight: function(element, options) { 1101 element = $(element); 1102 new Effect.Highlight(element, options); 1103 return element; 1104 } 1105 }; 1106 1107 $w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ 1108 'pulsate shake puff squish switchOff dropOut').each( 1109 function(effect) { 1110 Effect.Methods[effect] = function(element, options){ 1111 element = $(element); 1112 Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); 1113 return element; 1114 } 1115 } 1081 1116 ); 1082 1117 1083 Element.Methods.visualEffect = function(element, effect, options) { 1084 s = effect.gsub(/_/, '-').camelize(); 1085 effect_class = s.charAt(0).toUpperCase() + s.substring(1); 1086 new Effect[effect_class](element, options); 1087 return $(element); 1088 }; 1089 1090 Element.addMethods(); 1118 $w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( 1119 function(f) { Effect.Methods[f] = Element[f]; } 1120 ); 1121 1122 Element.addMethods(Effect.Methods); branches/1.1/data/web/sf/prototype/js/prototype.js
r3316 r7855 1 /* Prototype JavaScript framework, version 1. 5.02 * (c) 2005-200 7Sam Stephenson1 /* Prototype JavaScript framework, version 1.6.0.2 2 * (c) 2005-2008 Sam Stephenson 3 3 * 4 4 * Prototype is freely distributable under the terms of an MIT-style license. 5 * For details, see the Prototype web site: http:// prototype.conio.net/5 * For details, see the Prototype web site: http://www.prototypejs.org/ 6 6 * 7 /*--------------------------------------------------------------------------*/7 *--------------------------------------------------------------------------*/ 8 8 9 9 var Prototype = { 10 Version: '1.5.0', 10 Version: '1.6.0.2', 11 12 Browser: { 13 IE: !!(window.attachEvent && !window.opera), 14 Opera: !!window.opera, 15 WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, 16 Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1, 17 MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) 18 }, 19 11 20 BrowserFeatures: { 12 XPath: !!document.evaluate 13 }, 14 15 ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', 16 emptyFunction: function() {}, 21 XPath: !!document.evaluate, 22 ElementExtensions: !!window.HTMLElement, 23 SpecificElementExtensions: 24 document.createElement('div').__proto__ && 25 document.createElement('div').__proto__ !== 26 document.createElement('form').__proto__ 27 }, 28 29 ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>', 30 JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, 31 32 emptyFunction: function() { }, 17 33 K: function(x) { return x } 18 } 19 34 }; 35 36 if (Prototype.Browser.MobileSafari) 37 Prototype.BrowserFeatures.SpecificElementExtensions = false; 38 39 40 /* Based on Alex Arnell's inheritance implementation. */ 20 41 var Class = { 21 42 create: function() { 22 return function() { 43 var parent = null, properties = $A(arguments); 44 if (Object.isFunction(properties[0])) 45 parent = properties.shift(); 46 47 function klass() { 23 48 this.initialize.apply(this, arguments); 24 49 } 25 } 26 } 27 28 var Abstract = new Object(); 50 51 Object.extend(klass, Class.Methods); 52 klass.superclass = parent; 53 klass.subclasses = []; 54 55 if (parent) { 56 var subclass = function() { }; 57 subclass.prototype = parent.prototype; 58 klass.prototype = new subclass; 59 parent.subclasses.push(klass); 60 } 61 62 for (var i = 0; i < properties.length; i++) 63 klass.addMethods(properties[i]); 64 65 if (!klass.prototype.initialize) 66 klass.prototype.initialize = Prototype.emptyFunction; 67 68 klass.prototype.constructor = klass; 69 70 return klass; 71 } 72 }; 73 74 Class.Methods = { 75 addMethods: function(source) { 76 var ancestor = this.superclass && this.superclass.prototype; 77 var properties = Object.keys(source); 78 79 if (!Object.keys({ toString: true }).length) 80 properties.push("toString", "valueOf"); 81 82 for (var i = 0, length = properties.length; i < length; i++) { 83 var property = properties[i], value = source[property]; 84 if (ancestor && Object.isFunction(value) && 85 value.argumentNames().first() == "$super") { 86 var method = value, value = Object.extend((function(m) { 87 return function() { return ancestor[m].apply(this, arguments) }; 88 })(property).wrap(method), { 89 valueOf: function() { return method }, 90 toString: function() { return method.toString() } 91 }); 92 } 93 this.prototype[property] = value; 94 } 95 96 return this; 97 } 98 }; 99 100 var Abstract = { }; 29 101 30 102 Object.extend = function(destination, source) { 31 for (var property in source) {103 for (var property in source) 32 104 destination[property] = source[property]; 33 }34 105 return destination; 35 } 106 }; 36 107 37 108 Object.extend(Object, { 38 109 inspect: function(object) { 39 110 try { 40 if ( object === undefined) return 'undefined';111 if (Object.isUndefined(object)) return 'undefined'; 41 112 if (object === null) return 'null'; 42 return object.inspect ? object.inspect() : object.toString();113 return object.inspect ? object.inspect() : String(object); 43 114 } catch (e) { 44 115 if (e instanceof RangeError) return '...'; 45 116 throw e; 46 117 } 118 }, 119 120 toJSON: function(object) { 121 var type = typeof object; 122 switch (type) { 123 case 'undefined': 124 case 'function': 125 case 'unknown': return; 126 case 'boolean': return object.toString(); 127 } 128 129 if (object === null) return 'null'; 130 if (object.toJSON) return object.toJSON(); 131 if (Object.isElement(object)) return; 132 133 var results = []; 134 for (var property in object) { 135 var value = Object.toJSON(object[property]); 136 if (!Object.isUndefined(value)) 137 results.push(property.toJSON() + ': ' + value); 138 } 139 140 return '{' + results.join(', ') + '}'; 141 }, 142 143 toQueryString: function(object) { 144 return $H(object).toQueryString(); 145 }, 146 147 toHTML: function(object) { 148 return object && object.toHTML ? object.toHTML() : String.interpret(object); 47 149 }, 48 150 … … 62 164 63 165 clone: function(object) { 64 return Object.extend({}, object); 166 return Object.extend({ }, object); 167 }, 168 169 isElement: function(object) { 170 return object && object.nodeType == 1; 171 }, 172 173 isArray: function(object) { 174 return object != null && typeof object == "object" && 175 'splice' in object && 'join' in object; 176 }, 177 178 isHash: function(object) { 179 return object instanceof Hash; 180 }, 181 182 isFunction: function(object) { 183 return typeof object == "function"; 184 }, 185 186 isString: function(object) { 187 return typeof object == "string"; 188 }, 189 190 isNumber: function(object) { 191 return typeof object == "number"; 192 }, 193 194 isUndefined: function(object) { 195 return typeof object == "undefined"; 65 196 } 66 197 }); 67 198 68 Function.prototype.bind = function() { 69 var __method = this, args = $A(arguments), object = args.shift(); 70 return function() { 71 return __method.apply(object, args.concat($A(arguments))); 72 } 73 } 74 75 Function.prototype.bindAsEventListener = function(object) { 76 var __method = this, args = $A(arguments), object = args.shift(); 77 return function(event) { 78 return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments))); 79 } 80 } 81 82 Object.extend(Number.prototype, { 83 toColorPart: function() { 84 var digits = this.toString(16); 85 if (this < 16) return '0' + digits; 86 return digits; 87 }, 88 89 succ: function() { 90 return this + 1; 91 }, 92 93 times: function(iterator) { 94 $R(0, this, true).each(iterator); 95 return this; 199 Object.extend(Function.prototype, { 200 argumentNames: function() { 201 var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip"); 202 return names.length == 1 && !names[0] ? [] : names; 203 }, 204 205 bind: function() { 206 if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; 207 var __method = this, args = $A(arguments), object = args.shift(); 208 return function() { 209 return __method.apply(object, args.concat($A(arguments))); 210 } 211 }, 212 213 bindAsEventListener: function() { 214 var __method = this, args = $A(arguments), object = args.shift(); 215 return function(event) { 216 return __method.apply(object, [event || window.event].concat(args)); 217 } 218 }, 219 220 curry: function() { 221 if (!arguments.length) return this; 222 var __method = this, args = $A(arguments); 223 return function() { 224 return __method.apply(this, args.concat($A(arguments))); 225 } 226 }, 227 228 delay: function() { 229 var __method = this, args = $A(arguments), timeout = args.shift() * 1000; 230 return window.setTimeout(function() { 231 return __method.apply(__method, args); 232 }, timeout); 233 }, 234 235 wrap: function(wrapper) { 236 var __method = this; 237 return function() { 238 return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); 239 } 240 }, 241 242 methodize: function() { 243 if (this._methodized) return this._methodized; 244 var __method = this; 245 return this._methodized = function() { 246 return __method.apply(null, [this].concat($A(arguments))); 247 }; 96 248 } 97 249 }); 250 251 Function.prototype.defer = Function.prototype.delay.curry(0.01); 252 253 Date.prototype.toJSON = function() { 254 return '"' + this.getUTCFullYear() + '-' + 255 (this.getUTCMonth() + 1).toPaddedString(2) + '-' + 256 this.getUTCDate().toPaddedString(2) + 'T' + 257 this.getUTCHours().toPaddedString(2) + ':' + 258 this.getUTCMinutes().toPaddedString(2) + ':' + 259 this.getUTCSeconds().toPaddedString(2) + 'Z"'; 260 }; 98 261 99 262 var Try = { … … 106 269 returnValue = lambda(); 107 270 break; 108 } catch (e) { }271 } catch (e) { } 109 272 } 110 273 111 274 return returnValue; 112 275 } 113 } 276 }; 277 278 RegExp.prototype.match = RegExp.prototype.test; 279 280 RegExp.escape = function(str) { 281 return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); 282 }; 114 283 115 284 /*--------------------------------------------------------------------------*/ 116 285 117 var PeriodicalExecuter = Class.create(); 118 PeriodicalExecuter.prototype = { 286 var PeriodicalExecuter = Class.create({ 119 287 initialize: function(callback, frequency) { 120 288 this.callback = callback; … … 129 297 }, 130 298 299 execute: function() { 300 this.callback(this); 301 }, 302 131 303 stop: function() { 132 304 if (!this.timer) return; … … 139 311 try { 140 312 this.currentlyExecuting = true; 141 this. callback(this);313 this.execute(); 142 314 } finally { 143 315 this.currentlyExecuting = false; … … 145 317 } 146 318 } 147 } 148 String.interpret = function(value){ 149 return value == null ? '' : String(value); 150 } 319 }); 320 Object.extend(String, { 321 interpret: function(value) { 322 return value == null ? '' : String(value); 323 }, 324 specialChar: { 325 '\b': '\\b', 326 '\t': '\\t', 327 '\n': '\\n', 328 '\f': '\\f', 329 '\r': '\\r', 330 '\\': '\\\\' 331 } 332 }); 151 333 152 334 Object.extend(String.prototype, { … … 169 351 sub: function(pattern, replacement, count) { 170 352 replacement = this.gsub.prepareReplacement(replacement); 171 count = count === undefined? 1 : count;353 count = Object.isUndefined(count) ? 1 : count; 172 354 173 355 return this.gsub(pattern, function(match) { … … 179 361 scan: function(pattern, iterator) { 180 362 this.gsub(pattern, iterator); 181 return this;363 return String(this); 182 364 }, 183 365 184 366 truncate: function(length, truncation) { 185 367 length = length || 30; 186 truncation = truncation === undefined? '...' : truncation;368 truncation = Object.isUndefined(truncation) ? '...' : truncation; 187 369 return this.length > length ? 188 this.slice(0, length - truncation.length) + truncation : this;370 this.slice(0, length - truncation.length) + truncation : String(this); 189 371 }, 190 372 … … 214 396 215 397 escapeHTML: function() { 216 var div = document.createElement('div'); 217 var text = document.createTextNode(this); 218 div.appendChild(text); 219 return div.innerHTML; 398 var self = arguments.callee; 399 self.text.data = this; 400 return self.div.innerHTML; 220 401 }, 221 402 222 403 unescapeHTML: function() { 223 var div = document.createElement('div');404 var div = new Element('div'); 224 405 div.innerHTML = this.stripTags(); 225 406 return div.childNodes[0] ? (div.childNodes.length > 1 ? 226 $A(div.childNodes).inject('', function(memo,node){ return memo+node.nodeValue }) :407 $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : 227 408 div.childNodes[0].nodeValue) : ''; 228 409 }, … … 230 411 toQueryParams: function(separator) { 231 412 var match = this.strip().match(/([^?#]*)(#.*)?$/); 232 if (!match) return { };233 234 return match[1].split(separator || '&').inject({ }, function(hash, pair) {413 if (!match) return { }; 414 415 return match[1].split(separator || '&').inject({ }, function(hash, pair) { 235 416 if ((pair = pair.split('='))[0]) { 236 var name = decodeURIComponent(pair[0]);237 var value = pair [1] ? decodeURIComponent(pair[1]) : undefined;238 239 if (hash[name] !== undefined) { 240 if (hash[name].constructor != Array)241 hash[name] = [hash[name]];242 if (value) hash[name].push(value);417 var key = decodeURIComponent(pair.shift()); 418 var value = pair.length > 1 ? pair.join('=') : pair[0]; 419 if (value != undefined) value = decodeURIComponent(value); 420 421 if (key in hash) { 422 if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; 423 hash[key].push(value); 243 424 } 244 else hash[ name] = value;425 else hash[key] = value; 245 426 } 246 427 return hash; … … 257 438 }, 258 439 440 times: function(count) { 441 return count < 1 ? '' : new Array(count + 1).join(this); 442 }, 443 259 444 camelize: function() { 260 445 var parts = this.split('-'), len = parts.length; … … 271 456 }, 272 457 273 capitalize: function() {458 capitalize: function() { 274 459 return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); 275 460 }, … … 284 469 285 470 inspect: function(useDoubleQuotes) { 286 var escapedString = this.replace(/\\/g, '\\\\'); 287 if (useDoubleQuotes) 288 return '"' + escapedString.replace(/"/g, '\\"') + '"'; 289 else 290 return "'" + escapedString.replace(/'/g, '\\\'') + "'"; 471 var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { 472 var character = String.specialChar[match[0]]; 473 return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); 474 }); 475 if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; 476 return "'" + escapedString.replace(/'/g, '\\\'') + "'"; 477 }, 478 479 toJSON: function() { 480 return this.inspect(true); 481 }, 482 483 unfilterJSON: function(filter) { 484 return this.sub(filter || Prototype.JSONFilter, '#{1}'); 485 }, 486 487 isJSON: function() { 488 var str = this; 489 if (str.blank()) return false; 490 str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); 491 return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); 492 }, 493 494 evalJSON: function(sanitize) { 495 var json = this.unfilterJSON(); 496 try { 497 if (!sanitize || json.isJSON()) return eval('(' + json + ')'); 498 } catch (e) { } 499 throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); 500 }, 501 502 include: function(pattern) { 503 return this.indexOf(pattern) > -1; 504 }, 505 506 startsWith: function(pattern) { 507 return this.indexOf(pattern) === 0; 508 }, 509 510 endsWith: function(pattern) { 511 var d = this.length - pattern.length; 512 return d >= 0 && this.lastIndexOf(pattern) === d; 513 }, 514 515 empty: function() { 516 return this == ''; 517 }, 518 519 blank: function() { 520 return /^\s*$/.test(this); 521 }, 522 523 interpolate: function(object, pattern) { 524 return new Template(this, pattern).evaluate(object); 291 525 } 292 526 }); 293 527 528 if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { 529 escapeHTML: function() { 530 return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); 531 }, 532 unescapeHTML: function() { 533 return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); 534 } 535 }); 536 294 537 String.prototype.gsub.prepareReplacement = function(replacement) { 295 if ( typeof replacement == 'function') return replacement;538 if (Object.isFunction(replacement)) return replacement; 296 539 var template = new Template(replacement); 297 540 return function(match) { return template.evaluate(match) }; 298 } 541 }; 299 542 300 543 String.prototype.parseQuery = String.prototype.toQueryParams; 301 544 302 var Template = Class.create(); 303 Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; 304 Template.prototype = { 545 Object.extend(String.prototype.escapeHTML, { 546 div: document.createElement('div'), 547 text: document.createTextNode('') 548 }); 549 550 with (String.prototype.escapeHTML) div.appendChild(text); 551 552 var Template = Class.create({ 305 553 initialize: function(template, pattern) { 306 554 this.template = template.toString(); 307 this.pattern = pattern || Template.Pattern;555 this.pattern = pattern || Template.Pattern; 308 556 }, 309 557 310 558 evaluate: function(object) { 559 if (Object.isFunction(object.toTemplateReplacements)) 560 object = object.toTemplateReplacements(); 561 311 562 return this.template.gsub(this.pattern, function(match) { 312 var before = match[1]; 563 if (object == null) return ''; 564 565 var before = match[1] || ''; 313 566 if (before == '\\') return match[2]; 314 return before + String.interpret(object[match[3]]); 567 568 var ctx = object, expr = match[3]; 569 var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; 570 match = pattern.exec(expr); 571 if (match == null) return before; 572 573 while (match != null) { 574 var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; 575 ctx = ctx[comp]; 576 if (null == ctx || '' == match[3]) break; 577 expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); 578 match = pattern.exec(expr); 579 } 580 581 return before + String.interpret(ctx); 315 582 }); 316 583 } 317 } 318 319 var $break = new Object(); 320 var $ continue = new Object();584 }); 585 Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; 586 587 var $break = { }; 321 588 322 589 var Enumerable = { 323 each: function(iterator ) {590 each: function(iterator, context) { 324 591 var index = 0; 592 iterator = iterator.bind(context); 325 593 try { 326 594 this._each(function(value) { 327 try { 328 iterator(value, index++); 329 } catch (e) { 330 if (e != $continue) throw e; 331 } 595 iterator(value, index++); 332 596 }); 333 597 } catch (e) { … … 337 601 }, 338 602 339 eachSlice: function(number, iterator) { 603 eachSlice: function(number, iterator, context) { 604 iterator = iterator ? iterator.bind(context) : Prototype.K; 340 605 var index = -number, slices = [], array = this.toArray(); 341 606 while ((index += number) < array.length) 342 607 slices.push(array.slice(index, index+number)); 343 return slices.map(iterator); 344 }, 345 346 all: function(iterator) { 608 return slices.collect(iterator, context); 609 }, 610 611 all: function(iterator, context) { 612 iterator = iterator ? iterator.bind(context) : Prototype.K; 347 613 var result = true; 348 614 this.each(function(value, index) { 349 result = result && !! (iterator || Prototype.K)(value, index);615 result = result && !!iterator(value, index); 350 616 if (!result) throw $break; 351 617 }); … … 353 619 }, 354 620 355 any: function(iterator) { 621 any: function(iterator, context) { 622 iterator = iterator ? iterator.bind(context) : Prototype.K; 356 623 var result = false; 357 624 this.each(function(value, index) { 358 if (result = !! (iterator || Prototype.K)(value, index))625 if (result = !!iterator(value, index)) 359 626 throw $break; 360 627 }); … … 362 629 }, 363 630 364 collect: function(iterator) { 631 collect: function(iterator, context) { 632 iterator = iterator ? iterator.bind(context) : Prototype.K; 365 633 var results = []; 366 634 this.each(function(value, index) { 367 results.push( (iterator || Prototype.K)(value, index));635 results.push(iterator(value, index)); 368 636 }); 369 637 return results; 370 638 }, 371 639 372 detect: function(iterator) { 640 detect: function(iterator, context) { 641 iterator = iterator.bind(context); 373 642 var result; 374 643 this.each(function(value, index) { … … 381 650 }, 382 651 383 findAll: function(iterator) { 652 findAll: function(iterator, context) { 653 iterator = iterator.bind(context); 384 654 var results = []; 385 655 this.each(function(value, index) { … … 390 660 }, 391 661 392 grep: function(pattern, iterator) { 662 grep: function(filter, iterator, context) { 663 iterator = iterator ? iterator.bind(context) : Prototype.K; 393 664 var results = []; 665 666 if (Object.isString(filter)) 667 filter = new RegExp(filter); 668 394 669 this.each(function(value, index) { 395 var stringValue = value.toString(); 396 if (stringValue.match(pattern)) 397 results.push((iterator || Prototype.K)(value, index)); 398 }) 670 if (filter.match(value)) 671 results.push(iterator(value, index)); 672 }); 399 673 return results; 400 674 }, 401 675 402 676 include: function(object) { 677 if (Object.isFunction(this.indexOf)) 678 if (this.indexOf(object) != -1) return true; 679 403 680 var found = false; 404 681 this.each(function(value) { … … 412 689 413 690 inGroupsOf: function(number, fillWith) { 414 fillWith = fillWith === undefined? null : fillWith;691 fillWith = Object.isUndefined(fillWith) ? null : fillWith; 415 692 return this.eachSlice(number, function(slice) { 416 693 while(slice.length < number) slice.push(fillWith); … … 419 696 }, 420 697 421 inject: function(memo, iterator) { 698 inject: function(memo, iterator, context) { 699 iterator = iterator.bind(context); 422 700 this.each(function(value, index) { 423 701 memo = iterator(memo, value, index); … … 433 711 }, 434 712 435 max: function(iterator) { 713 max: function(iterator, context) { 714 iterator = iterator ? iterator.bind(context) : Prototype.K; 436 715 var result; 437 716 this.each(function(value, index) { 438 value = (iterator || Prototype.K)(value, index);439 if (result == undefined|| value >= result)717 value = iterator(value, index); 718 if (result == null || value >= result) 440 719 result = value; 441 720 }); … … 443 722 }, 444 723 445 min: function(iterator) { 724 min: function(iterator, context) { 725 iterator = iterator ? iterator.bind(context) : Prototype.K; 446 726 var result; 447 727 this.each(function(value, index) { 448 value = (iterator || Prototype.K)(value, index);449 if (result == undefined|| value < result)728 value = iterator(value, index); 729 if (result == null || value < result) 450 730 result = value; 451 731 }); … … 453 733 }, 454 734 455 partition: function(iterator) { 735 partition: function(iterator, context) { 736 iterator = iterator ? iterator.bind(context) : Prototype.K; 456 737 var trues = [], falses = []; 457 738 this.each(function(value, index) { 458 ( (iterator || Prototype.K)(value, index) ?739 (iterator(value, index) ? 459 740 trues : falses).push(value); 460 741 }); … … 464 745 pluck: function(property) { 465 746 var results = []; 466 this.each(function(value , index) {747 this.each(function(value) { 467 748 results.push(value[property]); 468 749 }); … … 470 751 }, 471 752 472 reject: function(iterator) { 753 reject: function(iterator, context) { 754 iterator = iterator.bind(context); 473 755 var results = []; 474 756 this.each(function(value, index) { … … 479 761 }, 480 762 481 sortBy: function(iterator) { 763 sortBy: function(iterator, context) { 764 iterator = iterator.bind(context); 482 765 return this.map(function(value, index) { 483 766 return {value: value, criteria: iterator(value, index)}; … … 494 777 zip: function() { 495 778 var iterator = Prototype.K, args = $A(arguments); 496 if ( typeof args.last() == 'function')779 if (Object.isFunction(args.last())) 497 780 iterator = args.pop(); 498 781 … … 510 793 return '#<Enumerable:' + this.toArray().inspect() + '>'; 511 794 } 512 } 795 }; 513 796 514 797 Object.extend(Enumerable, { … … 516 799 find: Enumerable.detect, 517 800 select: Enumerable.findAll, 801 filter: Enumerable.findAll, 518 802 member: Enumerable.include, 519 entries: Enumerable.toArray 803 entries: Enumerable.toArray, 804 every: Enumerable.all, 805 some: Enumerable.any 520 806 }); 521 var $A = Array.from = function(iterable) {807 function $A(iterable) { 522 808 if (!iterable) return []; 523 if (iterable.toArray) { 524 return iterable.toArray(); 525 } else { 526 var results = []; 527 for (var i = 0, length = iterable.length; i < length; i++) 528 results.push(iterable[i]); 809 if (iterable.toArray) return iterable.toArray(); 810 var length = iterable.length || 0, results = new Array(length); 811 while (length--) results[length] = iterable[length]; 812 return results; 813 } 814 815 if (Prototype.Browser.WebKit) { 816 $A = function(iterable) { 817 if (!iterable) return []; 818 if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') && 819 iterable.toArray) return iterable.toArray(); 820 var length = iterable.length || 0, results = new Array(length); 821 while (length--) results[length] = iterable[length]; 529 822 return results; 530 } 823 }; 531 824 } 532 825 826 Array.from = $A; 827 533 828 Object.extend(Array.prototype, Enumerable); 534 829 535 if (!Array.prototype._reverse) 536 Array.prototype._reverse = Array.prototype.reverse; 830 if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; 537 831 538 832 Object.extend(Array.prototype, { … … 563 857 flatten: function() { 564 858 return this.inject([], function(array, value) { 565 return array.concat( value && value.constructor == Array?859 return array.concat(Object.isArray(value) ? 566 860 value.flatten() : [value]); 567 861 }); … … 575 869 }, 576 870 577 indexOf: function(object) {578 for (var i = 0, length = this.length; i < length; i++)579 if (this[i] == object) return i;580 return -1;581 },582 583 871 reverse: function(inline) { 584 872 return (inline !== false ? this : this.toArray())._reverse(); … … 589 877 }, 590 878 591 uniq: function() { 592 return this.inject([], function(array, value) { 593 return array.include(value) ? array : array.concat([value]); 879 uniq: function(sorted) { 880 return this.inject([], function(array, value, index) { 881 if (0 == index || (sorted ? array.last() != value : !array.include(value))) 882 array.push(value); 883 return array; 884 }); 885 }, 886 887 intersect: function(array) { 888 return this.uniq().findAll(function(item) { 889 return array.detect(function(value) { return item === value }); 594 890 }); 595 891 }, … … 605 901 inspect: function() { 606 902 return '[' + this.map(Object.inspect).join(', ') + ']'; 903 }, 904 905 toJSON: function() { 906 var results = []; 907 this.each(function(object) { 908 var value = Object.toJSON(object); 909 if (!Object.isUndefined(value)) results.push(value); 910 }); 911 return '[' + results.join(', ') + ']'; 607 912 } 608 913 }); 609 914 915 // use native browser JS 1.6 implementation if available 916 if (Object.isFunction(Array.prototype.forEach)) 917 Array.prototype._each = Array.prototype.forEach; 918 919 if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { 920 i || (i = 0); 921 var length = this.length; 922 if (i < 0) i = length + i; 923 for (; i < length; i++) 924 if (this[i] === item) return i; 925 return -1; 926 }; 927 928 if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { 929 i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; 930 var n = this.slice(0, i).reverse().indexOf(item); 931 return (n < 0) ? n : i - n - 1; 932 }; 933 610 934 Array.prototype.toArray = Array.prototype.clone; 611 935 612 function $w(string){ 936 function $w(string) { 937 if (!Object.isString(string)) return []; 613 938 string = string.strip(); 614 939 return string ? string.split(/\s+/) : []; 615 940 } 616 941 617 if (window.opera){618 Array.prototype.concat = function() {942 if (Prototype.Browser.Opera){ 943 Array.prototype.concat = function() { 619 944 var array = []; 620 for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);621 for (var i = 0, length = arguments.length; i < length; i++) {622 if (arguments[i].constructor == Array) {623 for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)945 for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); 946 for (var i = 0, length = arguments.length; i < length; i++) { 947 if (Object.isArray(arguments[i])) { 948 for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) 624 949 array.push(arguments[i][j]); 625 950 } else { … … 628 953 } 629 954 return array; 630 } 955 }; 631 956 } 632 var Hash = function(obj) { 633 Object.extend(this, obj || {}); 634 }; 635 636 Object.extend(Hash, { 637 toQueryString: function(obj) { 638 var parts = []; 639 640 this.prototype._each.call(obj, function(pair) { 641 if (!pair.key) return; 642 643 if (pair.value && pair.value.constructor == Array) { 644 var values = pair.value.compact(); 645 if (values.length < 2) pair.value = values.reduce(); 646 else { 647 key = encodeURIComponent(pair.key); 648 values.each(function(value) { 649 value = value != undefined ? encodeURIComponent(value) : ''; 650 parts.push(key + '=' + encodeURIComponent(value)); 651 }); 652 return; 653 } 654 } 655 if (pair.value == undefined) pair[1] = ''; 656 parts.push(pair.map(encodeURIComponent).join('=')); 657 }); 658 659 return parts.join('&'); 957 Object.extend(Number.prototype, { 958 toColorPart: function() { 959 return this.toPaddedString(2, 16); 960 }, 961 962 succ: function() { 963 return this + 1; 964 }, 965 966 times: function(iterator) { 967 $R(0, this, true).each(iterator); 968 return this; 969 }, 970 971 toPaddedString: function(length, radix) { 972 var string = this.toString(radix || 10); 973 return '0'.times(length - string.length) + string; 974 }, 975 976 toJSON: function() { 977 return isFinite(this) ? this.toString() : 'null'; 660 978 } 661 979 }); 662 980 663 Object.extend(Hash.prototype, Enumerable); 664 Object.extend(Hash.prototype, { 665 _each: function(iterator) { 666 for (var key in this) { 667 var value = this[key]; 668 if (value && value == Hash.prototype[key]) continue; 669 670 var pair = [key, value]; 671 pair.key = key; 672 pair.value = value; 673 iterator(pair); 674 } 675 }, 676 677 keys: function() { 678 return this.pluck('key'); 679 }, 680 681 values: function() { 682 return this.pluck('value'); 683 }, 684 685 merge: function(hash) { 686 return $H(hash).inject(this, function(mergedHash, pair) { 687 mergedHash[pair.key] = pair.value; 688 return mergedHash; 689 }); 690 }, 691 692 remove: function() { 693 var result; 694 for(var i = 0, length = arguments.length; i < length; i++) { 695 var value = this[arguments[i]]; 696 if (value !== undefined){ 697 if (result === undefined) result = value; 698 else { 699 if (result.constructor != Array) result = [result]; 700 result.push(value) 701 } 702 } 703 delete this[arguments[i]]; 704 } 705 return result; 706 }, 707 708 toQueryString: function() { 709 return Hash.toQueryString(this); 710 }, 711 712 inspect: function() { 713 return '#<Hash:{' + this.map(function(pair) { 714 return pair.map(Object.inspect).join(': '); 715 }).join(', ') + '}>'; 716 } 981 $w('abs round ceil floor').each(function(method){ 982 Number.prototype[method] = Math[method].methodize(); 717 983 }); 718 719 984 function $H(object) { 720 if (object && object.constructor == Hash) return object;721 985 return new Hash(object); 722 986 }; 723 ObjectRange = Class.create(); 724 Object.extend(ObjectRange.prototype, Enumerable); 725 Object.extend(ObjectRange.prototype, { 987 988 var Hash = Class.create(Enumerable, (function() { 989 990 function toQueryPair(key, value) { 991 if (Object.isUndefined(value)) return key; 992 return key + '=' + encodeURIComponent(String.interpret(value)); 993 } 994 995 return { 996 initialize: function(object) { 997 this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); 998 }, 999 1000 _each: function(iterator) { 1001 for (var key in this._object) { 1002 var value = this._object[key], pair = [key, value]; 1003 pair.key = key; 1004 pair.value = value; 1005 iterator(pair); 1006 } 1007 }, 1008 1009 set: function(key, value) { 1010 return this._object[key] = value; 1011 }, 1012 1013 get: function(key) { 1014 return this._object[key]; 1015 }, 1016 1017 unset: function(key) { 1018 var value = this._object[key]; 1019 delete this._object[key]; 1020 return value; 1021 }, 1022 1023 toObject: function() { 1024 return Object.clone(this._object); 1025 }, 1026 1027 keys: function() { 1028 return this.pluck('key'); 1029 }, 1030 1031 values: function() { 1032 return this.pluck('value'); 1033 }, 1034 1035 index: function(value) { 1036 var match = this.detect(function(pair) { 1037 return pair.value === value; 1038 }); 1039 return match && match.key; 1040 }, 1041 1042 merge: function(object) { 1043 return this.clone().update(object); 1044 }, 1045 1046 update: function(object) { 1047 return new Hash(object).inject(this, function(result, pair) { 1048 result.set(pair.key, pair.value); 1049 return result; 1050 }); 1051 }, 1052 1053 toQueryString: function() { 1054 return this.map(function(pair) { 1055 var key = encodeURIComponent(pair.key), values = pair.value; 1056 1057 if (values && typeof values == 'object') { 1058 if (Object.isArray(values)) 1059 return values.map(toQueryPair.curry(key)).join('&'); 1060 } 1061 return toQueryPair(key, values); 1062 }).join('&'); 1063 }, 1064 1065 inspect: function() { 1066 return '#<Hash:{' + this.map(function(pair) { 1067 return pair.map(Object.inspect).join(': '); 1068 }).join(', ') + '}>'; 1069 }, 1070 1071 toJSON: function() { 1072 return Object.toJSON(this.toObject()); 1073 }, 1074 1075 clone: function() { 1076 return new Hash(this); 1077 } 1078 } 1079 })()); 1080 1081 Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; 1082 Hash.from = $H; 1083 var ObjectRange = Class.create(Enumerable, { 726 1084 initialize: function(start, end, exclusive) { 727 1085 this.start = start; … … 749 1107 var $R = function(start, end, exclusive) { 750 1108 return new ObjectRange(start, end, exclusive); 751 } 1109 }; 752 1110 753 1111 var Ajax = { … … 761 1119 762 1120 activeRequestCount: 0 763 } 1121 }; 764 1122 765 1123 Ajax.Responders = { … … 781 1139 dispatch: function(callback, request, transport, json) { 782 1140 this.each(function(responder) { 783 if ( typeof responder[callback] == 'function') {1141 if (Object.isFunction(responder[callback])) { 784 1142 try { 785 1143 responder[callback].apply(responder, [request, transport, json]); 786 } catch (e) { }1144 } catch (e) { } 787 1145 } 788 1146 }); … … 793 1151 794 1152 Ajax.Responders.register({ 795 onCreate: function() { 796 Ajax.activeRequestCount++; 797 }, 798 onComplete: function() { 799 Ajax.activeRequestCount--; 800 } 1153 onCreate: function() { Ajax.activeRequestCount++ }, 1154 onComplete: function() { Ajax.activeRequestCount-- } 801 1155 }); 802 1156 803 Ajax.Base = function() {}; 804 Ajax.Base.prototype = { 805 setOptions: function(options) { 1157 Ajax.Base = Class.create({ 1158 initialize: function(options) { 806 1159 this.options = { 807 1160 method: 'post', … … 809 1162 contentType: 'application/x-www-form-urlencoded', 810 1163 encoding: 'UTF-8', 811 parameters: '' 812 } 813 Object.extend(this.options, options || {}); 1164 parameters: '', 1165 evalJSON: true, 1166 evalJS: true 1167 }; 1168 Object.extend(this.options, options || { }); 814 1169 815 1170 this.options.method = this.options.method.toLowerCase(); 816 if (typeof this.options.parameters == 'string') 1171 1172 if (Object.isString(this.options.parameters)) 817 1173 this.options.parameters = this.options.parameters.toQueryParams(); 818 } 819 } 820 821 Ajax.Request = Class.create(); 822 Ajax.Request.Events = 823 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; 824 825 Ajax.Request.prototype = Object.extend(new Ajax.Base(), { 1174 else if (Object.isHash(this.options.parameters)) 1175 this.options.parameters = this.options.parameters.toObject(); 1176 } 1177 }); 1178 1179 Ajax.Request = Class.create(Ajax.Base, { 826 1180 _complete: false, 827 1181 828 initialize: function(url, options) { 1182 initialize: function($super, url, options) { 1183 $super(options); 829 1184 this.transport = Ajax.getTransport(); 830 this.setOptions(options);831 1185 this.request(url); 832 1186 }, … … 835 1189 this.url = url; 836 1190 this.method = this.options.method; 837 var params = this.options.parameters;1191 var params = Object.clone(this.options.parameters); 838 1192 839 1193 if (!['get', 'post'].include(this.method)) { … … 843 1197 } 844 1198 845 params = Hash.toQueryString(params); 846 if (params && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_=' 847 848 // when GET, append parameters to URL 849 if (this.method == 'get' && params) 850 this.url += (this.url.indexOf('?') > -1 ? '&' : '?') + params; 1199 this.parameters = params; 1200 1201 if (params = Object.toQueryString(params)) { 1202 // when GET, append parameters to URL 1203 if (this.method == 'get') 1204 this.url += (this.url.include('?') ? '&' : '?') + params; 1205 else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) 1206 params += '&_='; 1207 } 851 1208 852 1209 try { 853 Ajax.Responders.dispatch('onCreate', this, this.transport); 1210 var response = new Ajax.Response(this); 1211 if (this.options.onCreate) this.options.onCreate(response); 1212 Ajax.Responders.dispatch('onCreate', this, response); 854 1213 855 1214 this.transport.open(this.method.toUpperCase(), this.url, 856 1215 this.options.asynchronous); 857 1216 858 if (this.options.asynchronous) 859 setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); 1217 if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); 860 1218 861 1219 this.transport.onreadystatechange = this.onStateChange.bind(this); 862 1220 this.setRequestHeaders(); 863 1221 864 var body = this.method == 'post' ? (this.options.postBody || params) : null; 865 866 this.transport.send(body); 1222 this.body = this.method == 'post' ? (this.options.postBody || params) : null; 1223 this.transport.send(this.body); 867 1224 868 1225 /* Force Firefox to handle ready state 4 for synchronous requests */ … … 906 1263 var extras = this.options.requestHeaders; 907 1264 908 if ( typeof extras.push == 'function')1265 if (Object.isFunction(extras.push)) 909 1266 for (var i = 0, length = extras.length; i < length; i += 2) 910 1267 headers[extras[i]] = extras[i+1]; … … 918 1275 919 1276 success: function() { 920 return !this.transport.status 921 || (this.transport.status >= 200 && this.transport.status < 300); 1277 var status = this.getStatus(); 1278 return !status || (status >= 200 && status < 300); 1279 }, 1280 1281 getStatus: function() { 1282 try { 1283 return this.transport.status || 0; 1284 } catch (e) { return 0 } 922 1285 }, 923 1286 924 1287 respondToReadyState: function(readyState) { 925 var state = Ajax.Request.Events[readyState]; 926 var transport = this.transport, json = this.evalJSON(); 1288 var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); 927 1289 928 1290 if (state == 'Complete') { 929 1291 try { 930 1292 this._complete = true; 931 (this.options['on' + this.transport.status]1293 (this.options['on' + response.status] 932 1294 || this.options['on' + (this.success() ? 'Success' : 'Failure')] 933 || Prototype.emptyFunction)( transport, json);1295 || Prototype.emptyFunction)(response, response.headerJSON); 934 1296 } catch (e) { 935 1297 this.dispatchException(e); 936 1298 } 937 1299 938 if ((this.getHeader('Content-type') || 'text/javascript').strip(). 939 match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) 940 this.evalResponse(); 1300 var contentType = response.getHeader('Content-type'); 1301 if (this.options.evalJS == 'force' 1302 || (this.options.evalJS && this.isSameOrigin() && contentType 1303 && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) 1304 this.evalResponse(); 941 1305 } 942 1306 943 1307 try { 944 (this.options['on' + state] || Prototype.emptyFunction)( transport, json);945 Ajax.Responders.dispatch('on' + state, this, transport, json);1308 (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); 1309 Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); 946 1310 } catch (e) { 947 1311 this.dispatchException(e); … … 954 1318 }, 955 1319 1320 isSameOrigin: function() { 1321 var m = this.url.match(/^\s*https?:\/\/[^\/]*/); 1322 return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ 1323 protocol: location.protocol, 1324 domain: document.domain, 1325 port: location.port ? ':' + location.port : '' 1326 })); 1327 }, 1328 956 1329 getHeader: function(name) { 957 1330 try { 958 return this.transport.getResponseHeader(name); 959 } catch (e) { return null } 960 }, 961 962 evalJSON: function() { 963 try { 964 var json = this.getHeader('X-JSON'); 965 return json ? eval('(' + json + ')') : null; 1331 return this.transport.getResponseHeader(name) || null; 966 1332 } catch (e) { return null } 967 1333 }, … … 969 1335 evalResponse: function() { 970 1336 try { 971 return eval( this.transport.responseText);1337 return eval((this.transport.responseText || '').unfilterJSON()); 972 1338 } catch (e) { 973 1339 this.dispatchException(e); … … 981 1347 }); 982 1348 983 Ajax.Updater = Class.create(); 984 985 Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { 986 initialize: function(container, url, options) { 1349 Ajax.Request.Events = 1350 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; 1351 1352 Ajax.Response = Class.create({ 1353 initialize: function(request){ 1354 this.request = request; 1355 var transport = this.transport = request.transport, 1356 readyState = this.readyState = transport.readyState; 1357 1358 if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { 1359 this.status = this.getStatus(); 1360 this.statusText = this.getStatusText(); 1361 this.responseText = String.interpret(transport.responseText); 1362 this.headerJSON = this._getHeaderJSON(); 1363 } 1364 1365 if(readyState == 4) { 1366 var xml = transport.responseXML; 1367 this.responseXML = Object.isUndefined(xml) ? null : xml; 1368 this.responseJSON = this._getResponseJSON(); 1369 } 1370 }, 1371 1372 status: 0, 1373 statusText: '', 1374 1375 getStatus: Ajax.Request.prototype.getStatus, 1376 1377 getStatusText: function() { 1378 try { 1379 return this.transport.statusText || ''; 1380 } catch (e) { return '' } 1381 }, 1382 1383 getHeader: Ajax.Request.prototype.getHeader, 1384 1385 getAllHeaders: function() { 1386 try { 1387 return this.getAllResponseHeaders(); 1388 } catch (e) { return null } 1389 }, 1390 1391 getResponseHeader: function(name) { 1392 return this.transport.getResponseHeader(name); 1393 }, 1394 1395 getAllResponseHeaders: function() { 1396 return this.transport.getAllResponseHeaders(); 1397 }, 1398 1399 _getHeaderJSON: function() { 1400 var json = this.getHeader('X-JSON'); 1401 if (!json) return null; 1402 json = decodeURIComponent(escape(json)); 1403 try { 1404 return json.evalJSON(this.request.options.sanitizeJSON || 1405 !this.request.isSameOrigin()); 1406 } catch (e) { 1407 this.request.dispatchException(e); 1408 } 1409 }, 1410 1411 _getResponseJSON: function() { 1412 var options = this.request.options; 1413 if (!options.evalJSON || (options.evalJSON != 'force' && 1414 !(this.getHeader('Content-type') || '').include('application/json')) || 1415 this.responseText.blank()) 1416 return null; 1417 try { 1418 return this.responseText.evalJSON(options.sanitizeJSON || 1419 !this.request.isSameOrigin()); 1420 } catch (e) { 1421 this.request.dispatchException(e); 1422 } 1423 } 1424 }); 1425 1426 Ajax.Updater = Class.create(Ajax.Request, { 1427 initialize: function($super, container, url, options) { 987 1428 this.container = { 988 1429 success: (container.success || container), 989 1430 failure: (container.failure || (container.success ? null : container)) 990 } 991 992 this.transport = Ajax.getTransport(); 993 this.setOptions(options); 994 995 var onComplete = this.options.onComplete || Prototype.emptyFunction; 996 this.options.onComplete = (function(transport, param) { 997 this.updateContent(); 998 onComplete(transport, param); 1431 }; 1432 1433 options = Object.clone(options); 1434 var onComplete = options.onComplete; 1435 options.onComplete = (function(response, json) { 1436 this.updateContent(response.responseText); 1437 if (Object.isFunction(onComplete)) onComplete(response, json); 999 1438 }).bind(this); 1000 1439 1001 this.request(url);1002 }, 1003 1004 updateContent: function( ) {1005 var receiver = this.container[this.success() ? 'success' : 'failure'] ;1006 var response = this.transport.responseText;1007 1008 if (! this.options.evalScripts) response = response.stripScripts();1440 $super(url, options); 1441 }, 1442 1443 updateContent: function(responseText) { 1444 var receiver = this.container[this.success() ? 'success' : 'failure'], 1445 options = this.options; 1446 1447 if (!options.evalScripts) responseText = responseText.stripScripts(); 1009 1448 1010 1449 if (receiver = $(receiver)) { 1011 if (this.options.insertion) 1012 new this.options.insertion(receiver, response); 1013 else 1014 receiver.update(response); 1015 } 1016 1017 if (this.success()) { 1018 if (this.onComplete) 1019 setTimeout(this.onComplete.bind(this), 10); 1450 if (options.insertion) { 1451 if (Object.isString(options.insertion)) { 1452 var insertion = { }; insertion[options.insertion] = responseText; 1453 receiver.insert(insertion); 1454 } 1455 else options.insertion(receiver, responseText); 1456 } 1457 else receiver.update(responseText); 1020 1458 } 1021 1459 } 1022 1460 }); 1023 1461 1024 Ajax.PeriodicalUpdater = Class.create(); 1025 Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { 1026 initialize: function(container, url, options) { 1027 this.setOptions(options); 1462 Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { 1463 initialize: function($super, container, url, options) { 1464 $super(options); 1028 1465 this.onComplete = this.options.onComplete; 1029 1466 … … 1031 1468 this.decay = (this.options.decay || 1); 1032 1469 1033 this.updater = { };1470 this.updater = { }; 1034 1471 this.container = container; 1035 1472 this.url = url; … … 1049 1486 }, 1050 1487 1051 updateComplete: function(re quest) {1488 updateComplete: function(response) { 1052 1489 if (this.options.decay) { 1053 this.decay = (re quest.responseText == this.lastText ?1490 this.decay = (response.responseText == this.lastText ? 1054 1491 this.decay * this.options.decay : 1); 1055 1492 1056 this.lastText = request.responseText; 1057 } 1058 this.timer = setTimeout(this.onTimerEvent.bind(this), 1059 this.decay * this.frequency * 1000); 1493 this.lastText = response.responseText; 1494 } 1495 this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); 1060 1496 }, 1061 1497 … … 1070 1506 return elements; 1071 1507 } 1072 if ( typeof element == 'string')1508 if (Object.isString(element)) 1073 1509 element = document.getElementById(element); 1074 1510 return Element.extend(element); … … 1081 1517 null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); 1082 1518 for (var i = 0, length = query.snapshotLength; i < length; i++) 1083 results.push( query.snapshotItem(i));1519 results.push(Element.extend(query.snapshotItem(i))); 1084 1520 return results; 1085 1521 }; 1086 1522 } 1087 1523 1088 document.getElementsByClassName = function(className, parentElement) {1089 if (Prototype.BrowserFeatures.XPath) {1090 var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";1091 return document._getElementsByXPath(q, parentElement);1092 } else {1093 var children = ($(parentElement) || document.body).getElementsByTagName('*');1094 var elements = [], child;1095 for (var i = 0, length = children.length; i < length; i++) {1096 child = children[i];1097 if (Element.hasClassName(child, className))1098 elements.push(Element.extend(child));1099 }1100 return elements;1101 }1102 };1103 1104 1524 /*--------------------------------------------------------------------------*/ 1105 1525 1106 if (!window.Element) 1107 var Element = new Object(); 1108 1109 Element.extend = function(element) { 1110 if (!element || _nativeExtensions || element.nodeType == 3) return element; 1111 1112 if (!element._extended && element.tagName && element != window) { 1113 var methods = Object.clone(Element.Methods), cache = Element.extend.cache; 1114 1115 if (element.tagName == 'FORM') 1116 Object.extend(methods, Form.Methods); 1117 if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName)) 1118 Object.extend(methods, Form.Element.Methods); 1119 1120 Object.extend(methods, Element.Methods.Simulated); 1121 1122 for (var property in methods) { 1123 var value = methods[property]; 1124 if (typeof value == 'function' && !(property in element)) 1125 element[property] = cache.findOrStore(value); 1126 } 1127 } 1128 1129 element._extended = true; 1130 return element; 1131 }; 1132 1133 Element.extend.cache = { 1134 findOrStore: function(value) { 1135 return this[value] = this[value] || function() { 1136 return value.apply(null, [this].concat($A(arguments))); 1137 } 1138 } 1139 }; 1526 if (!window.Node) var Node = { }; 1527 1528 if (!Node.ELEMENT_NODE) { 1529 // DOM level 2 ECMAScript Language Binding 1530 Object.extend(Node, { 1531 ELEMENT_NODE: 1, 1532 ATTRIBUTE_NODE: 2, 1533 TEXT_NODE: 3, 1534 CDATA_SECTION_NODE: 4, 1535 ENTITY_REFERENCE_NODE: 5, 1536 ENTITY_NODE: 6, 1537 PROCESSING_INSTRUCTION_NODE: 7, 1538 COMMENT_NODE: 8, 1539 DOCUMENT_NODE: 9, 1540 DOCUMENT_TYPE_NODE: 10, 1541 DOCUMENT_FRAGMENT_NODE: 11, 1542 NOTATION_NODE: 12 1543 }); 1544 } 1545 1546 (function() { 1547 var element = this.Element; 1548 this.Element = function(tagName, attributes) { 1549 attributes = attributes || { }; 1550 tagName = tagName.toLowerCase(); 1551 var cache = Element.cache; 1552 if (Prototype.Browser.IE && attributes.name) { 1553 tagName = '<' + tagName + ' name="' + attributes.name + '">'; 1554 delete attributes.name; 1555 return Element.writeAttribute(document.createElement(tagName), attributes); 1556 } 1557 if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); 1558 return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); 1559 }; 1560 Object.extend(this.Element, element || { }); 1561 }).call(window); 1562 1563 Element.cache = { }; 1140 1564 1141 1565 Element.Methods = { … … 1166 1590 }, 1167 1591 1168 update: function(element, html) { 1169 html = typeof html == 'undefined' ? '' : html.toString(); 1170 $(element).innerHTML = html.stripScripts(); 1171 setTimeout(function() {html.evalScripts()}, 10); 1592 update: function(element, content) { 1593 element = $(element); 1594 if (content && content.toElement) content = content.toElement(); 1595 if (Object.isElement(content)) return element.update().insert(content); 1596 content = Object.toHTML(content); 1597 element.innerHTML = content.stripScripts(); 1598 content.evalScripts.bind(content).defer(); 1172 1599 return element; 1173 1600 }, 1174 1601 1175 replace: function(element, html) {1602 replace: function(element, content) { 1176 1603 element = $(element); 1177 html = typeof html == 'undefined' ? '' : html.toString(); 1178 if (element.outerHTML) { 1179 element.outerHTML = html.stripScripts(); 1180 } else { 1604 if (content && content.toElement) content = content.toElement(); 1605 else if (!Object.isElement(content)) { 1606 content = Object.toHTML(content); 1181 1607 var range = element.ownerDocument.createRange(); 1182 range.selectNode Contents(element);1183 element.parentNode.replaceChild(1184 range.createContextualFragment(html.stripScripts()), element);1185 } 1186 setTimeout(function() {html.evalScripts()}, 10);1608 range.selectNode(element); 1609 content.evalScripts.bind(content).defer(); 1610 content = range.createContextualFragment(content.stripScripts()); 1611 } 1612 element.parentNode.replaceChild(content, element); 1187 1613 return element; 1614 }, 1615 1616 insert: function(element, insertions) { 1617 element = $(element); 1618 1619 if (Object.isString(insertions) || Object.isNumber(insertions) || 1620 Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) 1621 insertions = {bottom:insertions}; 1622 1623 var content, insert, tagName, childNodes; 1624 1625 for (var position in insertions) { 1626 content = insertions[position]; 1627 position = position.toLowerCase(); 1628 insert = Element._insertionTranslations[position]; 1629 1630 if (content && content.toElement) content = content.toElement(); 1631 if (Object.isElement(content)) { 1632 insert(element, content); 1633 continue; 1634 } 1635 1636 content = Object.toHTML(content); 1637 1638 tagName = ((position == 'before' || position == 'after') 1639 ? element.parentNode : element).tagName.toUpperCase(); 1640 1641 childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); 1642 1643 if (position == 'top' || position == 'after') childNodes.reverse(); 1644 childNodes.each(insert.curry(element)); 1645 1646 content.evalScripts.bind(content).defer(); 1647 } 1648 1649 return element; 1650 }, 1651 1652 wrap: function(element, wrapper, attributes) { 1653 element = $(element); 1654 if (Object.isElement(wrapper)) 1655 $(wrapper).writeAttribute(attributes || { }); 1656 else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); 1657 else wrapper = new Element('div', wrapper); 1658 if (element.parentNode) 1659 element.parentNode.replaceChild(wrapper, element); 1660 wrapper.appendChild(element); 1661 return wrapper; 1188 1662 }, 1189 1663 … … 1213 1687 1214 1688 descendants: function(element) { 1215 return $A($(element).getElementsByTagName('*')); 1689 return $(element).select("*"); 1690 }, 1691 1692 firstDescendant: function(element) { 1693 element = $(element).firstChild; 1694 while (element && element.nodeType != 1) element = element.nextSibling; 1695 return $(element); 1216 1696 }, 1217 1697 … … 1237 1717 1238 1718 match: function(element, selector) { 1239 if ( typeof selector == 'string')1719 if (Object.isString(selector)) 1240 1720 selector = new Selector(selector); 1241 1721 return selector.match($(element)); … … 1243 1723 1244 1724 up: function(element, expression, index) { 1245 return Selector.findElement($(element).ancestors(), expression, index); 1725 element = $(element); 1726 if (arguments.length == 1) return $(element.parentNode); 1727 var ancestors = element.ancestors(); 1728 return Object.isNumber(expression) ? ancestors[expression] : 1729 Selector.findElement(ancestors, expression, index); 1246 1730 }, 1247 1731 1248 1732 down: function(element, expression, index) { 1249 return Selector.findElement($(element).descendants(), expression, index); 1733 element = $(element); 1734 if (arguments.length == 1) return element.firstDescendant(); 1735 return Object.isNumber(expression) ? element.descendants()[expression] : 1736 element.select(expression)[index || 0]; 1250 1737 }, 1251 1738 1252 1739 previous: function(element, expression, index) { 1253 return Selector.findElement($(element).previousSiblings(), expression, index); 1740 element = $(element); 1741 if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); 1742 var previousSiblings = element.previousSiblings(); 1743 return Object.isNumber(expression) ? previousSiblings[expression] : 1744 Selector.findElement(previousSiblings, expression, index); 1254 1745 }, 1255 1746 1256 1747 next: function(element, expression, index) { 1257 return Selector.findElement($(element).nextSiblings(), expression, index); 1258 }, 1259 1260 getElementsBySelector: function() { 1748 element = $(element); 1749 if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); 1750 var nextSiblings = element.nextSiblings(); 1751 return Object.isNumber(expression) ? nextSiblings[expression] : 1752 Selector.findElement(nextSiblings, expression, index); 1753 }, 1754 1755 select: function() { 1261 1756 var args = $A(arguments), element = $(args.shift()); 1262 1757 return Selector.findChildElements(element, args); 1263 1758 }, 1264 1759 1265 getElementsByClassName: function(element, className) { 1266 return document.getElementsByClassName(className, element); 1760 adjacent: function() { 1761 var args = $A(arguments), element = $(args.shift()); 1762 return Selector.findChildElements(element.parentNode, args).without(element); 1763 }, 1764 1765 identify: function(element) { 1766 element = $(element); 1767 var id = element.readAttribute('id'), self = arguments.callee; 1768 if (id) return id; 1769 do { id = 'anonymous_element_' + self.counter++ } while ($(id)); 1770 element.writeAttribute('id', id); 1771 return id; 1267 1772 }, 1268 1773 1269 1774 readAttribute: function(element, name) { 1270 1775 element = $(element); 1271 if ( document.all && !window.opera) {1272 var t = Element._attributeTranslations ;1776 if (Prototype.Browser.IE) { 1777 var t = Element._attributeTranslations.read; 1273 1778 if (t.values[name]) return t.values[name](element, name); 1274 if (t.names[name]) name = t.names[name]; 1275 var attribute = element.attributes[name]; 1276 if(attribute) return attribute.nodeValue; 1779 if (t.names[name]) name = t.names[name]; 1780 if (name.include(':')) { 1781 return (!element.attributes || !element.attributes[name]) ? null : 1782 element.attributes[name].value; 1783 } 1277 1784 } 1278 1785 return element.getAttribute(name); 1786 }, 1787 1788 writeAttribute: function(element, name, value) { 1789 element = $(element); 1790 var attributes = { }, t = Element._attributeTranslations.write; 1791 1792 if (typeof name == 'object') attributes = name; 1793 else attributes[name] = Obje