0
-// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
0
-// (c) 2005, 2006 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
0
-// (c) 2005, 2006 Jon Tirsen (http://www.tirsen.com)
0
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
0
+// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
0
+// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
0
if(typeof Effect == 'undefined')
0
throw("controls.js requires including script.aculo.us' effects.js library");
0
-Autocompleter.Base = function() {};
0
-Autocompleter.Base.prototype = {
0
+var Autocompleter = { }
0
+Autocompleter.Base = Class.create({
0
baseInitialize: function(element, update, options) {
0
- this.element = $(element);
0
+ this.element = element;
0
this.update = $(update);
0
+ this.oldElementValue = this.element.value;
0
this.setOptions(options);
0
- this.options = options || {
};
0
+ this.options = options || {
};
0
this.options.paramName = this.options.paramName || this.element.name;
0
this.options.tokens = this.options.tokens || [];
0
@@ -74,6 +75,9 @@ Autocompleter.Base.prototype = {
0
if(typeof(this.options.tokens) == 'string')
0
this.options.tokens = new Array(this.options.tokens);
0
+ // Force carriage returns as token delimiters anyway
0
+ if (!this.options.tokens.include('\n'))
0
+ this.options.tokens.push('\n');
0
@@ -81,15 +85,14 @@ Autocompleter.Base.prototype = {
0
Element.hide(this.update);
0
- Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this));
0
- Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this));
0
+ Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
0
+ Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
0
if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
0
- (navigator.appVersion.indexOf('MSIE')>0) &&
0
- (navigator.userAgent.indexOf('Opera')<0) &&
0
+ (Prototype.Browser.IE) &&
0
(Element.getStyle(this.update, 'position')=='absolute')) {
0
new Insertion.After(this.update,
0
'<iframe id="' + this.update.id + '_iefix" '+
0
@@ -139,17 +142,17 @@ Autocompleter.Base.prototype = {
0
-
if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
0
-
if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
0
if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
0
- (
navigator.appVersion.indexOf('AppleWebKit') > 0 && event.keyCode == 0)) return;
0
+ (
Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
0
@@ -195,7 +198,6 @@ Autocompleter.Base.prototype = {
0
Element.addClassName(this.getEntry(i),"selected") :
0
Element.removeClassName(this.getEntry(i),"selected");
0
@@ -238,21 +240,22 @@ Autocompleter.Base.prototype = {
0
if (this.options.select) {
0
- var nodes =
document.getElementsByClassName(this.options.select, selectedElement) || [];
0
+ var nodes =
$(selectedElement).select('.' + this.options.select) || [];
0
if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
0
value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
0
- var lastTokenPos = this.findLastToken();
0
- if (lastTokenPos != -1) {
0
- var newValue = this.element.value.substr(0, lastTokenPos + 1);
0
- var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/);
0
+ var bounds = this.getTokenBounds();
0
+ if (bounds[0] != -1) {
0
+ var newValue = this.element.value.substr(0, bounds[0]);
0
+ var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
0
newValue += whitespace[0];
0
- this.element.value = newValue + value
;
0
+ this.element.value = newValue + value
+ this.element.value.substr(bounds[1]);
0
this.element.value = value;
0
+ this.oldElementValue = this.element.value;
0
if (this.options.afterUpdateElement)
0
@@ -296,39 +299,48 @@ Autocompleter.Base.prototype = {
0
onObserverEvent: function() {
0
+ this.tokenBounds = null;
0
if(this.getToken().length>=this.options.minChars) {
0
- this.startIndicator();
0
this.getUpdatedChoices();
0
+ this.oldElementValue = this.element.value;
0
- var tokenPos = this.findLastToken();
0
- var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,'');
0
- var ret = this.element.value;
0
- return /\n/.test(ret) ? '' : ret;
0
- findLastToken: function() {
0
- var lastTokenPos = -1;
0
- for (var i=0; i<this.options.tokens.length; i++) {
0
- var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]);
0
- if (thisTokenPos > lastTokenPos)
0
- lastTokenPos = thisTokenPos;
0
+ var bounds = this.getTokenBounds();
0
+ return this.element.value.substring(bounds[0], bounds[1]).strip();
0
+ getTokenBounds: function() {
0
+ if (null != this.tokenBounds) return this.tokenBounds;
0
+ var value = this.element.value;
0
+ if (value.strip().empty()) return [-1, 0];
0
+ var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
0
+ var offset = (diff == this.oldElementValue.length ? 1 : 0);
0
+ var prevTokenPos = -1, nextTokenPos = value.length;
0
+ for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
0
+ tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
0
+ if (tp > prevTokenPos) prevTokenPos = tp;
0
+ tp = value.indexOf(this.options.tokens[index], diff + offset);
0
+ if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
0
+ return
(this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
0
+Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
0
+ var boundary = Math.min(newS.length, oldS.length);
0
+ for (var index = 0; index < boundary; ++index)
0
+ if (newS[index] != oldS[index])
0
-Ajax.Autocompleter = Class.create();
0
-Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), {
0
+Ajax.Autocompleter = Class.create(Autocompleter.Base, {
0
initialize: function(element, update, url, options) {
0
this.baseInitialize(element, update, options);
0
this.options.asynchronous = true;
0
@@ -338,7 +350,9 @@ Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.pro
0
getUpdatedChoices: function() {
0
- entry = encodeURIComponent(this.options.paramName) + '=' +
0
+ this.startIndicator();
0
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
0
encodeURIComponent(this.getToken());
0
this.options.parameters = this.options.callback ?
0
@@ -346,14 +360,13 @@ Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.pro
0
if(this.options.defaultParams)
0
this.options.parameters += '&' + this.options.defaultParams;
0
new Ajax.Request(this.url, this.options);
0
onComplete: function(request) {
0
this.updateChoices(request.responseText);
0
// The local array autocompleter. Used when you'd prefer to
0
@@ -391,8 +404,7 @@ Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.pro
0
// In that case, the other options above will not apply unless
0
-Autocompleter.Local = Class.create();
0
-Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
0
+Autocompleter.Local = Class.create(Autocompleter.Base, {
0
initialize: function(element, update, array, options) {
0
this.baseInitialize(element, update, options);
0
this.options.array = array;
0
@@ -448,13 +460,12 @@ Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
0
ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
0
return "<ul>" + ret.join('') + "</ul>";
0
-// AJAX in-place editor
0
-// see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor
0
+// AJAX in-place editor and collection editor
0
+// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
0
// Use this if you notice weird scrolling problems on some browsers,
0
// the DOM might be a bit confused when this gets called so do this
0
@@ -465,353 +476,472 @@ Field.scrollFreeActivate = function(field) {
0
-Ajax.InPlaceEditor = Class.create();
0
-Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99";
0
-Ajax.InPlaceEditor.prototype = {
0
+Ajax.InPlaceEditor = Class.create({
0
initialize: function(element, url, options) {
0
- this.element = $(element);
0
- this.options = Object.extend({
0
- savingText: "Saving...",
0
- clickToEditText: "Click to edit",
0
- onComplete: function(transport, element) {
0
- new Effect.Highlight(element, {startcolor: this.options.highlightcolor});
0
- onFailure: function(transport) {
0
- alert("Error communicating with the server: " + transport.responseText.stripTags());
0
- callback: function(form) {
0
- return Form.serialize(form);
0
- handleLineBreaks: true,
0
- loadingText: 'Loading...',
0
- savingClassName: 'inplaceeditor-saving',
0
- loadingClassName: 'inplaceeditor-loading',
0
- formClassName: 'inplaceeditor-form',
0
- highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,
0
- highlightendcolor: "#FFFFFF",
0
- externalControl: null,