Modified: maven/archiva/trunk/archiva-webapp/src/main/webapp/js/scriptaculous/controls.js URL: http://svn.apache.org/viewvc/maven/archiva/trunk/archiva-webapp/src/main/webapp/js/scriptaculous/controls.js?view=diff&rev=489860&r1=489859&r2=489860 ============================================================================== --- maven/archiva/trunk/archiva-webapp/src/main/webapp/js/scriptaculous/controls.js (original) +++ maven/archiva/trunk/archiva-webapp/src/main/webapp/js/scriptaculous/controls.js Fri Dec 22 22:39:46 2006 @@ -1,3 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + // script.aculo.us controls.js v1.6.4, Wed Sep 06 11:30:58 CEST 2006 // Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) @@ -35,325 +54,372 @@ // useful when one of the tokens is \n (a newline), as it // allows smart autocompletion after linebreaks. -if(typeof Effect == 'undefined') - throw("controls.js requires including script.aculo.us' effects.js library"); +if ( typeof Effect == 'undefined' ) + throw("controls.js requires including script.aculo.us' effects.js library"); var Autocompleter = {} -Autocompleter.Base = function() {}; +Autocompleter.Base = function() +{ +}; Autocompleter.Base.prototype = { - baseInitialize: function(element, update, options) { - this.element = $(element); - this.update = $(update); - this.hasFocus = false; - this.changed = false; - this.active = false; - this.index = 0; - this.entryCount = 0; - - if(this.setOptions) - this.setOptions(options); - else - this.options = options || {}; - - this.options.paramName = this.options.paramName || this.element.name; - this.options.tokens = this.options.tokens || []; - this.options.frequency = this.options.frequency || 0.4; - this.options.minChars = this.options.minChars || 1; - this.options.onShow = this.options.onShow || - function(element, update){ - if(!update.style.position || update.style.position=='absolute') { - update.style.position = 'absolute'; - Position.clone(element, update, { - setHeight: false, - offsetTop: element.offsetHeight - }); - } - Effect.Appear(update,{duration:0.15}); - }; - this.options.onHide = this.options.onHide || - function(element, update){ new Effect.Fade(update,{duration:0.15}) }; - - if(typeof(this.options.tokens) == 'string') - this.options.tokens = new Array(this.options.tokens); - - this.observer = null; - - this.element.setAttribute('autocomplete','off'); - - Element.hide(this.update); - - Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this)); - Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this)); - }, - - show: function() { - if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); - if(!this.iefix && - (navigator.appVersion.indexOf('MSIE')>0) && - (navigator.userAgent.indexOf('Opera')<0) && - (Element.getStyle(this.update, 'position')=='absolute')) { - new Insertion.After(this.update, - '<iframe id="' + this.update.id + '_iefix" '+ - 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' + - 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>'); - this.iefix = $(this.update.id+'_iefix'); - } - if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); - }, - - fixIEOverlapping: function() { - Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); - this.iefix.style.zIndex = 1; - this.update.style.zIndex = 2; - Element.show(this.iefix); - }, - - hide: function() { - this.stopIndicator(); - if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); - if(this.iefix) Element.hide(this.iefix); - }, - - startIndicator: function() { - if(this.options.indicator) Element.show(this.options.indicator); - }, - - stopIndicator: function() { - if(this.options.indicator) Element.hide(this.options.indicator); - }, - - onKeyPress: function(event) { - if(this.active) - switch(event.keyCode) { - case Event.KEY_TAB: - case Event.KEY_RETURN: - this.selectEntry(); - Event.stop(event); - case Event.KEY_ESC: - this.hide(); - this.active = false; - Event.stop(event); - return; - case Event.KEY_LEFT: - case Event.KEY_RIGHT: - return; - case Event.KEY_UP: - this.markPrevious(); - this.render(); - if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event); - return; - case Event.KEY_DOWN: - this.markNext(); - this.render(); - if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event); - return; - } - else - if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || - (navigator.appVersion.indexOf('AppleWebKit') > 0 && event.keyCode == 0)) return; - - this.changed = true; - this.hasFocus = true; - - if(this.observer) clearTimeout(this.observer); - this.observer = - setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); - }, - - activate: function() { - this.changed = false; - this.hasFocus = true; - this.getUpdatedChoices(); - }, - - onHover: function(event) { - var element = Event.findElement(event, 'LI'); - if(this.index != element.autocompleteIndex) + baseInitialize: function( element, update, options ) { - this.index = element.autocompleteIndex; - this.render(); - } - Event.stop(event); - }, - - onClick: function(event) { - var element = Event.findElement(event, 'LI'); - this.index = element.autocompleteIndex; - this.selectEntry(); - this.hide(); - }, - - onBlur: function(event) { - // needed to make click events working - setTimeout(this.hide.bind(this), 250); - this.hasFocus = false; - this.active = false; - }, - - render: function() { - if(this.entryCount > 0) { - for (var i = 0; i < this.entryCount; i++) - this.index==i ? - Element.addClassName(this.getEntry(i),"selected") : - Element.removeClassName(this.getEntry(i),"selected"); - - if(this.hasFocus) { - this.show(); - this.active = true; - } - } else { - this.active = false; - this.hide(); - } - }, - - markPrevious: function() { - if(this.index > 0) this.index-- - else this.index = this.entryCount-1; - this.getEntry(this.index).scrollIntoView(true); - }, - - markNext: function() { - if(this.index < this.entryCount-1) this.index++ - else this.index = 0; - this.getEntry(this.index).scrollIntoView(false); - }, - - getEntry: function(index) { - return this.update.firstChild.childNodes[index]; - }, - - getCurrentEntry: function() { - return this.getEntry(this.index); - }, - - selectEntry: function() { - this.active = false; - this.updateElement(this.getCurrentEntry()); - }, - - updateElement: function(selectedElement) { - if (this.options.updateElement) { - this.options.updateElement(selectedElement); - return; - } - var value = ''; - if (this.options.select) { - var nodes = document.getElementsByClassName(this.options.select, selectedElement) || []; - if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); - } else - value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); - - var lastTokenPos = this.findLastToken(); - if (lastTokenPos != -1) { - var newValue = this.element.value.substr(0, lastTokenPos + 1); - var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/); - if (whitespace) - newValue += whitespace[0]; - this.element.value = newValue + value; - } else { - this.element.value = value; - } - this.element.focus(); - - if (this.options.afterUpdateElement) - this.options.afterUpdateElement(this.element, selectedElement); - }, - - updateChoices: function(choices) { - if(!this.changed && this.hasFocus) { - this.update.innerHTML = choices; - Element.cleanWhitespace(this.update); - Element.cleanWhitespace(this.update.firstChild); - - if(this.update.firstChild && this.update.firstChild.childNodes) { - this.entryCount = - this.update.firstChild.childNodes.length; - for (var i = 0; i < this.entryCount; i++) { - var entry = this.getEntry(i); - entry.autocompleteIndex = i; - this.addObservers(entry); - } - } else { + this.element = $(element); + this.update = $(update); + this.hasFocus = false; + this.changed = false; + this.active = false; + this.index = 0; this.entryCount = 0; - } - this.stopIndicator(); - this.index = 0; - - if(this.entryCount==1 && this.options.autoSelect) { + if ( this.setOptions ) + this.setOptions(options); + else + this.options = options || {}; + + this.options.paramName = this.options.paramName || this.element.name; + this.options.tokens = this.options.tokens || []; + this.options.frequency = this.options.frequency || 0.4; + this.options.minChars = this.options.minChars || 1; + this.options.onShow = this.options.onShow || function( element, update ) + { + if ( !update.style.position || update.style.position == 'absolute' ) + { + update.style.position = 'absolute'; + Position.clone(element, update, { + setHeight: false, + offsetTop: element.offsetHeight + }); + } + Effect.Appear(update, {duration:0.15}); + }; + this.options.onHide = this.options.onHide || function( element, update ) + { + new Effect.Fade(update, {duration:0.15}) + }; + + if ( typeof(this.options.tokens) == 'string' ) + this.options.tokens = new Array(this.options.tokens); + + this.observer = null; + + this.element.setAttribute('autocomplete', 'off'); + + Element.hide(this.update); + + Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this)); + Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this)); + }, + + show: function() + { + if ( Element.getStyle(this.update, 'display') == 'none' ) this.options.onShow(this.element, this.update); + if ( !this.iefix && (navigator.appVersion.indexOf('MSIE') > 0) && (navigator.userAgent.indexOf('Opera') < 0) && + (Element.getStyle(this.update, 'position') == 'absolute') ) + { + new Insertion.After(this.update, '<iframe id="' + this.update.id + '_iefix" ' + + 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' + + 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>'); + this.iefix = $(this.update.id + '_iefix'); + } + if ( this.iefix ) setTimeout(this.fixIEOverlapping.bind(this), 50); + }, + + fixIEOverlapping: function() + { + Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); + this.iefix.style.zIndex = 1; + this.update.style.zIndex = 2; + Element.show(this.iefix); + }, + + hide: function() + { + this.stopIndicator(); + if ( Element.getStyle(this.update, 'display') != 'none' ) this.options.onHide(this.element, this.update); + if ( this.iefix ) Element.hide(this.iefix); + }, + + startIndicator: function() + { + if ( this.options.indicator ) Element.show(this.options.indicator); + }, + + stopIndicator: function() + { + if ( this.options.indicator ) Element.hide(this.options.indicator); + }, + + onKeyPress: function( event ) + { + if ( this.active ) + switch ( event.keyCode ) + { + case Event.KEY_TAB: + case Event.KEY_RETURN: + this.selectEntry(); + Event.stop(event); + case Event.KEY_ESC: + this.hide(); + this.active = false; + Event.stop(event); + return; + case Event.KEY_LEFT: + case Event.KEY_RIGHT: + return; + case Event.KEY_UP: + this.markPrevious(); + this.render(); + if ( navigator.appVersion.indexOf('AppleWebKit') > 0 ) Event.stop(event); + return; + case Event.KEY_DOWN: + this.markNext(); + this.render(); + if ( navigator.appVersion.indexOf('AppleWebKit') > 0 ) Event.stop(event); + return; + } + else + if ( event.keyCode == Event.KEY_TAB || event.keyCode == Event.KEY_RETURN || + (navigator.appVersion.indexOf('AppleWebKit') > 0 && event.keyCode == 0) ) return; + + this.changed = true; + this.hasFocus = true; + + if ( this.observer ) clearTimeout(this.observer); + this.observer = setTimeout(this.onObserverEvent.bind(this), this.options.frequency * 1000); + }, + + activate: function() + { + this.changed = false; + this.hasFocus = true; + this.getUpdatedChoices(); + }, + + onHover: function( event ) + { + var element = Event.findElement(event, 'LI'); + if ( this.index != element.autocompleteIndex ) + { + this.index = element.autocompleteIndex; + this.render(); + } + Event.stop(event); + }, + + onClick: function( event ) + { + var element = Event.findElement(event, 'LI'); + this.index = element.autocompleteIndex; this.selectEntry(); this.hide(); - } else { - this.render(); - } - } - }, + }, - addObservers: function(element) { - Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); - Event.observe(element, "click", this.onClick.bindAsEventListener(this)); - }, - - onObserverEvent: function() { - this.changed = false; - if(this.getToken().length>=this.options.minChars) { - this.startIndicator(); - this.getUpdatedChoices(); - } else { - this.active = false; - this.hide(); - } - }, + onBlur: function( event ) + { + // needed to make click events working + setTimeout(this.hide.bind(this), 250); + this.hasFocus = false; + this.active = false; + }, + + render: function() + { + if ( this.entryCount > 0 ) + { + for ( var i = 0; i < this.entryCount; i++ ) + this.index == i ? Element.addClassName(this.getEntry(i), "selected") + : Element.removeClassName(this.getEntry(i), "selected"); + + if ( this.hasFocus ) + { + this.show(); + this.active = true; + } + } + else + { + this.active = false; + this.hide(); + } + }, + + markPrevious: function() + { + if ( this.index > 0 ) this.index-- + else this.index = this.entryCount - 1; + this.getEntry(this.index).scrollIntoView(true); + }, + + markNext: function() + { + if ( this.index < this.entryCount - 1 ) this.index++ + else this.index = 0; + this.getEntry(this.index).scrollIntoView(false); + }, + + getEntry: function( index ) + { + return this.update.firstChild.childNodes[index]; + }, + + getCurrentEntry: function() + { + return this.getEntry(this.index); + }, + + selectEntry: function() + { + this.active = false; + this.updateElement(this.getCurrentEntry()); + }, + + updateElement: function( selectedElement ) + { + if ( this.options.updateElement ) + { + this.options.updateElement(selectedElement); + return; + } + var value = ''; + if ( this.options.select ) + { + var nodes = document.getElementsByClassName(this.options.select, selectedElement) || []; + if ( nodes.length > 0 ) value = Element.collectTextNodes(nodes[0], this.options.select); + } + else + value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); + + var lastTokenPos = this.findLastToken(); + if ( lastTokenPos != -1 ) + { + var newValue = this.element.value.substr(0, lastTokenPos + 1); + var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/); + if ( whitespace ) + newValue += whitespace[0]; + this.element.value = newValue + value; + } + else + { + this.element.value = value; + } + this.element.focus(); + + if ( this.options.afterUpdateElement ) + this.options.afterUpdateElement(this.element, selectedElement); + }, + + updateChoices: function( choices ) + { + if ( !this.changed && this.hasFocus ) + { + this.update.innerHTML = choices; + Element.cleanWhitespace(this.update); + Element.cleanWhitespace(this.update.firstChild); + + if ( this.update.firstChild && this.update.firstChild.childNodes ) + { + this.entryCount = this.update.firstChild.childNodes.length; + for ( var i = 0; i < this.entryCount; i++ ) + { + var entry = this.getEntry(i); + entry.autocompleteIndex = i; + this.addObservers(entry); + } + } + else + { + this.entryCount = 0; + } + + this.stopIndicator(); + this.index = 0; + + if ( this.entryCount == 1 && this.options.autoSelect ) + { + this.selectEntry(); + this.hide(); + } + else + { + this.render(); + } + } + }, + + addObservers: function( element ) + { + Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); + Event.observe(element, "click", this.onClick.bindAsEventListener(this)); + }, + + onObserverEvent: function() + { + this.changed = false; + if ( this.getToken().length >= this.options.minChars ) + { + this.startIndicator(); + this.getUpdatedChoices(); + } + else + { + this.active = false; + this.hide(); + } + }, + + getToken: function() + { + var tokenPos = this.findLastToken(); + if ( tokenPos != -1 ) + var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/, '').replace(/\s+$/, ''); + else + var ret = this.element.value; + + return /\n/.test(ret) ? '' : ret; + }, - getToken: function() { - var tokenPos = this.findLastToken(); - if (tokenPos != -1) - var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,''); - else - var ret = this.element.value; - - return /\n/.test(ret) ? '' : ret; - }, - - findLastToken: function() { - var lastTokenPos = -1; - - for (var i=0; i<this.options.tokens.length; i++) { - var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]); - if (thisTokenPos > lastTokenPos) - lastTokenPos = thisTokenPos; + findLastToken: function() + { + var lastTokenPos = -1; + + for ( var i = 0; i < this.options.tokens.length; i++ ) + { + var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]); + if ( thisTokenPos > lastTokenPos ) + lastTokenPos = thisTokenPos; + } + return lastTokenPos; } - return lastTokenPos; - } } Ajax.Autocompleter = Class.create(); Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), { - initialize: function(element, update, url, options) { - this.baseInitialize(element, update, options); - this.options.asynchronous = true; - this.options.onComplete = this.onComplete.bind(this); - this.options.defaultParams = this.options.parameters || null; - this.url = url; - }, - - getUpdatedChoices: function() { - entry = encodeURIComponent(this.options.paramName) + '=' + - encodeURIComponent(this.getToken()); - - this.options.parameters = this.options.callback ? - this.options.callback(this.element, entry) : entry; - - if(this.options.defaultParams) - this.options.parameters += '&' + this.options.defaultParams; - - new Ajax.Request(this.url, this.options); - }, - - onComplete: function(request) { - this.updateChoices(request.responseText); - } + initialize: function( element, update, url, options ) + { + this.baseInitialize(element, update, options); + this.options.asynchronous = true; + this.options.onComplete = this.onComplete.bind(this); + this.options.defaultParams = this.options.parameters || null; + this.url = url; + }, + + getUpdatedChoices: function() + { + entry = encodeURIComponent(this.options.paramName) + '=' + encodeURIComponent(this.getToken()); + + this.options.parameters = this.options.callback ? this.options.callback(this.element, entry) : entry; + + if ( this.options.defaultParams ) + this.options.parameters += '&' + this.options.defaultParams; + + new Ajax.Request(this.url, this.options); + }, + + onComplete: function( request ) + { + this.updateChoices(request.responseText); + } }); @@ -394,63 +460,73 @@ Autocompleter.Local = Class.create(); Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), { - initialize: function(element, update, array, options) { - this.baseInitialize(element, update, options); - this.options.array = array; - }, - - getUpdatedChoices: function() { - this.updateChoices(this.options.selector(this)); - }, - - setOptions: function(options) { - this.options = Object.extend({ - choices: 10, - partialSearch: true, - partialChars: 2, - ignoreCase: true, - fullSearch: false, - selector: function(instance) { - var ret = []; // Beginning matches - var partial = []; // Inside matches - var entry = instance.getToken(); - var count = 0; - - for (var i = 0; i < instance.options.array.length && - ret.length < instance.options.choices ; i++) { - - var elem = instance.options.array[i]; - var foundPos = instance.options.ignoreCase ? - elem.toLowerCase().indexOf(entry.toLowerCase()) : - elem.indexOf(entry); - - while (foundPos != -1) { - if (foundPos == 0 && elem.length != entry.length) { - ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + - elem.substr(entry.length) + "</li>"); - break; - } else if (entry.length >= instance.options.partialChars && - instance.options.partialSearch && foundPos != -1) { - if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { - partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" + - elem.substr(foundPos, entry.length) + "</strong>" + elem.substr( - foundPos + entry.length) + "</li>"); - break; - } - } + initialize: function( element, update, array, options ) + { + this.baseInitialize(element, update, options); + this.options.array = array; + }, - foundPos = instance.options.ignoreCase ? - elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : - elem.indexOf(entry, foundPos + 1); - - } - } - if (partial.length) - ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)) - return "<ul>" + ret.join('') + "</ul>"; - } - }, options || {}); - } + getUpdatedChoices: function() + { + this.updateChoices(this.options.selector(this)); + }, + + setOptions: function( options ) + { + this.options = Object.extend({ + choices: 10, + partialSearch: true, + partialChars: 2, + ignoreCase: true, + fullSearch: false, + selector: function( instance ) + { + var ret = []; + // Beginning matches + var partial = []; + // Inside matches + var entry = instance.getToken(); + var count = 0; + + for ( var i = 0; i < instance.options.array.length && ret.length < instance.options.choices; i++ ) + { + + var elem = instance.options.array[i]; + var foundPos = instance.options.ignoreCase ? elem.toLowerCase().indexOf(entry.toLowerCase()) + : elem.indexOf(entry); + + while ( foundPos != -1 ) + { + if ( foundPos == 0 && elem.length != entry.length ) + { + ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + + elem.substr(entry.length) + "</li>"); + break; + } + else if ( entry.length >= instance.options.partialChars && instance.options.partialSearch && + foundPos != -1 ) + { + if ( instance.options.fullSearch || /\s/.test(elem.substr(foundPos - 1, 1)) ) + { + partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" + + elem.substr(foundPos, entry.length) + "</strong>" + + elem.substr(foundPos + entry.length) + "</li>"); + break; + } + } + + foundPos = + instance.options.ignoreCase ? elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) + : elem.indexOf(entry, foundPos + 1); + + } + } + if ( partial.length ) + ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)) + return "<ul>" + ret.join('') + "</ul>"; + } + }, options || {}); + } }); // AJAX in-place editor @@ -460,350 +536,407 @@ // Use this if you notice weird scrolling problems on some browsers, // the DOM might be a bit confused when this gets called so do this // waits 1 ms (with setTimeout) until it does the activation -Field.scrollFreeActivate = function(field) { - setTimeout(function() { - Field.activate(field); - }, 1); +Field.scrollFreeActivate = function( field ) +{ + setTimeout(function() + { + Field.activate(field); + }, 1); } Ajax.InPlaceEditor = Class.create(); Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99"; Ajax.InPlaceEditor.prototype = { - initialize: function(element, url, options) { - this.url = url; - this.element = $(element); - - this.options = Object.extend({ - okButton: true, - okText: "ok", - cancelLink: true, - cancelText: "cancel", - savingText: "Saving...", - clickToEditText: "Click to edit", - okText: "ok", - rows: 1, - onComplete: function(transport, element) { - new Effect.Highlight(element, {startcolor: this.options.highlightcolor}); - }, - onFailure: function(transport) { - alert("Error communicating with the server: " + transport.responseText.stripTags()); - }, - callback: function(form) { - return Form.serialize(form); - }, - handleLineBreaks: true, - loadingText: 'Loading...', - savingClassName: 'inplaceeditor-saving', - loadingClassName: 'inplaceeditor-loading', - formClassName: 'inplaceeditor-form', - highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor, - highlightendcolor: "#FFFFFF", - externalControl: null, - submitOnBlur: false, - ajaxOptions: {}, - evalScripts: false - }, options || {}); - - if(!this.options.formId && this.element.id) { - this.options.formId = this.element.id + "-inplaceeditor"; - if ($(this.options.formId)) { - // there's already a form with that name, don't specify an id - this.options.formId = null; - } - } - - if (this.options.externalControl) { - this.options.externalControl = $(this.options.externalControl); - } - - this.originalBackground = Element.getStyle(this.element, 'background-color'); - if (!this.originalBackground) { - this.originalBackground = "transparent"; - } - - this.element.title = this.options.clickToEditText; - - this.onclickListener = this.enterEditMode.bindAsEventListener(this); - this.mouseoverListener = this.enterHover.bindAsEventListener(this); - this.mouseoutListener = this.leaveHover.bindAsEventListener(this); - Event.observe(this.element, 'click', this.onclickListener); - Event.observe(this.element, 'mouseover', this.mouseoverListener); - Event.observe(this.element, 'mouseout', this.mouseoutListener); - if (this.options.externalControl) { - Event.observe(this.options.externalControl, 'click', this.onclickListener); - Event.observe(this.options.externalControl, 'mouseover', this.mouseoverListener); - Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener); - } - }, - enterEditMode: function(evt) { - if (this.saving) return; - if (this.editing) return; - this.editing = true; - this.onEnterEditMode(); - if (this.options.externalControl) { - Element.hide(this.options.externalControl); - } - Element.hide(this.element); - this.createForm(); - this.element.parentNode.insertBefore(this.form, this.element); - if (!this.options.loadTextURL) Field.scrollFreeActivate(this.editField); - // stop the event to avoid a page refresh in Safari - if (evt) { - Event.stop(evt); - } - return false; - }, - createForm: function() { - this.form = document.createElement("form"); - this.form.id = this.options.formId; - Element.addClassName(this.form, this.options.formClassName) - this.form.onsubmit = this.onSubmit.bind(this); - - this.createEditField(); - - if (this.options.textarea) { - var br = document.createElement("br"); - this.form.appendChild(br); - } + initialize: function( element, url, options ) + { + this.url = url; + this.element = $(element); - if (this.options.okButton) { - okButton = document.createElement("input"); - okButton.type = "submit"; - okButton.value = this.options.okText; - okButton.className = 'editor_ok_button'; - this.form.appendChild(okButton); - } + this.options = Object.extend({ + okButton: true, + okText: "ok", + cancelLink: true, + cancelText: "cancel", + savingText: "Saving...", + clickToEditText: "Click to edit", + okText: "ok", + rows: 1, + onComplete: function( transport, element ) + { + new Effect.Highlight(element, {startcolor: this.options.highlightcolor}); + }, + onFailure: function( transport ) + { + alert("Error communicating with the server: " + transport.responseText.stripTags()); + }, + callback: function( form ) + { + return Form.serialize(form); + }, + handleLineBreaks: true, + loadingText: 'Loading...', + savingClassName: 'inplaceeditor-saving', + loadingClassName: 'inplaceeditor-loading', + formClassName: 'inplaceeditor-form', + highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor, + highlightendcolor: "#FFFFFF", + externalControl: null, + submitOnBlur: false, + ajaxOptions: {}, + evalScripts: false + }, options || {}); + + if ( !this.options.formId && this.element.id ) + { + this.options.formId = this.element.id + "-inplaceeditor"; + if ( $(this.options.formId) ) + { + // there's already a form with that name, don't specify an id + this.options.formId = null; + } + } - if (this.options.cancelLink) { - cancelLink = document.createElement("a"); - cancelLink.href = "#"; - cancelLink.appendChild(document.createTextNode(this.options.cancelText)); - cancelLink.onclick = this.onclickCancel.bind(this); - cancelLink.className = 'editor_cancel'; - this.form.appendChild(cancelLink); - } - }, - hasHTMLLineBreaks: function(string) { - if (!this.options.handleLineBreaks) return false; - return string.match(/<br/i) || string.match(/<p>/i); - }, - convertHTMLLineBreaks: function(string) { - return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<p>/gi, ""); - }, - createEditField: function() { - var text; - if(this.options.loadTextURL) { - text = this.options.loadingText; - } else { - text = this.getText(); - } + if ( this.options.externalControl ) + { + this.options.externalControl = $(this.options.externalControl); + } - var obj = this; - - if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) { - this.options.textarea = false; - var textField = document.createElement("input"); - textField.obj = this; - textField.type = "text"; - textField.name = "value"; - textField.value = text; - textField.style.backgroundColor = this.options.highlightcolor; - textField.className = 'editor_field'; - var size = this.options.size || this.options.cols || 0; - if (size != 0) textField.size = size; - if (this.options.submitOnBlur) - textField.onblur = this.onSubmit.bind(this); - this.editField = textField; - } else { - this.options.textarea = true; - var textArea = document.createElement("textarea"); - textArea.obj = this; - textArea.name = "value"; - textArea.value = this.convertHTMLLineBreaks(text); - textArea.rows = this.options.rows; - textArea.cols = this.options.cols || 40; - textArea.className = 'editor_field'; - if (this.options.submitOnBlur) - textArea.onblur = this.onSubmit.bind(this); - this.editField = textArea; - } - - if(this.options.loadTextURL) { - this.loadExternalText(); - } - this.form.appendChild(this.editField); - }, - getText: function() { - return this.element.innerHTML; - }, - loadExternalText: function() { - Element.addClassName(this.form, this.options.loadingClassName); - this.editField.disabled = true; - new Ajax.Request( - this.options.loadTextURL, - Object.extend({ - asynchronous: true, - onComplete: this.onLoadedExternalText.bind(this) - }, this.options.ajaxOptions) - ); - }, - onLoadedExternalText: function(transport) { - Element.removeClassName(this.form, this.options.loadingClassName); - this.editField.disabled = false; - this.editField.value = transport.responseText.stripTags(); - Field.scrollFreeActivate(this.editField); - }, - onclickCancel: function() { - this.onComplete(); - this.leaveEditMode(); - return false; - }, - onFailure: function(transport) { - this.options.onFailure(transport); - if (this.oldInnerHTML) { - this.element.innerHTML = this.oldInnerHTML; - this.oldInnerHTML = null; - } - return false; - }, - onSubmit: function() { - // onLoading resets these so we need to save them away for the Ajax call - var form = this.form; - var value = this.editField.value; - - // do this first, sometimes the ajax call returns before we get a chance to switch on Saving... - // which means this will actually switch on Saving... *after* we've left edit mode causing Saving... - // to be displayed indefinitely - this.onLoading(); - - if (this.options.evalScripts) { - new Ajax.Request( - this.url, Object.extend({ - parameters: this.options.callback(form, value), - onComplete: this.onComplete.bind(this), - onFailure: this.onFailure.bind(this), - asynchronous:true, - evalScripts:true - }, this.options.ajaxOptions)); - } else { - new Ajax.Updater( - { success: this.element, - // don't update on failure (this could be an option) - failure: null }, - this.url, Object.extend({ - parameters: this.options.callback(form, value), - onComplete: this.onComplete.bind(this), - onFailure: this.onFailure.bind(this) + this.originalBackground = Element.getStyle(this.element, 'background-color'); + if ( !this.originalBackground ) + { + this.originalBackground = "transparent"; + } + + this.element.title = this.options.clickToEditText; + + this.onclickListener = this.enterEditMode.bindAsEventListener(this); + this.mouseoverListener = this.enterHover.bindAsEventListener(this); + this.mouseoutListener = this.leaveHover.bindAsEventListener(this); + Event.observe(this.element, 'click', this.onclickListener); + Event.observe(this.element, 'mouseover', this.mouseoverListener); + Event.observe(this.element, 'mouseout', this.mouseoutListener); + if ( this.options.externalControl ) + { + Event.observe(this.options.externalControl, 'click', this.onclickListener); + Event.observe(this.options.externalControl, 'mouseover', this.mouseoverListener); + Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener); + } + }, + enterEditMode: function( evt ) + { + if ( this.saving ) return; + if ( this.editing ) return; + this.editing = true; + this.onEnterEditMode(); + if ( this.options.externalControl ) + { + Element.hide(this.options.externalControl); + } + Element.hide(this.element); + this.createForm(); + this.element.parentNode.insertBefore(this.form, this.element); + if ( !this.options.loadTextURL ) Field.scrollFreeActivate(this.editField); + // stop the event to avoid a page refresh in Safari + if ( evt ) + { + Event.stop(evt); + } + return false; + }, + createForm: function() + { + this.form = document.createElement("form"); + this.form.id = this.options.formId; + Element.addClassName(this.form, this.options.formClassName) + this.form.onsubmit = this.onSubmit.bind(this); + + this.createEditField(); + + if ( this.options.textarea ) + { + var br = document.createElement("br"); + this.form.appendChild(br); + } + + if ( this.options.okButton ) + { + okButton = document.createElement("input"); + okButton.type = "submit"; + okButton.value = this.options.okText; + okButton.className = 'editor_ok_button'; + this.form.appendChild(okButton); + } + + if ( this.options.cancelLink ) + { + cancelLink = document.createElement("a"); + cancelLink.href = "#"; + cancelLink.appendChild(document.createTextNode(this.options.cancelText)); + cancelLink.onclick = this.onclickCancel.bind(this); + cancelLink.className = 'editor_cancel'; + this.form.appendChild(cancelLink); + } + }, + hasHTMLLineBreaks: function( string ) + { + if ( !this.options.handleLineBreaks ) return false; + return string.match(/<br/i) || string.match(/<p>/i); + }, + convertHTMLLineBreaks: function( string ) + { + return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<p>/gi, ""); + }, + createEditField: function() + { + var text; + if ( this.options.loadTextURL ) + { + text = this.options.loadingText; + } + else + { + text = this.getText(); + } + + var obj = this; + + if ( this.options.rows == 1 && !this.hasHTMLLineBreaks(text) ) + { + this.options.textarea = false; + var textField = document.createElement("input"); + textField.obj = this; + textField.type = "text"; + textField.name = "value"; + textField.value = text; + textField.style.backgroundColor = this.options.highlightcolor; + textField.className = 'editor_field'; + var size = this.options.size || this.options.cols || 0; + if ( size != 0 ) textField.size = size; + if ( this.options.submitOnBlur ) + textField.onblur = this.onSubmit.bind(this); + this.editField = textField; + } + else + { + this.options.textarea = true; + var textArea = document.createElement("textarea"); + textArea.obj = this; + textArea.name = "value"; + textArea.value = this.convertHTMLLineBreaks(text); + textArea.rows = this.options.rows; + textArea.cols = this.options.cols || 40; + textArea.className = 'editor_field'; + if ( this.options.submitOnBlur ) + textArea.onblur = this.onSubmit.bind(this); + this.editField = textArea; + } + + if ( this.options.loadTextURL ) + { + this.loadExternalText(); + } + this.form.appendChild(this.editField); + }, + getText: function() + { + return this.element.innerHTML; + }, + loadExternalText: function() + { + Element.addClassName(this.form, this.options.loadingClassName); + this.editField.disabled = true; + new Ajax.Request(this.options.loadTextURL, Object.extend({ + asynchronous: true, + onComplete: this.onLoadedExternalText.bind(this) }, this.options.ajaxOptions)); + }, + onLoadedExternalText: function( transport ) + { + Element.removeClassName(this.form, this.options.loadingClassName); + this.editField.disabled = false; + this.editField.value = transport.responseText.stripTags(); + Field.scrollFreeActivate(this.editField); + }, + onclickCancel: function() + { + this.onComplete(); + this.leaveEditMode(); + return false; + }, + onFailure: function( transport ) + { + this.options.onFailure(transport); + if ( this.oldInnerHTML ) + { + this.element.innerHTML = this.oldInnerHTML; + this.oldInnerHTML = null; + } + return false; + }, + onSubmit: function() + { + // onLoading resets these so we need to save them away for the Ajax call + var form = this.form; + var value = this.editField.value; + + // do this first, sometimes the ajax call returns before we get a chance to switch on Saving... + // which means this will actually switch on Saving... *after* we've left edit mode causing Saving... + // to be displayed indefinitely + this.onLoading(); + + if ( this.options.evalScripts ) + { + new Ajax.Request(this.url, Object.extend({ + parameters: this.options.callback(form, value), + onComplete: this.onComplete.bind(this), + onFailure: this.onFailure.bind(this), + asynchronous:true, + evalScripts:true + }, this.options.ajaxOptions)); + } + else + { + new Ajax.Updater({ success: this.element, + // don't update on failure (this could be an option) + failure: null }, this.url, Object.extend({ + parameters: this.options.callback(form, value), + onComplete: this.onComplete.bind(this), + onFailure: this.onFailure.bind(this) + }, this.options.ajaxOptions)); + } + // stop the event to avoid a page refresh in Safari + if ( arguments.length > 1 ) + { + Event.stop(arguments[0]); + } + return false; + }, + onLoading: function() + { + this.saving = true; + this.removeForm(); + this.leaveHover(); + this.showSaving(); + }, + showSaving: function() + { + this.oldInnerHTML = this.element.innerHTML; + this.element.innerHTML = this.options.savingText; + Element.addClassName(this.element, this.options.savingClassName); + this.element.style.backgroundColor = this.originalBackground; + Element.show(this.element); + }, + removeForm: function() + { + if ( this.form ) + { + if ( this.form.parentNode ) Element.remove(this.form); + this.form = null; + } + }, + enterHover: function() + { + if ( this.saving ) return; + this.element.style.backgroundColor = this.options.highlightcolor; + if ( this.effect ) + { + this.effect.cancel(); + } + Element.addClassName(this.element, this.options.hoverClassName) + }, + leaveHover: function() + { + if ( this.options.backgroundColor ) + { + this.element.style.backgroundColor = this.oldBackground; + } + Element.removeClassName(this.element, this.options.hoverClassName) + if ( this.saving ) return; + this.effect = new Effect.Highlight(this.element, { + startcolor: this.options.highlightcolor, + endcolor: this.options.highlightendcolor, + restorecolor: this.originalBackground + }); + }, + leaveEditMode: function() + { + Element.removeClassName(this.element, this.options.savingClassName); + this.removeForm(); + this.leaveHover(); + this.element.style.backgroundColor = this.originalBackground; + Element.show(this.element); + if ( this.options.externalControl ) + { + Element.show(this.options.externalControl); + } + this.editing = false; + this.saving = false; + this.oldInnerHTML = null; + this.onLeaveEditMode(); + }, + onComplete: function( transport ) + { + this.leaveEditMode(); + this.options.onComplete.bind(this)(transport, this.element); + }, + onEnterEditMode: function() + { + }, + onLeaveEditMode: function() + { + }, + dispose: function() + { + if ( this.oldInnerHTML ) + { + this.element.innerHTML = this.oldInnerHTML; + } + this.leaveEditMode(); + Event.stopObserving(this.element, 'click', this.onclickListener); + Event.stopObserving(this.element, 'mouseover', this.mouseoverListener); + Event.stopObserving(this.element, 'mouseout', this.mouseoutListener); + if ( this.options.externalControl ) + { + Event.stopObserving(this.options.externalControl, 'click', this.onclickListener); + Event.stopObserving(this.options.externalControl, 'mouseover', this.mouseoverListener); + Event.stopObserving(this.options.externalControl, 'mouseout', this.mouseoutListener); + } } - // stop the event to avoid a page refresh in Safari - if (arguments.length > 1) { - Event.stop(arguments[0]); - } - return false; - }, - onLoading: function() { - this.saving = true; - this.removeForm(); - this.leaveHover(); - this.showSaving(); - }, - showSaving: function() { - this.oldInnerHTML = this.element.innerHTML; - this.element.innerHTML = this.options.savingText; - Element.addClassName(this.element, this.options.savingClassName); - this.element.style.backgroundColor = this.originalBackground; - Element.show(this.element); - }, - removeForm: function() { - if(this.form) { - if (this.form.parentNode) Element.remove(this.form); - this.form = null; - } - }, - enterHover: function() { - if (this.saving) return; - this.element.style.backgroundColor = this.options.highlightcolor; - if (this.effect) { - this.effect.cancel(); - } - Element.addClassName(this.element, this.options.hoverClassName) - }, - leaveHover: function() { - if (this.options.backgroundColor) { - this.element.style.backgroundColor = this.oldBackground; - } - Element.removeClassName(this.element, this.options.hoverClassName) - if (this.saving) return; - this.effect = new Effect.Highlight(this.element, { - startcolor: this.options.highlightcolor, - endcolor: this.options.highlightendcolor, - restorecolor: this.originalBackground - }); - }, - leaveEditMode: function() { - Element.removeClassName(this.element, this.options.savingClassName); - this.removeForm(); - this.leaveHover(); - this.element.style.backgroundColor = this.originalBackground; - Element.show(this.element); - if (this.options.externalControl) { - Element.show(this.options.externalControl); - } - this.editing = false; - this.saving = false; - this.oldInnerHTML = null; - this.onLeaveEditMode(); - }, - onComplete: function(transport) { - this.leaveEditMode(); - this.options.onComplete.bind(this)(transport, this.element); - }, - onEnterEditMode: function() {}, - onLeaveEditMode: function() {}, - dispose: function() { - if (this.oldInnerHTML) { - this.element.innerHTML = this.oldInnerHTML; - } - this.leaveEditMode(); - Event.stopObserving(this.element, 'click', this.onclickListener); - Event.stopObserving(this.element, 'mouseover', this.mouseoverListener); - Event.stopObserving(this.element, 'mouseout', this.mouseoutListener); - if (this.options.externalControl) { - Event.stopObserving(this.options.externalControl, 'click', this.onclickListener); - Event.stopObserving(this.options.externalControl, 'mouseover', this.mouseoverListener); - Event.stopObserving(this.options.externalControl, 'mouseout', this.mouseoutListener); - } - } }; Ajax.InPlaceCollectionEditor = Class.create(); Object.extend(Ajax.InPlaceCollectionEditor.prototype, Ajax.InPlaceEditor.prototype); Object.extend(Ajax.InPlaceCollectionEditor.prototype, { - createEditField: function() { - if (!this.cached_selectTag) { - var selectTag = document.createElement("select"); - var collection = this.options.collection || []; - var optionTag; - collection.each(function(e,i) { - optionTag = document.createElement("option"); - optionTag.value = (e instanceof Array) ? e[0] : e; - if((typeof this.options.value == 'undefined') && - ((e instanceof Array) ? this.element.innerHTML == e[1] : e == optionTag.value)) optionTag.selected = true; - if(this.options.value==optionTag.value) optionTag.selected = true; - optionTag.appendChild(document.createTextNode((e instanceof Array) ? e[1] : e)); - selectTag.appendChild(optionTag); - }.bind(this)); - this.cached_selectTag = selectTag; - } + createEditField: function() + { + if ( !this.cached_selectTag ) + { + var selectTag = document.createElement("select"); + var collection = this.options.collection || []; + var optionTag; + collection.each(function( e, i ) + { + optionTag = document.createElement("option"); + optionTag.value = (e instanceof Array) ? e[0] : e; + if ( (typeof this.options.value == 'undefined') && + ((e instanceof Array) ? this.element.innerHTML == e[1] : e == + optionTag.value) ) optionTag.selected = + true; + if ( this.options.value == optionTag.value ) optionTag.selected = true; + optionTag.appendChild(document.createTextNode((e instanceof Array) ? e[1] : e)); + selectTag.appendChild(optionTag); + }.bind(this)); + this.cached_selectTag = selectTag; + } - this.editField = this.cached_selectTag; - if(this.options.loadTextURL) this.loadExternalText(); - this.form.appendChild(this.editField); - this.options.callback = function(form, value) { - return "value=" + encodeURIComponent(value); + this.editField = this.cached_selectTag; + if ( this.options.loadTextURL ) this.loadExternalText(); + this.form.appendChild(this.editField); + this.options.callback = function( form, value ) + { + return "value=" + encodeURIComponent(value); + } } - } }); // Delayed observer, like Form.Element.Observer, @@ -812,22 +945,25 @@ Form.Element.DelayedObserver = Class.create(); Form.Element.DelayedObserver.prototype = { - initialize: function(element, delay, callback) { - this.delay = delay || 0.5; - this.element = $(element); - this.callback = callback; - this.timer = null; - this.lastValue = $F(this.element); - Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); - }, - delayedListener: function(event) { - if(this.lastValue == $F(this.element)) return; - if(this.timer) clearTimeout(this.timer); - this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); - this.lastValue = $F(this.element); - }, - onTimerEvent: function() { - this.timer = null; - this.callback(this.element, $F(this.element)); - } + initialize: function( element, delay, callback ) + { + this.delay = delay || 0.5; + this.element = $(element); + this.callback = callback; + this.timer = null; + this.lastValue = $F(this.element); + Event.observe(this.element, 'keyup', this.delayedListener.bindAsEventListener(this)); + }, + delayedListener: function( event ) + { + if ( this.lastValue == $F(this.element) ) return; + if ( this.timer ) clearTimeout(this.timer); + this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); + this.lastValue = $F(this.element); + }, + onTimerEvent: function() + { + this.timer = null; + this.callback(this.element, $F(this.element)); + } };
