aolists-webtop
Version:
Web interface for aoLists
531 lines (508 loc) • 15.7 kB
JavaScript
/**
* @class aoVisualHolder
* @extends Ext.form.Field
*
* Creates a binary control
*
* @author Slocum at Ext - Modified byJose Gonzalez
* @copyright (c) 2014, by Candid.Concepts LC
* @version 1.0
*
* @license myDualControl is licensed under the terms of
* the Open Source LGPL 3.0 license. Commercial use is permitted to the extent
* that the code/component(s) do NOT become part of another Open Source or Commercially
* licensed development library or toolkit without explicit permission.
*
* <p>License details: <a href="http://www.gnu.org/licenses/lgpl.html"
* target="_blank">http://www.gnu.org/licenses/lgpl.html</a></p>
*
*/
Ext.ns('Ext.ux.form');
/**
* Creates new aoVisualHolder
* @constructor
* @param {Object} config A config object
*/
Ext.ux.form.aoVisualHolder = Ext.extend(Ext.form.Field, {
/**
* @cfg {String/Object} defaultAutoCreate DomHelper element spec
* Let superclass to create hidden field instead of textbox. Hidden will be submittend to server
*/
defaultAutoCreate: {
tag: 'input',
type: 'hidden'
},
/**
* @cfg {Number} secondaryWidth Width of secondary field in pixels (defaults to 8)
*/
secondaryWidth: 4,
/**
* @cfg {Number} separatorWidth Width of separator in pixels (defaults to 0)
*/
separatorWidth: 0,
/**
* @cfg {function} primaryBase Base for primary field (defaults to textfield).
*/
primaryBase: function (src) {
return new Ext.form.TextField(src);
},
/**
* @cfg {Object} primaryConfig Config for primary constructor.
*/
primaryConfig: {},
/**
* @cfg {string} primaryClickEvent Event for click event (default null for no event).
*/
primaryClickEvent: null,
/**
* @cfg {function} secondaryBase Base for secondary field (defaults to button).
*/
secondaryBase: function (src) {
return new Ext.Button(src);
},
/**
* @cfg {Object} secondaryConfig Config for secondary constructor.
*/
secondaryConfig: {},
/**
* @cfg {string} secondaryClickEvent Event for click event (default null for no event).
*/
secondaryClickEvent: null,
/**
* @private
* creates both fields and installs the necessary event handlers
*/
initComponent: function () {
// call parent initComponent
Ext.ux.form.aoVisualHolder.superclass.initComponent.call(this);
// create primary
var primaryXConfig = Ext.apply({
id: this.id + '-p',
width: this.Width - this.secondaryWidth,
selectOnFocus: this.selectOnFocus,
readOnly: this.readOnly,
listeners: {
blur: {
scope: this,
fn: this.onBlur
},
focus: {
scope: this,
fn: this.onFocus
},
click: {
scope: this,
fn: this.onPClick
}
}
}, this.primaryConfig);
this.df = this.primaryBase(primaryXConfig);
this.df.ownerCt = this;
// create secondary
var secondaryXConfig = Ext.apply({
id: this.id + '-s',
width: this.secondaryWidth,
selectOnFocus: this.selectOnFocus,
readOnly: this.readOnly,
listeners: {
blur: {
scope: this,
fn: this.onBlur
},
focus: {
scope: this,
fn: this.onFocus
},
click: {
scope: this,
fn: this.onSClick
}
}
}, this.secondaryConfig);
this.tf = this.secondaryBase(secondaryXConfig);
this.tf.ownerCt = this;
// relay events
this.relayEvents(this.df, ['focus', 'specialkey', 'invalid', 'valid']);
this.relayEvents(this.tf, ['focus', 'specialkey', 'invalid', 'valid']);
},
/**
* @private
* Renders underlying primary and secondary and provides a workaround for side error icon bug
*/
onRender: function (ct, position) {
if (!this.isRendered) {
// render underlying hidden field
Ext.ux.form.aoVisualHolder.superclass.onRender.call(this, ct, position);
this.df.tabIndex = this.tabIndex;
this.tf.tabIndex = this.tabIndex;
// render primary and secondary
// create bounding table
var t = Ext.DomHelper.append(ct, {
tag: 'table',
style: 'border-collapse:collapse',
children: [{
tag: 'tr',
children: [{
tag: 'td',
style: 'padding-right:' + this.separatorWidth.toString() + 'px',
cls: 'ux-primary'
}, {
tag: 'td',
cls: 'ux-secondary'
}]
}]
}, true);
this.tableEl = t;
this.wrap = t.wrap({
cls: 'x-form-field-wrap'
});
// this.wrap = t.wrap();
this.wrap.on("mousedown", this.onMouseDown, this, {
delay: 10
});
// render primary & secondary
this.df.render(t.child('td.ux-primary'));
this.tf.render(t.child('td.ux-secondary'));
// workaround for IE trigger misalignment bug
if (Ext.isIE && Ext.isStrict) {
t.select('input').applyStyles({
top: 0
});
}
this.on('specialkey', this.onSpecialKey, this);
this.df.el.swallowEvent(['keydown', 'keypress']);
this.tf.el.swallowEvent(['keydown', 'keypress']);
// setup name for submit
this.el.dom.name = this.hiddenName || this.name || this.id;
// prevent helper fields from being submitted
this.df.el.dom.removeAttribute("name");
this.tf.el.dom.removeAttribute("name");
// we're rendered flag
this.isRendered = true;
// update hidden field
this.updateValue();
this.fireEvent("render", this);
}
},
/**
* @private
*/
adjustSize: Ext.BoxComponent.prototype.adjustSize,
/**
* @private
*/
alignErrorIcon: function () {
this.errorIcon.alignTo(this.tableEl, 'tl-tr', [2, 0]);
},
/**
* Calls clearInvalid on the primary and secondary
*/
clearInvalid: function () {
if (this.df.clearInvalid) {
this.df.clearInvalid();
}
if (this.tf.clearInvalid) {
this.tf.clearInvalid();
}
},
/**
* Calls markInvalid on both primary and secondary
* @param {String} msg Invalid message to display
*/
markInvalid: function (msg) {
if (this.df.markInvalid) {
this.df.markInvalid(msg);
}
if (this.tf.markInvalid) {
this.tf.markInvalid(msg);
}
},
/**
* @private
* called from Component::destroy.
* Destroys all elements and removes all listeners we've created.
*/
beforeDestroy: function () {
if (this.isRendered) {
// this.removeAllListeners();
this.wrap.removeAllListeners();
this.wrap.remove();
this.tableEl.remove();
this.df.destroy();
this.tf.destroy();
}
},
/**
* Disable this component.
* @return {Ext.Component} this
*/
disable: function () {
if (this.isRendered) {
this.df.disabled = this.disabled;
this.df.onDisable();
this.tf.onDisable();
}
this.disabled = true;
this.df.disabled = true;
this.tf.disabled = true;
this.fireEvent("disable", this);
return this;
},
/**
* Enable this component.
* @return {Ext.Component} this
*/
enable: function () {
if (this.rendered) {
this.df.onEnable();
this.tf.onEnable();
}
this.disabled = false;
this.df.disabled = false;
this.tf.disabled = false;
this.fireEvent("enable", this);
return this;
},
/**
* @private Focus date filed
*/
focus: function () {
this.df.focus();
},
/**
* @private
*/
getPositionEl: function () {
return this.wrap;
},
// }}}
// {{{
/**
* @private
*/
getResizeEl: function () {
return this.wrap;
},
/**
* @return {Boolean} true = valid, false = invalid
* @private Calls isValid methods of underlying primary and secondary and returns the result
*/
isValid: function () {
return this.df.isValid() && this.tf.isValid();
},
/**
* Returns true if this component is visible
* @return {boolean}
*/
isVisible: function () {
return this.df.rendered && this.df.getActionEl().isVisible();
},
/**
* @private Handles blur event
*/
onBlur: function (f) {
// called by both primary and secondary blur events
// revert focus to previous field if clicked in between
if (this.wrapClick) {
f.focus();
this.wrapClick = false;
}
this.updateValue();
// fire events later
(function () {
if (!this.df.hasFocus && !this.tf.hasFocus) {
var v = this.getValue();
if (String(v) !== String(this.startValue)) {
if (this.rmtID) {
this.rmtID = null;
}
if (!this.handleChange || !this.handleChange()) {
this.fireEvent("change", this, v, this.startValue);
}
}
this.hasFocus = false;
this.fireEvent('blur', this);
}
}).defer(200, this);
},
/**
* @private Handles focus event
*/
onFocus: function () {
if (!this.hasFocus) {
this.hasFocus = true;
this.startValue = this.getValue();
this.fireEvent("focus", this);
}
},
/**
* @private Handles generic click event
*/
onClick: function (evt) {},
/**
* @private Handles primary click event
*/
onPClick: function () {
this.onClick(this.primaryClickEvent);
},
/**
* @private Handles secondary click event
*/
onSClick: function () {
if (!this.secondaryClickEvent) {
var custom = new Ext.Resizable(this.getEl().id, {
wrap: true,
pinned: true,
handles: 'all',
draggable: true,
dynamic: true
});
var customEl = custom.getEl();
// move to the body to prevent overlap on my blog
document.body.insertBefore(customEl.dom, document.body.firstChild);
customEl.on('dblclick', function () {
customEl.hide(true);
});
} else {
this.onClick(this.secondaryClickEvent);
}
},
/**
* @private Just to prevent blur event when clicked in the middle of fields
*/
onMouseDown: function (e) {
if (!this.disabled) {
this.wrapClick = 'td' === e.target.nodeName.toLowerCase();
}
},
/**
* @private
* Handles Tab and Shift-Tab events
*/
onSpecialKey: function (t, e) {
var key = e.getKey();
if (key === e.TAB) {
if (t === this.df && !e.shiftKey) {
e.stopEvent();
this.tf.focus();
}
if (t === this.tf && e.shiftKey) {
e.stopEvent();
this.df.focus();
}
}
// otherwise it misbehaves in editor grid
if (key === e.ENTER) {
this.updateValue();
}
},
/**
* @private
* Sets correct sizes of underlying primary and secondary
* With workarounds for IE bugs
*/
setSize: function (w, h) {
if (w) {
if (this.df.setSize) {
this.df.setSize(w - this.secondaryWidth - this.separatorWidth, h);
}
if (this.tf.setSize) {
this.tf.setSize(this.secondaryWidth, h);
}
if (Ext.isIE) {
this.df.el.up('td').setWidth(w - this.secondaryWidth - this.separatorWidth);
this.tf.el.up('td').setWidth(this.secondaryWidth);
}
}
},
/**
* Hide or show this component by boolean
* @return {Ext.Component} this
*/
setVisible: function (visible) {
if (visible) {
this.df.show();
this.tf.show();
} else {
this.df.hide();
this.tf.hide();
}
return this;
},
show: function () {
return this.setVisible(true);
},
hide: function () {
return this.setVisible(false);
},
/**
* @private Updates all of Date, Time and Hidden
*/
updateValue: function () {
if (this.isRendered) {
this.el.dom.value = this.getValue();
}
this.value = this.getValue();
},
/**
* @return {Boolean} true = valid, false = invalid
* calls validate methods of primary and secondary
*/
validate: function () {
return this.df.validate() && this.tf.validate();
},
/**
* Returns renderer suitable to render this field
* @param {Object} Column model config
*/
renderer: function (field) {
var renderer = function (val) {
return val;
};
return renderer;
},
/**
* @private Sets the value of primary
*/
setPrimary: function (name) {
this.df.setValue(name);
},
/**
* @private Gets the value of primary
*/
getPrimary: function () {
return this.df.getValue();
},
/**
* @private Sets the value of secondary
*/
setSecondary: function (yn) {
},
/**
* @private Gets the value of secondary
*/
getSecondary: function (yn) {
return false;
},
/**
* @param {String} val Value to set
* Sets the value of this field
*/
setValue: function (val) {
if (!val) {
this.setPrimary('');
this.setSecondary(false);
} else {
this.setPrimary(val);
this.setSecondary(false);
}
this.updateValue();
},
/**
* @return {String} Returns value of this field
*/
getValue: function () {
return this.getPrimary();
}
});
Ext.reg('visualholder', Ext.ux.form.aoVisualHolder);