lastTokenPos)
- lastTokenPos = thisTokenPos;
- }
- 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);
- }
-
-});
-
-// The local array autocompleter. Used when you'd prefer to
-// inject an array of autocompletion options into the page, rather
-// than sending out Ajax queries, which can be quite slow sometimes.
-//
-// The constructor takes four parameters. The first two are, as usual,
-// the id of the monitored textbox, and id of the autocompletion menu.
-// The third is the array you want to autocomplete from, and the fourth
-// is the options block.
-//
-// Extra local autocompletion options:
-// - choices - How many autocompletion choices to offer
-//
-// - partialSearch - If false, the autocompleter will match entered
-// text only at the beginning of strings in the
-// autocomplete array. Defaults to true, which will
-// match text at the beginning of any *word* in the
-// strings in the autocomplete array. If you want to
-// search anywhere in the string, additionally set
-// the option fullSearch to true (default: off).
-//
-// - fullSsearch - Search anywhere in autocomplete array strings.
-//
-// - partialChars - How many characters to enter before triggering
-// a partial match (unlike minChars, which defines
-// how many characters are required to do any match
-// at all). Defaults to 2.
-//
-// - ignoreCase - Whether to ignore case when autocompleting.
-// Defaults to true.
-//
-// It's possible to pass in a custom function as the 'selector'
-// option, if you prefer to write your own autocompletion logic.
-// In that case, the other options above will not apply unless
-// you support them.
-
-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("" + elem.substr(0, entry.length) + "" +
- elem.substr(entry.length) + "");
- 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("" + elem.substr(0, foundPos) + "" +
- elem.substr(foundPos, entry.length) + "" + elem.substr(
- foundPos + entry.length) + "");
- 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 "";
- }
- }, options || {});
- }
-});
-
-// AJAX in-place editor
-//
-// see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor
-
-// 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);
-}
-
-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({
- paramName: "value",
- 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);
- }
-
- 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(/
/i);
- },
- convertHTMLLineBreaks: function(string) {
- return string.replace(/
/gi, "\n").replace(/
/gi, "\n").replace(/<\/p>/gi, "\n").replace(//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 = this.options.paramName;
- 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 = this.options.paramName;
- 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);
- }
- }
-};
-
-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;
- }
-
- 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,
-// but waits for delay after last key input
-// Ideal for live-search fields
-
-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));
- }
-};
--
cgit v1.2.3