controls.js revision ada1678a4262b208a7b87391f520a7767d25287c
// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// (c) 2005, 2006 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
// (c) 2005, 2006 Jon Tirsen (http://www.tirsen.com)
// Contributors:
// Richard Livsey
// Rahul Bhargava
// Rob Wills
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
// Autocompleter.Base handles all the autocompletion functionality
// that's independent of the data source for autocompletion. This
// includes drawing the autocompletion menu, observing keyboard
// and mouse events, and similar.
//
// Specific autocompleters need to provide, at the very least,
// a getUpdatedChoices function that will be invoked every time
// the text inside the monitored textbox changes. This method
// should get the text for which to provide autocompletion by
// invoking this.getToken(), NOT by directly accessing
// this.element.value. This is to allow incremental tokenized
// autocompletion. Specific auto-completion logic (AJAX, etc)
// belongs in getUpdatedChoices.
//
// Tokenized incremental autocompletion is enabled automatically
// when an autocompleter is instantiated with the 'tokens' option
// in the options parameter, e.g.:
// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
// will incrementally autocomplete with a comma as the token.
// Additionally, ',' in the above example can be replaced with
// a token array, e.g. { tokens: [',', '\n'] } which
// enables autocompletion on multiple tokens. This is most
// 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");
var Autocompleter = {}
Autocompleter.Base = function() {};
this.hasFocus = false;
this.changed = false;
this.active = false;
this.index = 0;
this.entryCount = 0;
if(this.setOptions)
this.setOptions(options);
else
setHeight: false,
});
}
};
this.observer = null;
},
show: function() {
if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
if(!this.iefix &&
'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
}
},
fixIEOverlapping: function() {
},
hide: function() {
this.stopIndicator();
if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
},
startIndicator: function() {
},
stopIndicator: function() {
},
onKeyPress: function(event) {
if(this.active)
case Event.KEY_RETURN:
this.selectEntry();
this.hide();
this.active = false;
return;
return;
this.markPrevious();
this.render();
return;
this.markNext();
this.render();
return;
}
else
this.changed = true;
this.hasFocus = true;
this.observer =
},
activate: function() {
this.changed = false;
this.hasFocus = true;
this.getUpdatedChoices();
},
{
this.render();
}
},
this.selectEntry();
this.hide();
},
// needed to make click events working
this.hasFocus = false;
this.active = false;
},
render: function() {
if(this.entryCount > 0) {
for (var i = 0; i < this.entryCount; i++)
this.index==i ?
if(this.hasFocus) {
this.show();
this.active = true;
}
} else {
this.active = false;
this.hide();
}
},
markPrevious: function() {
},
markNext: function() {
else this.index = 0;
},
},
getCurrentEntry: function() {
},
selectEntry: function() {
this.active = false;
this.updateElement(this.getCurrentEntry());
},
updateElement: function(selectedElement) {
if (this.options.updateElement) {
return;
}
var value = '';
} else
var lastTokenPos = this.findLastToken();
if (lastTokenPos != -1) {
if (whitespace)
} else {
}
if (this.options.afterUpdateElement)
},
updateChoices: function(choices) {
this.entryCount =
for (var i = 0; i < this.entryCount; i++) {
entry.autocompleteIndex = i;
this.addObservers(entry);
}
} else {
this.entryCount = 0;
}
this.stopIndicator();
this.index = 0;
this.selectEntry();
this.hide();
} else {
this.render();
}
}
},
addObservers: function(element) {
},
onObserverEvent: function() {
this.changed = false;
this.startIndicator();
this.getUpdatedChoices();
} else {
this.active = false;
this.hide();
}
},
getToken: function() {
var tokenPos = this.findLastToken();
if (tokenPos != -1)
else
},
findLastToken: function() {
var lastTokenPos = -1;
if (thisTokenPos > lastTokenPos)
}
return lastTokenPos;
}
}
this.options.asynchronous = true;
},
getUpdatedChoices: function() {
encodeURIComponent(this.getToken());
if(this.options.defaultParams)
},
onComplete: function(request) {
}
});
// 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.
},
getUpdatedChoices: function() {
},
setOptions: function(options) {
choices: 10,
partialSearch: true,
partialChars: 2,
ignoreCase: true,
fullSearch: false,
var ret = []; // Beginning matches
var partial = []; // Inside matches
var count = 0;
while (foundPos != -1) {
break;
break;
}
}
}
}
}
}, 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
setTimeout(function() {
}, 1);
}
paramName: "value",
okButton: true,
okText: "ok",
cancelLink: true,
cancelText: "cancel",
savingText: "Saving...",
clickToEditText: "Click to edit",
okText: "ok",
rows: 1,
},
},
},
handleLineBreaks: true,
loadingText: 'Loading...',
savingClassName: 'inplaceeditor-saving',
loadingClassName: 'inplaceeditor-loading',
formClassName: 'inplaceeditor-form',
highlightendcolor: "#FFFFFF",
externalControl: null,
submitOnBlur: false,
ajaxOptions: {},
evalScripts: false
}, options || {});
// there's already a form with that name, don't specify an id
}
}
if (this.options.externalControl) {
}
if (!this.originalBackground) {
this.originalBackground = "transparent";
}
if (this.options.externalControl) {
}
},
enterEditMode: function(evt) {
if (this.saving) return;
if (this.editing) return;
this.editing = true;
this.onEnterEditMode();
if (this.options.externalControl) {
}
this.createForm();
// stop the event to avoid a page refresh in Safari
if (evt) {
}
return false;
},
createForm: function() {
this.createEditField();
}
}
if (this.options.cancelLink) {
}
},
hasHTMLLineBreaks: function(string) {
if (!this.options.handleLineBreaks) return false;
},
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) {
} else {
}
var obj = this;
if (this.options.submitOnBlur)
} else {
if (this.options.submitOnBlur)
}
if(this.options.loadTextURL) {
this.loadExternalText();
}
},
getText: function() {
},
loadExternalText: function() {
this.options.loadTextURL,
Object.extend({
asynchronous: true,
}, this.options.ajaxOptions)
);
},
onLoadedExternalText: function(transport) {
},
onclickCancel: function() {
this.onComplete();
this.leaveEditMode();
return false;
},
if (this.oldInnerHTML) {
this.oldInnerHTML = null;
}
return false;
},
onSubmit: function() {
// onLoading resets these so we need to save them away for the Ajax call
// 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) {
asynchronous:true,
evalScripts:true
}, this.options.ajaxOptions));
} else {
// don't update on failure (this could be an option)
failure: null },
}, this.options.ajaxOptions));
}
// stop the event to avoid a page refresh in Safari
}
return false;
},
onLoading: function() {
this.saving = true;
this.removeForm();
this.leaveHover();
this.showSaving();
},
showSaving: function() {
},
removeForm: function() {
if(this.form) {
this.form = null;
}
},
enterHover: function() {
if (this.saving) return;
if (this.effect) {
}
},
leaveHover: function() {
if (this.options.backgroundColor) {
}
if (this.saving) return;
});
},
leaveEditMode: function() {
this.removeForm();
this.leaveHover();
if (this.options.externalControl) {
}
this.editing = false;
this.saving = false;
this.oldInnerHTML = null;
this.onLeaveEditMode();
},
onComplete: function(transport) {
this.leaveEditMode();
},
onEnterEditMode: function() {},
onLeaveEditMode: function() {},
dispose: function() {
if (this.oldInnerHTML) {
}
this.leaveEditMode();
if (this.options.externalControl) {
}
}
};
createEditField: function() {
if (!this.cached_selectTag) {
var optionTag;
collection.each(function(e,i) {
((e instanceof Array) ? this.element.innerHTML == e[1] : e == optionTag.value)) optionTag.selected = true;
}.bind(this));
this.cached_selectTag = selectTag;
}
this.editField = this.cached_selectTag;
}
}
});
// Delayed observer, like Form.Element.Observer,
// but waits for delay after last key input
// Ideal for live-search fields
this.timer = null;
},
delayedListener: function(event) {
},
onTimerEvent: function() {
this.timer = null;
}
};