Created
November 10, 2013 11:18
-
-
Save ssire/7396964 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* AXEL Plugin | |
* | |
* Sample input element transformed into an AXEL plugin (called "date" in this example) but this is a plain vanilla plugin | |
* | |
* The purpose is to have an example to brainstorm on AXEL plugin API and keyboard manager API | |
* | |
* Synopsis : | |
* - <xt:use types="date">default value</xt:use> | |
* | |
*/ | |
(function ($axel) { | |
var _DateField = { | |
//////////////////////// | |
// Life cycle methods // | |
//////////////////////// | |
onGenerate : function ( aContainer, aXTUse, aDocument ) { | |
var _handle = xtdom.createElement(aDocument, 'input'); | |
xtdom.setAttribute(_handle, 'type', 'text'); | |
if (this.getParam('noedit') === 'true') { | |
_handle.disabled = true; | |
} | |
aContainer.appendChild(_handle); | |
return _handle; | |
}, | |
onInit : function ( aDefaultData, anOptionAttr, aRepeater ) { | |
var h = this.getHandle(); | |
this.isEditable = !this.getParam('noedit'); | |
this.defaultData = aDefaultData || ''; | |
if (size = this.getParam('size')) { | |
xtdom.setAttribute(h, 'size', size); | |
} | |
h.value = this.defaultData; // FIXME: placeholder if HTML5 (?) | |
if (this.getParam('hasClass')) { | |
xtdom.addClassName(h, this.getParam('hasClass')); | |
} | |
}, | |
onAwake : function () { | |
var h = this.getHandle(); | |
var _this = this; | |
if (this.isEditable) { | |
xtdom.addEventListener(h, 'focus', | |
function(ev) { | |
if (!_this.isEditing()) { | |
_this.startEditing(ev); | |
} | |
xtdom.stopPropagation(ev); | |
xtdom.preventDefault(ev); | |
}, true); | |
xtdom.addEventListener(h, 'click', | |
function(ev) { | |
if (!_this.isEditing()) { | |
_this.startEditing(ev); | |
} | |
xtdom.stopPropagation(ev); | |
xtdom.preventDefault(ev); | |
}, true); | |
xtdom.addEventListener(h, 'mouseup', // needed on Safari to prevent unselection | |
function(ev) { | |
xtdom.stopPropagation(ev); | |
xtdom.preventDefault(ev); | |
}, true); | |
xtdom.addEventListener(h, 'blur', | |
function(ev) { | |
if (_this.isEditing()) { | |
_this.stopEditing(false, true); | |
} | |
}, true); | |
} | |
}, | |
onLoad : function (aPoint, aDataSrc) { | |
var value, fallback; | |
if (aPoint !== -1) { | |
value = aDataSrc.getDataFor(aPoint); | |
fallback = this.getDefaultData(); | |
this.getHandle().value = value || fallback || ''; | |
this.setModified(value !== fallback); | |
this.set(false); | |
} else { | |
this.clear(false); | |
} | |
}, | |
onSave : function (aLogger) { | |
var value; | |
if (this.isOptional() && !this.isSet()) { | |
aLogger.discardNodeIfEmpty(); | |
} else { | |
value = this.getHandle().value; | |
if (value) { | |
aLogger.write(value); | |
} | |
} | |
}, | |
//////////////////////////////// | |
// Overwritten plugin methods // | |
//////////////////////////////// | |
api : { | |
getData : function ( ) { | |
return this.getHandle().value; | |
}, | |
isFocusable : function () { | |
return (this.isEditable && ((!this.isOptional()) || this.isSet())); | |
}, | |
// AXEL keyboard API (called from Keyboard manager instance) | |
isEditing : function () { | |
return this._isEditing; | |
}, | |
// AXEL keyboard API (called from Keyboard manager instance) | |
doKeyDown : function (ev) { | |
}, | |
// AXEL keyboard API (called from Keyboard manager instance) | |
doKeyUp : function (ev) { | |
}, | |
// AXEL tab group manager API | |
// Gives the focus to *this* instance. Called by the tab navigation manager. | |
focus : function () { | |
this.getHandle().focus(); | |
this.startEditing(); | |
}, | |
// AXEL tab group manager API | |
// Takes the focus away from *this* instance. Called by the tab navigation manager. | |
unfocus : function () { | |
this.stopEditing(); | |
} | |
}, | |
///////////////////////////// | |
// Specific plugin methods // | |
///////////////////////////// | |
methods : { | |
// Starts an edition process on *this* instance's device. | |
startEditing : function (aEvent) { | |
var h, kbd = xtiger.session(this.getDocument()).load('keyboard'); | |
if (! this._isEditing) { | |
h = this.getHandle(); | |
this._legacy = h.value; | |
this._isEditing = true; | |
// registers to keyboard events | |
this.kbdHandlers = kbd.register(this, h); | |
kbd.grab(this, this); | |
if (!this.isModified()) { | |
xtdom.focusAndSelect(h); | |
} | |
} | |
}, | |
// Stops the ongoing edition process | |
stopEditing : function (isCancel, isBlur) { | |
var h = this.getHandle(); | |
var kbd = xtiger.session(this.getDocument()).load('keyboard'); | |
if (this._isEditing) { | |
this._isEditing = false; // do it first to prevent any potential blur handle callback | |
kbd.unregister(this, this.kbdHandlers, h); | |
kbd.release(this, this); | |
if (!isCancel) { | |
this.update(h.value); | |
} | |
if ((! isBlur) && (h.blur)) { | |
h.blur(); | |
} | |
} | |
}, | |
// Called by Keyboard manager (Esc key) | |
cancelEditing : function () { | |
this.getHandle().value = this._legacy; | |
this.stopEditing(); | |
}, | |
// Updates this model with the given data. | |
// If this instance is optional and "unset", autocheck it. | |
update : function (aData) { | |
// 1. no change | |
if (aData === this._legacy) { | |
return; | |
} | |
// 2. normalizes text (empty text is set to _defaultData) | |
if (aData.search(/\S/) === -1 || (aData === this._defaultData)) { | |
this.clear(true); | |
} else { | |
// 3. notifies data was updated | |
this.setModified(aData !== this.defaultData); | |
this.set(true); | |
} | |
}, | |
// Clears the model and sets its data to the default data. | |
// Unsets it if it is optional and propagates the new state if asked to. | |
clear : function (doPropagate) { | |
this.getHandle().value = this.defaultData; | |
this.setModified(false); | |
if (this.isOptional() && this.isSet()) { | |
this.unset(doPropagate); | |
} | |
}, | |
// Overwrite 'optional' mixin method | |
set : function(doPropagate) { | |
// propagates state change in case some repeat ancestors are unset at that moment | |
if (doPropagate) { | |
if (!this.getParam('noedit')) { | |
xtiger.editor.Repeat.autoSelectRepeatIter(this.getHandle()); | |
} | |
xtdom.removeClassName(this._handle, 'axel-repeat-unset'); | |
// fix if *this* model is "placed" and the handle is outside the DOM at the moment | |
} | |
if (! this._isOptionSet) { | |
this._isOptionSet = true; | |
if (this._isOptional) { | |
this._handle.disabled = false; | |
this._optCheckBox.checked = true; | |
} | |
} | |
}, | |
// Overwrite 'optional' mixin method | |
unset : function (doPropagate) { | |
if (this._isOptionSet) { | |
this._isOptionSet = false; | |
if (this._isOptional) { | |
this._handle.disabled = true; | |
this._optCheckBox.checked = false; | |
} | |
} | |
} | |
} | |
}; | |
$axel.plugin.register( | |
'date', | |
{ filterable: true, optional: true }, | |
{ | |
// checked : 'false' | |
}, | |
_DateField | |
); | |
}($axel)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment