rhymix/modules/editor/skins/xquared/javascripts/ui/Control.js
haneul 7c3b336e41 17223554 : xquared upgrade to 0.7
git-svn-id: http://xe-core.googlecode.com/svn/sandbox@4968 201d5d3c-b55e-5fd7-737f-ddc643e51545
2008-11-24 08:52:19 +00:00

404 lines
No EOL
10 KiB
JavaScript

/**
* @namespace UI Controls
*
* @requires Xquared.js
* @requires ui/Base.js
*/
xq.ui.FormDialog = xq.Class(/** @lends xq.ui.FormDialog.prototype */ {
/**
* Displays given HTML form as a dialog.
*
* @constructs
* @param {xq.Editor} xed Dialog owner.
* @param {String} html HTML string which contains FORM.
* @param {Function} [onLoadHandler] callback function to be called when the form is loaded.
* @param {Function} [onCloseHandler] callback function to be called when the form is closed.
*/
initialize: function(xed, html, onLoadHandler, onCloseHandler) {
xq.addToFinalizeQueue(this);
this.xed = xed;
this.html = html;
this.onLoadHandler = onLoadHandler || function() {};
this.onCloseHandler = onCloseHandler || function() {};
this.form = null;
},
/**
* Shows dialog
*
* @param {Object} [options] collection of options
*/
show: function(options) {
options = options || {};
options.position = options.position || 'centerOfWindow';
options.mode = options.mode || 'modal';
options.cancelOnEsc = options.cancelOnEsc || true;
var self = this;
// create and append container
var container = document.createElement('DIV');
container.style.display = 'none';
document.body.appendChild(container);
// initialize form
container.innerHTML = this.html;
this.form = container.getElementsByTagName('FORM')[0];
this.form.onsubmit = function() {
self.onCloseHandler(xq.serializeForm(this));
self.close();
return false;
};
var cancelButton = xq.getElementsByClassName(this.form, 'cancel')[0];
cancelButton.onclick = function() {
self.onCloseHandler();
self.close();
};
if(options.mode === 'modal') {
this.dimmed = document.createElement('DIV');
this.dimmed.style.position = 'absolute';
this.dimmed.style.backgroundColor = 'black';
this.dimmed.style.opacity = 0.5;
this.dimmed.style.filter = 'alpha(opacity=50)';
this.dimmed.style.zIndex=902;
this.dimmed.style.top='0px';
this.dimmed.style.left='0px';
document.body.appendChild(this.dimmed);
this.resizeDimmedDiv = function(e) {
this.dimmed.style.display='none';
this.dimmed.style.width=document.documentElement.scrollWidth+'px';
this.dimmed.style.height=document.documentElement.scrollHeight+'px';
this.dimmed.style.display='block';
}.bind(this);
xq.observe(window, 'resize', this.resizeDimmedDiv);
this.resizeDimmedDiv();
}
// append dialog
document.body.appendChild(this.form);
container.parentNode.removeChild(container);
// place dialog to center of window
this.setPosition(options.position);
// give focus
var elementToFocus = xq.getElementsByClassName(this.form, 'initialFocus');
if(elementToFocus.length > 0) elementToFocus[0].focus();
// handle cancelOnEsc option
if(options.cancelOnEsc) {
xq.observe(this.form, 'keydown', function(e) {
if(e.keyCode === 27) {
this.onCloseHandler();
this.close();
}
}.bind(this));
}
this.onLoadHandler(this);
},
/**
* Closes dialog
*/
close: function() {
this.form.parentNode.removeChild(this.form);
if(this.dimmed) {
this.dimmed.parentNode.removeChild(this.dimmed);
this.dimmed = null;
xq.stopObserving(window, 'resize', this.resizeDimmedDiv);
this.resizeDimmedDiv = null;
}
},
/**
* Sets position of dialog
*
* @param {String} target "centerOfWindow" or "centerOfEditor"
*/
setPosition: function(target) {
var targetElement = null;
var left = 0;
var top = 0;
if(target === 'centerOfWindow') {
targetElement = document.documentElement;
left += targetElement.scrollLeft;
top += targetElement.scrollTop;
} else if(target === 'centerOfEditor') {
targetElement = this.xed.getCurrentEditMode() == 'wysiwyg' ? this.xed.wysiwygEditorDiv : this.xed.sourceEditorDiv;
var o = targetElement;
do {
left += o.offsetLeft;
top += o.offsetTop;
} while(o = o.offsetParent)
} else if(target === 'nearbyCaret') {
throw "Not implemented yet";
} else {
throw "Invalid argument: " + target;
}
var targetWidth = targetElement.clientWidth;
var targetHeight = targetElement.clientHeight;
var dialogWidth = this.form.clientWidth;
var dialogHeight = this.form.clientHeight;
left += parseInt((targetWidth - dialogWidth) / 2);
top += parseInt((targetHeight - dialogHeight) / 2);
this.form.style.left = left + "px";
this.form.style.top = top + "px";
}
})
xq.ui.QuickSearchDialog = xq.Class(/** @lends xq.ui.QuickSearchDialog.prototype */ {
/**
* Displays quick search dialog
*
* @constructs
* @param {xq.Editor} xed Dialog owner.
* @param {Object} param Parameters.
*/
initialize: function(xed, param) {
xq.addToFinalizeQueue(this);
this.xed = xed;
this.rdom = xq.rdom.Base.createInstance();
this.param = param;
if(!this.param.renderItem) this.param.renderItem = function(item) {
return this.rdom.getInnerText(item);
}.bind(this);
this.container = null;
},
getQuery: function() {
if(!this.container) return "";
return this._getInputField().value;
},
onSubmit: function(e) {
if(this.matchCount() > 0) {
this.param.onSelect(this.xed, this.list[this._getSelectedIndex()]);
}
this.close();
xq.stopEvent(e);
return false;
},
onCancel: function(e) {
if(this.param.onCancel) this.param.onCancel(this.xed);
this.close();
},
onBlur: function(e) {
// @WORKAROUND: Ugly
setTimeout(function() {this.onCancel(e)}.bind(this), 400);
},
onKey: function(e) {
var esc = new xq.Shortcut("ESC");
var enter = new xq.Shortcut("ENTER");
var up = new xq.Shortcut("UP");
var down = new xq.Shortcut("DOWN");
if(esc.matches(e)) {
this.onCancel(e);
} else if(enter.matches(e)) {
this.onSubmit(e);
} else if(up.matches(e)) {
this._moveSelectionUp();
} else if(down.matches(e)) {
this._moveSelectionDown();
} else {
this.updateList();
}
},
onClick: function(e) {
var target = e.srcElement || e.target;
if(target.nodeName === "LI") {
var index = this._getIndexOfLI(target);
this.param.onSelect(this.xed, this.list[index]);
}
},
onList: function(list) {
this.list = list;
this.renderList(list);
},
updateList: function() {
window.setTimeout(function() {
this.param.listProvider(this.getQuery(), this.xed, this.onList.bind(this));
}.bind(this), 0);
},
renderList: function(list)
{
var ol = this._getListContainer();
ol.innerHTML = "";
for(var i = 0; i < list.length; i++) {
var li = this.rdom.createElement('LI');
li.innerHTML = this.param.renderItem(list[i]);
ol.appendChild(li);
}
if(ol.hasChildNodes()) {
ol.firstChild.className = "selected";
}
},
show: function() {
if(!this.container) this.container = this._create();
var dialog = this.rdom.insertNodeAt(this.container, this.rdom.getRoot(), "end");
this.setPosition('centerOfEditor');
this.updateList();
this.focus();
},
close: function() {
this.rdom.deleteNode(this.container);
},
focus: function() {
this._getInputField().focus();
},
setPosition: function(target) {
var targetElement = null;
var left = 0;
var top = 0;
if(target === 'centerOfWindow') {
left += targetElement.scrollLeft;
top += targetElement.scrollTop;
targetElement = document.documentElement;
} else if(target === 'centerOfEditor') {
targetElement = this.xed.getCurrentEditMode() == 'wysiwyg' ? this.xed.wysiwygEditorDiv : this.xed.sourceEditorDiv;
var o = targetElement;
do {
left += o.offsetLeft;
top += o.offsetTop;
} while(o = o.offsetParent)
} else if(target === 'nearbyCaret') {
throw "Not implemented yet";
} else {
throw "Invalid argument: " + target;
}
var targetWidth = targetElement.clientWidth;
var targetHeight = targetElement.clientHeight;
var dialogWidth = this.container.clientWidth;
var dialogHeight = this.container.clientHeight;
left += parseInt((targetWidth - dialogWidth) / 2);
top += parseInt((targetHeight - dialogHeight) / 2);
this.container.style.left = left + "px";
this.container.style.top = top + "px";
},
matchCount: function() {
return this.list ? this.list.length : 0;
},
_create: function() {
// make container
var container = this.rdom.createElement("DIV");
container.className = "xqQuickSearch";
// make title
if(this.param.title) {
var title = this.rdom.createElement("H1");
title.innerHTML = this.param.title;
container.appendChild(title);
}
// make input field
var inputWrapper = this.rdom.createElement("DIV");
inputWrapper.className = "input";
var form = this.rdom.createElement("FORM");
var input = this.rdom.createElement("INPUT");
input.type = "text";
input.value = "";
form.appendChild(input);
inputWrapper.appendChild(form);
container.appendChild(inputWrapper);
// make list
var list = this.rdom.createElement("OL");
xq.observe(input, 'blur', this.onBlur.bindAsEventListener(this));
xq.observe(input, 'keypress', this.onKey.bindAsEventListener(this));
xq.observe(list, 'click', this.onClick.bindAsEventListener(this), true);
xq.observe(form, 'submit', this.onSubmit.bindAsEventListener(this));
xq.observe(form, 'reset', this.onCancel.bindAsEventListener(this));
container.appendChild(list);
return container;
},
_getInputField: function() {
return this.container.getElementsByTagName('INPUT')[0];
},
_getListContainer: function() {
return this.container.getElementsByTagName('OL')[0];
},
_getSelectedIndex: function() {
var ol = this._getListContainer();
for(var i = 0; i < ol.childNodes.length; i++) {
if(ol.childNodes[i].className === 'selected') return i;
}
},
_getIndexOfLI: function(li) {
var ol = this._getListContainer();
for(var i = 0; i < ol.childNodes.length; i++) {
if(ol.childNodes[i] === li) return i;
}
},
_moveSelectionUp: function() {
var count = this.matchCount();
if(count === 0) return;
var index = this._getSelectedIndex();
var ol = this._getListContainer();
ol.childNodes[index].className = "";
index--;
if(index < 0) index = count - 1;
ol.childNodes[index].className = "selected";
},
_moveSelectionDown: function() {
var count = this.matchCount();
if(count === 0) return;
var index = this._getSelectedIndex();
var ol = this._getListContainer();
ol.childNodes[index].className = "";
index++;
if(index >= count) index = 0;
ol.childNodes[index].className = "selected";
}
});