Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Gallery Build Tag: gallery-2011.06.15-19-18

  • Loading branch information...
commit 53301484d0f7fea238f4cbb44393753ee318a693 1 parent 796eed0
YUI Builder authored
View
418 build/gallery-form/gallery-form-debug.js
@@ -248,6 +248,7 @@ Y.Form = Y.Base.create('form', Y.Widget, [Y.WidgetParent], {
var formAction = this.get('action'),
formMethod = this.get('method'),
submitViaIO = this.get('submitViaIO'),
+ io = this.get("io"),
transaction,
cfg;
@@ -260,7 +261,6 @@ Y.Form = Y.Base.create('form', Y.Widget, [Y.WidgetParent], {
}
};
- var io = this.get("io");
transaction = io(formAction, cfg);
this._ioIds[transaction.id] = transaction;
} else {
@@ -523,6 +523,68 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
toString: function() {
return this.name;
},
+
+ /**
+ * @property FormField.FIELD_TEMPLATE
+ * @type String
+ * @description Template used to render the field node
+ */
+ FIELD_TEMPLATE : '<input></input>',
+
+ /**
+ * @property FormField.FIELD_CLASS
+ * @type String
+ * @description CSS class used to locate a placeholder for
+ * the field node and style it.
+ */
+ FIELD_CLASS : 'field',
+
+ /**
+ * @property FormField.LABEL_TEMPLATE
+ * @type String
+ * @description Template used to draw a label node
+ */
+ LABEL_TEMPLATE : '<label></label>',
+
+ /**
+ * @property FormField.LABEL_CLASS
+ * @type String
+ * @description CSS class used to locate a placeholder for
+ * the label node and style it.
+ */
+ LABEL_CLASS : 'label',
+
+ /**
+ * @property FormField.HINT_TEMPLATE
+ * @type String
+ * @description Optionally a template used to draw a hint node. Derived
+ * classes can use it to provide additional information about the field
+ */
+ HINT_TEMPLATE : '',
+
+ /**
+ * @property FormField.HINT_CLASS
+ * @type String
+ * @description CSS class used to locate a placeholder for
+ * the hint node and style it.
+ */
+ HINT_CLASS : 'hint',
+
+ /**
+ * @property FormField.ERROR_TEMPLATE
+ * @type String
+ * @description Template used to draw an error node
+ */
+ ERROR_TEMPLATE : '<span></span>',
+
+ /**
+ * @property FormField.ERROR_CLASS
+ * @type String
+ * @description CSS class used to locate a placeholder for
+ * the error node and style it.
+ */
+ ERROR_CLASS : 'error',
+
/**
* @property _labelNode
* @protected
@@ -531,6 +593,14 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
*/
_labelNode: null,
+ /**
+ * @property _hintNode
+ * @protected
+ * @type Object
+ * @description The hint node with extra text describing the field
+ */
+ _hintNode : null,
+
/**
* @property _fieldNode
* @protected
@@ -618,6 +688,35 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
},
/**
+ * @method _renderNode
+ * @protected
+ * @description Helper method to render new nodes, possibly replacing
+ * markup placeholders.
+ */
+ _renderNode : function (nodeTemplate, nodeClass, nodeBefore) {
+ if (!nodeTemplate) {
+ return null;
+ }
+ var contentBox = this.get('contentBox'),
+ node = Y.Node.create(nodeTemplate),
+ placeHolder = contentBox.one('.' + nodeClass);
+
+ node.addClass(nodeClass);
+
+ if (placeHolder) {
+ placeHolder.replace(node);
+ } else {
+ if (nodeBefore) {
+ contentBox.insertBefore(node, nodeBefore);
+ } else {
+ contentBox.appendChild(node);
+ }
+ }
+
+ return node;
+ },
+
+ /**
* @method _renderLabelNode
* @protected
* @description Draws the form field's label node into the contentBox
@@ -627,14 +726,25 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
labelNode = contentBox.one('label');
if (!labelNode || labelNode.get('for') != this.get('id')) {
- labelNode = Y.Node.create(Y.FormField.LABEL_TEMPLATE);
- contentBox.appendChild(labelNode);
+ labelNode = this._renderNode(this.LABEL_TEMPLATE, this.LABEL_CLASS);
}
this._labelNode = labelNode;
},
/**
+ * @method _renderHintNode
+ * @protected
+ * @description Draws the hint node into the contentBox. If a node is
+ * found in the contentBox with class HINT_CLASS, it will be
+ * considered a markup placeholder and replaced with the hint node.
+ */
+ _renderHintNode : function () {
+ this._hintNode = this._renderNode(this.HINT_TEMPLATE,
+ this.HINT_CLASS);
+ },
+
+ /**
* @method _renderFieldNode
* @protected
* @description Draws the field node into the contentBox
@@ -644,8 +754,7 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
field = contentBox.one('#' + this.get('id'));
if (!field) {
- field = Y.Node.create(Y.FormField.INPUT_TEMPLATE);
- contentBox.appendChild(field);
+ field = this._renderNode(this.FIELD_TEMPLATE, this.FIELD_CLASS);
}
this._fieldNode = field;
@@ -657,16 +766,35 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
* @description Syncs the the label node and this instances attributes
*/
_syncLabelNode: function() {
+ var label = this.get('label'),
+ required = this.get('required'),
+ requiredLabel = this.get('requiredLabel');
if (this._labelNode) {
- this._labelNode.setAttrs({
- innerHTML: this.get('label')
- });
+ this._labelNode.set("text", "");
+ if (label) {
+ this._labelNode.append("<span class='caption'>" + label + "</span>");
+ }
+ if (required && requiredLabel) {
+ this._labelNode.append("<span class='separator'> </span>");
+ this._labelNode.append("<span class='required'>" + requiredLabel + "</span>");
+ }
this._labelNode.setAttribute('for', this.get('id') + Y.FormField.FIELD_ID_SUFFIX);
}
},
/**
- * @method _syncLabelNode
+ * @method _syncHintNode
+ * @protected
+ * @description Syncs the hintNode
+ */
+ _syncHintNode : function () {
+ if (this._hintNode) {
+ this._hintNode.set("text", this.get("hint"));
+ }
+ },
+
+ /**
+ * @method _syncFieldNode
* @protected
* @description Syncs the fieldNode and this instances attributes
*/
@@ -728,12 +856,9 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
* @description Adds an error node with the supplied message
*/
_showError: function(errMsg) {
- var contentBox = this.get('contentBox'),
- errorNode = Y.Node.create('<span>' + errMsg + '</span>');
-
- errorNode.addClass('error');
- contentBox.insertBefore(errorNode, this._labelNode);
+ var errorNode = this._renderNode(this.ERROR_TEMPLATE, this.ERROR_CLASS, this._labelNode);
+ errorNode.set("text", errMsg);
this._errorNode = errorNode;
},
@@ -744,8 +869,7 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
*/
_clearError: function() {
if (this._errorNode) {
- var contentBox = this.get('contentBox');
- contentBox.removeChild(this._errorNode);
+ this._errorNode.remove();
this._errorNode = null;
}
},
@@ -817,6 +941,7 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
renderUI: function() {
this._renderLabelNode();
this._renderFieldNode();
+ this._renderHintNode();
},
bindUI: function() {
@@ -873,6 +998,7 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
syncUI: function() {
this.get('boundingBox').removeAttribute('tabindex');
this._syncLabelNode();
+ this._syncHintNode();
this._syncFieldNode();
this._syncError();
this._syncDisabled();
@@ -938,6 +1064,17 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
},
/**
+ * @attribute hint
+ * @type String
+ * @default ""
+ * @description Extra text explaining what the field is about.
+ */
+ hint : {
+ value : '',
+ validator : Y.Lang.isString
+ },
+
+ /**
* @attribute validator
* @type Function
* @default "function () { return true; }"
@@ -988,6 +1125,17 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
validateInline: {
value: false,
validator: Y.Lang.isBoolean
+ },
+
+ /**
+ * @attribute requiredLabel
+ * @type String
+ * @description Text to append to the labal caption for a required
+ * field, by default nothing will be appended.
+ */
+ requiredLabel : {
+ value : '',
+ validator : Y.Lang.isString
}
},
@@ -1173,20 +1321,6 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
INVALID_SPECIAL_CHARS: "Please use only letters and numbers",
/**
- * @property FormField.INPUT_TEMPLATE
- * @type String
- * @description Template used to draw an input node
- */
- INPUT_TEMPLATE: '<input />',
-
- /**
- * @property FormField.LABEL_TEMPLATE
- * @type String
- * @description Template used to draw a label node
- */
- LABEL_TEMPLATE: '<label></label>',
-
- /**
* @property FormField.REQUIRED_ERROR_TEXT
* @type String
* @description Error text to display for a required field
@@ -1339,31 +1473,9 @@ Y.HiddenField = Y.Base.create('hidden-field', Y.FormField, [Y.WidgetChild], {
* @description A hidden field node
*/
Y.TextareaField = Y.Base.create('textarea-field', Y.FormField, [Y.WidgetChild], {
- _renderFieldNode : function () {
- var contentBox = this.get('contentBox'),
- field = contentBox.one('#' + this.get('id'));
-
- if (!field) {
- field = Y.Node.create(Y.TextareaField.NODE_TEMPLATE);
- field.setAttrs({
- name : this.get('name'),
- innerHTML : this.get('value')
- });
- contentBox.appendChild(field);
- }
- field.setAttribute('tabindex', Y.FormField.tabIndex);
- Y.FormField.tabIndex++;
-
- this._fieldNode = field;
- }
-}, {
- /**
- * @property TextareaField.NODE_TEMPLATE
- * @type String
- * @description Template used to draw a textarea node
- */
- NODE_TEMPLATE : '<textarea></textarea>'
+ FIELD_TEMPLATE : '<textarea></textarea>'
+
});
/**
* @class ChoiceField
@@ -1374,6 +1486,11 @@ Y.TextareaField = Y.Base.create('textarea-field', Y.FormField, [Y.WidgetChild],
* selection of choices
*/
Y.ChoiceField = Y.Base.create('choice-field', Y.FormField, [Y.WidgetParent, Y.WidgetChild], {
+
+ LABEL_TEMPLATE: '<span></span>',
+ SINGLE_CHOICE: Y.RadioField,
+ MULTI_CHOICE: Y.CheckboxField,
+
/**
* @method _validateChoices
* @protected
@@ -1412,22 +1529,16 @@ Y.ChoiceField = Y.Base.create('choice-field', Y.FormField, [Y.WidgetParent, Y.Wi
return true;
},
- _renderLabelNode: function() {
- var contentBox = this.get('contentBox'),
- titleNode = Y.Node.create('<span></span>');
-
- titleNode.set('innerHTML', this.get('label'));
- contentBox.appendChild(titleNode);
-
- this._labelNode = titleNode;
- },
-
_renderFieldNode: function() {
var contentBox = this.get('contentBox'),
- choices = this.get('choices'),
- multiple = this.get('multi'),
- fieldType = (multiple === true ? Y.CheckboxField: Y.RadioField);
+ parent = contentBox.one("." + this.FIELD_CLASS),
+ choices = this.get('choices'),
+ multiple = this.get('multi'),
+ fieldType = (multiple === true ? this.MULTI_CHOICE: this.SINGLE_CHOICE);
+ if (!parent) {
+ parent = contentBox;
+ }
Y.Array.each(choices,
function(c, i, a) {
var cfg = {
@@ -1438,9 +1549,9 @@ Y.ChoiceField = Y.Base.create('choice-field', Y.FormField, [Y.WidgetParent, Y.Wi
},
field = new fieldType(cfg);
- field.render(contentBox);
+ field.render(parent);
}, this);
- this._fieldNode = contentBox.all('input');
+ this._fieldNode = parent.all('input');
},
_syncFieldNode: function() {
@@ -1458,6 +1569,17 @@ Y.ChoiceField = Y.Base.create('choice-field', Y.FormField, [Y.WidgetParent, Y.Wi
}
},
+ /**
+ * @method _afterChoiceChange
+ * @description When the available choices for the choice field change,
+ * the old ones are removed and the new ones are rendered.
+ */
+ _afterChoicesChange: function(event) {
+ var contentBox = this.get("contentBox");
+ contentBox.all(".yui3-form-field").remove();
+ this._renderFieldNode();
+ },
+
clear: function() {
this._fieldNode.each(function(node, index, list) {
node.set('checked', false);
@@ -1481,6 +1603,7 @@ Y.ChoiceField = Y.Base.create('choice-field', Y.FormField, [Y.WidgetParent, Y.Wi
this.set('value', value);
},
this));
+ this.after('choicesChange', this._afterChoicesChange);
}
},
@@ -1517,22 +1640,23 @@ Y.ChoiceField = Y.Base.create('choice-field', Y.FormField, [Y.WidgetParent, Y.Wi
* @description A select field node
*/
Y.SelectField = Y.Base.create('select-field', Y.ChoiceField, [Y.WidgetParent, Y.WidgetChild], {
+
+ FIELD_TEMPLATE : '<select></select>',
+
+ /**
+ * @property SelectField.DEFAULT_OPTION_TEXT
+ * @type String
+ * @description The display title of the default choice in the select box
+ */
+ DEFAULT_OPTION_TEXT : 'Choose one',
+
/**
* @method _renderFieldNode
* @protected
* @description Draws the select node into the contentBox
*/
_renderFieldNode: function() {
- var contentBox = this.get('contentBox'),
- field = contentBox.one('#' + this.get('id'));
-
- if (!field) {
- field = Y.Node.create(Y.SelectField.NODE_TEMPLATE);
- contentBox.appendChild(field);
- }
-
- this._fieldNode = field;
-
+ Y.SelectField.superclass.constructor.superclass._renderFieldNode.apply(this, arguments);
this._renderOptionNodes();
},
@@ -1568,6 +1692,7 @@ Y.SelectField = Y.Base.create('select-field', Y.ChoiceField, [Y.WidgetParent, Y.
Y.SelectField.superclass.constructor.superclass._syncFieldNode.apply(this, arguments);
this._fieldNode.setAttrs({
+ size : this.get('size'),
multiple: (this.get('multi') === true ? 'multiple': '')
});
},
@@ -1586,7 +1711,7 @@ Y.SelectField = Y.Base.create('select-field', Y.ChoiceField, [Y.WidgetParent, Y.
if (useDefaultOption === true) {
choices.unshift({
- label: Y.SelectField.DEFAULT_OPTION_TEXT,
+ label : this.DEFAULT_OPTION_TEXT,
value: ''
});
}
@@ -1611,6 +1736,18 @@ Y.SelectField = Y.Base.create('select-field', Y.ChoiceField, [Y.WidgetParent, Y.
},
/**
+ * @method _afterChoiceChange
+ * @description When the available options for the select field change,
+ * the old ones are removed and the new ones are rendered.
+ */
+ _afterChoicesChange: function(evt) {
+ var options = this._fieldNode.all("option");
+ options.remove();
+ this._renderOptionNodes();
+ this._syncOptionNodes();
+ },
+
+ /**
* @method clear
* @description Restores the selected option to the default
*/
@@ -1620,6 +1757,7 @@ Y.SelectField = Y.Base.create('select-field', Y.ChoiceField, [Y.WidgetParent, Y.
bindUI: function() {
Y.SelectField.superclass.constructor.superclass.bindUI.apply(this, arguments);
+ this.after('choicesChange', this._afterChoicesChange);
},
syncUI: function() {
@@ -1629,26 +1767,12 @@ Y.SelectField = Y.Base.create('select-field', Y.ChoiceField, [Y.WidgetParent, Y.
},
{
/**
- * @property SelectField.NODE_TEMPLATE
- * @type String
- * @description Template used to draw a select node
- */
- NODE_TEMPLATE: '<select></select>',
-
- /**
* @property SelectField.OPTION_TEMPLATE
* @type String
* @description Template used to draw an option node
*/
OPTION_TEMPLATE: '<option></option>',
- /**
- * @property SelectField.DEFAULT_OPTION_TEXT
- * @type String
- * @description The display title of the default choice in the select box
- */
- DEFAULT_OPTION_TEXT: 'Choose one',
-
ATTRS: {
/**
* @attribute useDefaultOption
@@ -1660,19 +1784,42 @@ Y.SelectField = Y.Base.create('select-field', Y.ChoiceField, [Y.WidgetParent, Y.
useDefaultOption: {
validator: Y.Lang.isBoolean,
value: true
+ },
+
+ /**
+ * @attribute choices
+ * @type Array
+ * @description The choices to render into this field
+ */
+ choices: {
+ validator: function(val) {
+ if (this.get("useDefaultOption") &&
+ Y.Lang.isArray(val) &&
+ val.length === 0) {
+ // Empty arrays are okay if useDefaultOption is 'true'
+ return true;
+ } else {
+ return this._validateChoices(val);
+ }
+ }
+ },
+
+ /**
+ * @attribute size
+ * @type String
+ * @default 0
+ * @description Value of 'size' attribute of the select element.
+ */
+ size : {
+ validator : Y.Lang.isString,
+ value : '0'
}
}
});
Y.FormButton = Y.Base.create('button-field', Y.FormField, [Y.WidgetChild], {
- _renderButtonNode : function () {
- var contentBox = this.get('contentBox'), bn;
-
- bn = Y.Node.create(Y.FormButton.NODE_TEMPLATE);
- contentBox.appendChild(bn);
- this._fieldNode = bn;
- },
- _syncLabelNode: function () {},
+ FIELD_TEMPLATE : '<button></button>',
+ LABEL_TEMPLATE: '',
_syncFieldNode : function () {
this._fieldNode.setAttrs({
@@ -1688,17 +1835,26 @@ Y.FormButton = Y.Base.create('button-field', Y.FormField, [Y.WidgetChild], {
return;
}
- var oc = this.get('onclick');
Y.Event.purgeElement(this._fieldNode, true, 'click');
- Y.on('click', Y.bind(oc.fn, oc.scope, true), this._fieldNode);
+ Y.on('click', Y.bind(this._promptConfirm, this), this._fieldNode);
},
- renderUI : function () {
- this._renderButtonNode();
+ _promptConfirm: function(event) {
+ event.preventDefault();
+ var message = this.get("message"),
+ onclick = this.get("onclick");
+
+ if (message) {
+ if (!this.get("confirm")(message)) {
+ return;
+ }
+ }
+ onclick.fn.apply(onclick.scope);
},
bindUI : function () {
this.after('onclickChange', Y.bind(this._setClickHandler, this, true));
+ this.after('disabledChange', this._syncDisabled, this);
this._setClickHandler();
}
}, {
@@ -1724,10 +1880,34 @@ Y.FormButton = Y.Base.create('button-field', Y.FormField, [Y.WidgetChild], {
val.argument = val.argument || {};
return val;
}
- }
- },
+ },
+
+ /**
+ * @attribute message
+ * @type String
+ * @default null
+ * @description Optional confirmation message to be passed to the
+ * confirm function.
+ */
+ message: {
+ validator : Y.Lang.isString,
+ value: null
+ },
- NODE_TEMPLATE : '<button></button>'
+ /**
+ * @attribute confirm
+ * @type Function
+ * @default null
+ * @description Optional confirmation function called when the button
+ * is clicked. It will be be passed the string set in the 'message'
+ * attribute. If it returns 'true' the the onclick handler will be
+ * called, otherwise it will be skipped.
+ */
+ confirm: {
+ validator : Y.Lang.isFunction,
+ value: null
+ }
+ }
});
/**
* @class FileField
@@ -1737,21 +1917,7 @@ Y.FormButton = Y.Base.create('button-field', Y.FormField, [Y.WidgetChild], {
* @description A file field node
*/
-Y.FileField = Y.Base.create('file-field', Y.FormField, [Y.WidgetChild], {
- _renderFieldNode : function () {
- var contentBox = this.get('contentBox'),
- field = contentBox.one('#' + this.get('id'));
-
- if (!field) {
- field = Y.Node.create(Y.FileField.FILE_INPUT_TEMPLATE);
- contentBox.appendChild(field);
- }
-
- this._fieldNode = field;
- }
-}, {
- FILE_INPUT_TEMPLATE : '<input type="file" />'
-});
+Y.FileField = Y.Base.create('file-field', Y.FormField, [Y.WidgetChild]);
/**
* @class SubmitButton
* @extends FormField
@@ -1770,8 +1936,8 @@ Y.SubmitButton = Y.Base.create('submit-button', Y.FormField, [Y.WidgetChild], {
* @description A reset button
*/
Y.ResetButton = Y.Base.create('reset-button', Y.FormField, [Y.WidgetChild], {
- _renderLabelNode: function() {}
+ LABEL_TEMPLATE: ''
});
-}, 'gallery-2011.02.23-19-01' ,{requires:['node', 'widget-base', 'widget-htmlparser', 'io-form', 'widget-parent', 'widget-child', 'base-build', 'substitute', 'io-upload-iframe']});
+}, 'gallery-2011.06.15-19-18' ,{requires:['node', 'widget-base', 'widget-htmlparser', 'io-form', 'widget-parent', 'widget-child', 'base-build', 'substitute', 'io-upload-iframe']});
View
8 build/gallery-form/gallery-form-min.js
@@ -1,4 +1,4 @@
-YUI.add("gallery-form",function(a){a.Form=a.Base.create("form",a.Widget,[a.WidgetParent],{toString:function(){return this.name;},CONTENT_TEMPLATE:"<form></form>",_ioIds:null,_validateMethod:function(b){if(!a.Lang.isString(b)){return false;}if(b.toLowerCase()!="get"&&b.toLowerCase()!="post"){return false;}return true;},_parseAction:function(b){var c=b.one("form");if(!c){c=b;}if(c){return c.get("action");}},_parseMethod:function(b){var c=b.one("form");if(!c){c=b;}if(c){return c.get("method");}},_parseFields:function(c){var e=c.all("*"),f=c.all("label"),b=[],d={text:a.TextField,hidden:a.HiddenField,file:a.FileField,checkbox:a.CheckboxField,radio:a.RadioField,reset:a.ResetButton,submit:a.SubmitButton,button:(a.Button||a.FormButton)};e.each(function(j,h,g){var n=j.get("nodeName"),l=j.get("id"),i,k,m=[];if(n=="INPUT"){i=j.get("type");k={type:(d[i]?d[i]:a.TextField),name:j.get("name"),value:j.get("value"),checked:j.get("checked")};if(k.type==d.button){k.label=j.get("value");}}else{if(n=="BUTTON"){k={type:d.button,name:j.get("name"),label:j.get("innerHTML")};}else{if(n=="SELECT"){j.all("option").each(function(p,q,o){m.push({label:p.get("innerHTML"),value:p.get("value")});});k={type:a.SelectField,name:j.get("name"),choices:m};}else{if(n=="TEXTAREA"){k={type:a.TextareaField,name:j.get("name"),value:j.get("innerHTML")};}}}}if(k){if(l){k.id=l;f.some(function(p,q,o){if(p.get("htmlFor")==l){k.label=p.get("innerHTML");}});}b.push(k);}j.remove();});return b;},_syncFormAttributes:function(){var b=this.get("contentBox");b.setAttrs({action:this.get("action"),method:this.get("method")});if(this.get("encodingType")===a.Form.MULTIPART_ENCODED){b.setAttribute("enctype","multipart/form-data");}},_runValidation:function(){var b=true;this.each(function(c){if(c.validateField()===false){b=false;}});return b;},_enableInlineValidation:function(){this.each(function(b){b.set("validateInline",true);});},_disableInlineValidation:function(){this.each(function(b){b.set("validateInline",false);});},_handleIOEvent:function(d,b,c){if(this._ioIds[b]!==undefined){this.fire(d,{response:c});}},reset:function(){var b=a.Node.getDOMNode(this.get("contentBox"));if(a.Lang.isFunction(b.reset)){b.reset();}this.each(function(c){c.resetFieldNode();c.set("error",null);});},submit:function(){if(this.get("skipValidationBeforeSubmit")===true||this._runValidation()){var c=this.get("action"),e=this.get("method"),d=this.get("submitViaIO"),f,b;if(d===true){b={method:e,form:{id:this.get("contentBox"),upload:(this.get("encodingType")===a.Form.MULTIPART_ENCODED)}};var g=this.get("io");f=g(c,b);this._ioIds[f.id]=f;}else{this.get("contentBox").submit();}}},getField:function(b){var c;if(a.Lang.isNumber(b)){c=this.item(b);}else{if(a.Lang.isString(b)){this.each(function(d){if(d.get("name")==b){c=d;}});}}return c;},initializer:function(b){this._ioIds={};this.publish("submit");this.publish("reset");this.publish("start");this.publish("success");this.publish("failure");this.publish("complete");this.publish("xdr");},destructor:function(){},renderUI:function(){},bindUI:function(){this.get("contentBox").on("submit",a.bind(function(b){b.halt();},this));this.after("inlineValidationChange",a.bind(function(b){if(b.newVal===true){this._enableInlineValidation();}else{this._disableInlineValidation();}},this));this.after("success",a.bind(function(b){if(this.get("resetAfterSubmit")===true){this.reset();}},this));a.on("io:start",a.bind(this._handleIOEvent,this,"start"));a.on("io:complete",a.bind(this._handleIOEvent,this,"complete"));a.on("io:xdr",a.bind(this._handleIOEvent,this,"xdr"));a.on("io:success",a.bind(this._handleIOEvent,this,"success"));a.on("io:failure",a.bind(this._handleIOEvent,this,"failure"));this.each(a.bind(function(b){if(b.name=="submit-button"){b.on("click",a.bind(this.submit,this));}else{if(b.name=="reset-button"){b.on("click",a.bind(this.reset,this));}}},this));},syncUI:function(){this._syncFormAttributes();if(this.get("inlineValidation")===true){this._enableInlineValidation();}}},{ATTRS:{defaultChildType:{valueFn:function(){return a.TextField;}},method:{value:"post",validator:function(b){return this._validateMethod(b);},setter:function(b){return b.toLowerCase();}},action:{value:".",validator:a.Lang.isString},fields:{setter:function(b){return this.set("children",b);}},inlineValidation:{value:false,validator:a.Lang.isBoolean},resetAfterSubmit:{value:true,validator:a.Lang.isBoolean},encodingType:{value:1,validator:a.Lang.isNumber},skipValidationBeforeSubmit:{value:false,validator:a.Lang.isBoolean},submitViaIO:{value:true,validator:a.Lang.isBoolean},io:{value:a.io}},HTML_PARSER:{action:function(b){return this._parseAction(b);},method:function(b){return this._parseMethod(b);},children:function(b){return this._parseFields(b);}},FORM_TEMPLATE:"<form></form>",URL_ENCODED:1,MULTIPART_ENCODED:2});a.FormField=a.Base.create("form-field",a.Widget,[a.WidgetParent,a.WidgetChild],{toString:function(){return this.name;},_labelNode:null,_fieldNode:null,_errorNode:null,_initialValue:null,_validateError:function(b){if(a.Lang.isString(b)){return true;}if(b===null||typeof b=="undefined"){return true;}return false;},_validateValidator:function(c){if(a.Lang.isString(c)){var b=/^(email|phone|ip|date|time|postal|special)$/;if(b.test(c)===true){return true;}}if(a.Lang.isFunction(c)){return true;}return false;},_setValidator:function(c){var b={email:a.FormField.VALIDATE_EMAIL_ADDRESS,phone:a.FormField.VALIDATE_PHONE_NUMBER,ip:a.FormField.VALIDATE_IP_ADDRESS,date:a.FormField.VALIDATE_DATE,time:a.FormField.VALIDATE_TIME,postal:a.FormField.VALIDATE_POSTAL_CODE,special:a.FormField.VALIDATE_NO_SPECIAL_CHARS};return(b[c]?b[c]:c);},_renderLabelNode:function(){var b=this.get("contentBox"),c=b.one("label");if(!c||c.get("for")!=this.get("id")){c=a.Node.create(a.FormField.LABEL_TEMPLATE);b.appendChild(c);}this._labelNode=c;},_renderFieldNode:function(){var b=this.get("contentBox"),c=b.one("#"+this.get("id"));if(!c){c=a.Node.create(a.FormField.INPUT_TEMPLATE);b.appendChild(c);}this._fieldNode=c;
-},_syncLabelNode:function(){if(this._labelNode){this._labelNode.setAttrs({innerHTML:this.get("label")});this._labelNode.setAttribute("for",this.get("id")+a.FormField.FIELD_ID_SUFFIX);}},_syncFieldNode:function(){var b=this.name.split("-")[0];if(!b){return;}this._fieldNode.setAttrs({name:this.get("name"),type:b,id:this.get("id")+a.FormField.FIELD_ID_SUFFIX,value:this.get("value")});this._fieldNode.setAttribute("tabindex",a.FormField.tabIndex);a.FormField.tabIndex++;},_syncError:function(){var b=this.get("error");if(b){this._showError(b);}},_syncDisabled:function(c){var b=this.get("disabled");if(b===true){this._fieldNode.setAttribute("disabled","disabled");}else{this._fieldNode.removeAttribute("disabled");}},_checkRequired:function(){if(this.get("required")===true&&this.get("value").length===0){return false;}return true;},_showError:function(c){var b=this.get("contentBox"),d=a.Node.create("<span>"+c+"</span>");d.addClass("error");b.insertBefore(d,this._labelNode);this._errorNode=d;},_clearError:function(){if(this._errorNode){var b=this.get("contentBox");b.removeChild(this._errorNode);this._errorNode=null;}},_enableInlineValidation:function(){this.after("valueChange",this.validateField,this);},_disableInlineValidation:function(){this.detach("valueChange",this.validateField,this);},validateField:function(d){var c=this.get("value"),b=this.get("validator");this.set("error",null);if(d&&d.src!="ui"){return false;}if(!this._checkRequired()){this.set("error",a.FormField.REQUIRED_ERROR_TEXT);return false;}else{if(!c){return true;}}return b.call(this,c,this);},resetFieldNode:function(){this.set("value",this._initialValue);this._fieldNode.set("value",this._initialValue);this.fire("nodeReset");},clear:function(){this.set("value","");this._fieldNode.set("value","");this._initialValue=null;this.fire("clear");},initializer:function(){this.publish("blur");this.publish("change");this.publish("focus");this.publish("clear");this.publish("nodeReset");this._initialValue=this.get("value");},destructor:function(b){},renderUI:function(){this._renderLabelNode();this._renderFieldNode();},bindUI:function(){this._fieldNode.on("change",a.bind(function(b){this.set("value",this._fieldNode.get("value"),{src:"ui"});},this));this.on("valueChange",a.bind(function(b){if(b.src!="ui"){this._fieldNode.set("value",b.newVal);}},this));this._fieldNode.on("blur",a.bind(function(b){this.set("value",this._fieldNode.get("value"),{src:"ui"});},this));this._fieldNode.on("focus",a.bind(function(b){this.fire("focus",b);},this));this.on("errorChange",a.bind(function(b){if(b.newVal){this._showError(b.newVal);}else{this._clearError();}},this));this.on("validateInlineChange",a.bind(function(b){if(b.newVal===true){this._enableInlineValidation();}else{this._disableInlineValidation();}},this));this.after("disabledChange",a.bind(function(b){this._syncDisabled();},this));},syncUI:function(){this.get("boundingBox").removeAttribute("tabindex");this._syncLabelNode();this._syncFieldNode();this._syncError();this._syncDisabled();if(this.get("validateInline")===true){this._enableInlineValidation();}}},{ATTRS:{id:{value:a.guid(),validator:a.Lang.isString,writeOnce:true},name:{validator:a.Lang.isString,writeOnce:true},value:{value:"",validator:a.Lang.isString},label:{value:"",validator:a.Lang.isString},validator:{value:function(b){return true;},validator:function(b){return this._validateValidator(b);},setter:function(b){return this._setValidator(b);}},error:{value:false,validator:function(b){return this._validateError(b);}},required:{value:false,validator:a.Lang.isBoolean},validateInline:{value:false,validator:a.Lang.isBoolean}},tabIndex:1,VALIDATE_EMAIL_ADDRESS:function(d,c){var b=/^([\w]+(?:\.[\w]+)*)@((?:[\w]+\.)*\w[\w]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;if(b.test(d)===false){c.set("error",a.FormField.INVALID_EMAIL_MESSAGE);return false;}return true;},INVALID_EMAIL_MESSAGE:"Please enter a valid email address",VALIDATE_PHONE_NUMBER:function(d,c){var b=/^((\+\d{1,3}(-| )?\(?\d\)?(-| )?\d{1,5})|(\(?\d{2,6}\)?))(-| )?(\d{3,4})(-| )?(\d{4})(( x| ext)\d{1,5}){0,1}$/;if(b.test(d)===false){c.set("error",a.FormField.INVALID_PHONE_NUMBER);return false;}return true;},INVALID_PHONE_NUMBER:"Please enter a valid phone number",VALIDATE_IP_ADDRESS:function(f,e){var c=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/,b,d=true;if(c.test(f)===false){d=false;}b=f.split(".");a.Array.each(b,function(h,j,g){var k=parseInt(h,10);if(k<0||k>255){d=false;}});if(d===false){e.set("error",a.FormField.INVALID_IP_MESSAGE);}return d;},INVALID_IP_MESSAGE:"Please enter a valid IP address",VALIDATE_DATE:function(d,c){var b=/^([1-9]|1[0-2])(\-|\/)([0-2][0-9]|3[0-1])(\-|\/)(\d{4}|\d{2})$/;if(b.test(d)===false){c.set("error",a.FormField.INVALID_DATE_MESSAGE);return false;}return true;},INVALID_DATE_MESSAGE:"Please enter a a valid date",VALIDATE_TIME:function(d,c){var b=/^([1-9]|1[0-2]):[0-5]\d(:[0-5]\d(\.\d{1,3})?)?$/;if(b.test(d)===false){c.set("error",a.FormField.INVALID_TIME_MESSAGE);return false;}return true;},INVALID_TIME_MESSAGE:"Please enter a valid time",VALIDATE_POSTAL_CODE:function(e,d){var b,c=true;if(e.length==6||e.length==7){b=/^[a-zA-Z]\d[a-zA-Z](-|\s)?\d[a-zA-Z]\d$/;}else{if(e.length==5||e.length==10){b=/^\d{5}((-|\s)\d{4})?$/;}else{if(e.length>0){c=false;}}}if(c===false||(b&&b.test(e)===false)){d.set("error",a.FormField.INVALID_POSTAL_CODE_MESSAGE);return false;}return true;},INVALID_POSTAL_CODE_MESSAGE:"Please enter a valid postal code",VALIDATE_NO_SPECIAL_CHARS:function(d,c){var b=/^[a-zA-Z0-9]*$/;if(b.test(d)===false){c.set("error",a.FormField.INVALID_SPECIAL_CHARS);return false;}return true;},INVALID_SPECIAL_CHARS:"Please use only letters and numbers",INPUT_TEMPLATE:"<input />",LABEL_TEMPLATE:"<label></label>",REQUIRED_ERROR_TEXT:"This field is required",FIELD_ID_SUFFIX:"-field"});a.TextField=a.Base.create("text-field",a.FormField,[a.WidgetChild]);a.PasswordField=a.Base.create("password-field",a.FormField,[a.WidgetChild]);a.CheckboxField=a.Base.create("checkbox-field",a.FormField,[a.WidgetChild],{_syncChecked:function(){this._fieldNode.set("checked",this.get("checked"));
-},initializer:function(){a.CheckboxField.superclass.initializer.apply(this,arguments);},syncUI:function(){a.CheckboxField.superclass.syncUI.apply(this,arguments);this._syncChecked();},bindUI:function(){a.CheckboxField.superclass.bindUI.apply(this,arguments);this.after("checkedChange",a.bind(function(b){if(b.src!="ui"){this._fieldNode.set("checked",b.newVal);}},this));this._fieldNode.after("change",a.bind(function(b){this.set("checked",b.currentTarget.get("checked"),{src:"ui"});},this));}},{ATTRS:{"checked":{value:false,validator:a.Lang.isBoolean}}});a.RadioField=a.Base.create("radio-field",a.FormField,[a.WidgetChild]);a.HiddenField=a.Base.create("hidden-field",a.FormField,[a.WidgetChild],{_valueDisplayNode:null,_renderValueDisplayNode:function(){if(this.get("displayValue")===true){var c=a.Node.create("<div></div>"),b=this.get("contentBox");b.appendChild(c);this._valueDisplayNode=c;}},renderUI:function(){a.HiddenField.superclass.renderUI.apply(this,arguments);this._renderValueDisplayNode();},bindUI:function(){a.HiddenField.superclass.bindUI.apply(this,arguments);if(this.get("displayValue")===true){this.after("valueChange",a.bind(function(b,c){this._valueDisplayNode.set("innerHTML",c.newVal);},this,true));}},clear:function(){}},{ATTRS:{displayValue:{value:false,writeOnce:true,validator:a.Lang.isBoolean}}});a.TextareaField=a.Base.create("textarea-field",a.FormField,[a.WidgetChild],{_renderFieldNode:function(){var b=this.get("contentBox"),c=b.one("#"+this.get("id"));if(!c){c=a.Node.create(a.TextareaField.NODE_TEMPLATE);c.setAttrs({name:this.get("name"),innerHTML:this.get("value")});b.appendChild(c);}c.setAttribute("tabindex",a.FormField.tabIndex);a.FormField.tabIndex++;this._fieldNode=c;}},{NODE_TEMPLATE:"<textarea></textarea>"});a.ChoiceField=a.Base.create("choice-field",a.FormField,[a.WidgetParent,a.WidgetChild],{_validateChoices:function(d){if(!a.Lang.isArray(d)){return false;}var c=0,b=d.length;for(;c<b;c++){if(!a.Lang.isObject(d[c])){delete d[c];continue;}if(!d[c].label||!a.Lang.isString(d[c].label)||!d[c].value||!a.Lang.isString(d[c].value)){delete d[c];continue;}}if(d.length===0){return false;}return true;},_renderLabelNode:function(){var b=this.get("contentBox"),c=a.Node.create("<span></span>");c.set("innerHTML",this.get("label"));b.appendChild(c);this._labelNode=c;},_renderFieldNode:function(){var d=this.get("contentBox"),e=this.get("choices"),b=this.get("multi"),c=(b===true?a.CheckboxField:a.RadioField);a.Array.each(e,function(k,h,g){var f={value:k.value,id:(this.get("id")+"_choice"+h),name:this.get("name"),label:k.label},j=new c(f);j.render(d);},this);this._fieldNode=d.all("input");},_syncFieldNode:function(){var b=this.get("value").split(",");if(b&&b.length>0){a.Array.each(b,function(c){this._fieldNode.each(function(e,d,f){if(a.Lang.trim(e.get("value"))==a.Lang.trim(c)){e.set("checked",true);return true;}},this);},this);}},clear:function(){this._fieldNode.each(function(c,b,d){c.set("checked",false);},this);this.set("value","");},bindUI:function(){this._fieldNode.on("change",a.bind(function(c){var b="";this._fieldNode.each(function(e,d,f){if(e.get("checked")===true){if(b.length>0){b+=",";}b+=e.get("value");}},this);this.set("value",b);},this));}},{ATTRS:{choices:{validator:function(b){return this._validateChoices(b);}},multi:{validator:a.Lang.isBoolean,value:false}}});a.SelectField=a.Base.create("select-field",a.ChoiceField,[a.WidgetParent,a.WidgetChild],{_renderFieldNode:function(){var b=this.get("contentBox"),c=b.one("#"+this.get("id"));if(!c){c=a.Node.create(a.SelectField.NODE_TEMPLATE);b.appendChild(c);}this._fieldNode=c;this._renderOptionNodes();},_renderOptionNodes:function(){var c=this.get("choices"),b;if(this.get("useDefaultOption")===true){b=a.Node.create(a.SelectField.OPTION_TEMPLATE);this._fieldNode.appendChild(b);}a.Array.each(c,function(f,e,d){b=a.Node.create(a.SelectField.OPTION_TEMPLATE);this._fieldNode.appendChild(b);},this);},_syncFieldNode:function(){a.SelectField.superclass.constructor.superclass._syncFieldNode.apply(this,arguments);this._fieldNode.setAttrs({multiple:(this.get("multi")===true?"multiple":"")});},_syncOptionNodes:function(){var f=this.get("choices"),b=this.get("contentBox"),d=b.all("option"),e=this.get("useDefaultOption"),c=this.get("value");if(e===true){f.unshift({label:a.SelectField.DEFAULT_OPTION_TEXT,value:""});}d.each(function(j,i,h){var g=f[i].label,k=f[i].value;j.setAttrs({innerHTML:g,value:k});if(c==k){j.setAttrs({selected:true,defaultSelected:true});}},this);},clear:function(){this._fieldNode.value="";},bindUI:function(){a.SelectField.superclass.constructor.superclass.bindUI.apply(this,arguments);},syncUI:function(){a.SelectField.superclass.syncUI.apply(this,arguments);this._syncOptionNodes();}},{NODE_TEMPLATE:"<select></select>",OPTION_TEMPLATE:"<option></option>",DEFAULT_OPTION_TEXT:"Choose one",ATTRS:{useDefaultOption:{validator:a.Lang.isBoolean,value:true}}});a.FormButton=a.Base.create("button-field",a.FormField,[a.WidgetChild],{_renderButtonNode:function(){var b=this.get("contentBox"),c;c=a.Node.create(a.FormButton.NODE_TEMPLATE);b.appendChild(c);this._fieldNode=c;},_syncLabelNode:function(){},_syncFieldNode:function(){this._fieldNode.setAttrs({innerHTML:this.get("label"),id:this.get("id")+a.FormField.FIELD_ID_SUFFIX});this.get("contentBox").addClass("first-child");},_setClickHandler:function(){if(!this._fieldNode){return;}var b=this.get("onclick");a.Event.purgeElement(this._fieldNode,true,"click");a.on("click",a.bind(b.fn,b.scope,true),this._fieldNode);},renderUI:function(){this._renderButtonNode();},bindUI:function(){this.after("onclickChange",a.bind(this._setClickHandler,this,true));this._setClickHandler();}},{ATTRS:{onclick:{validator:function(b){if(a.Lang.isObject(b)===false){return false;}if(typeof b.fn=="undefined"||a.Lang.isFunction(b.fn)===false){return false;}return true;},value:{fn:function(b){}},setter:function(b){b.scope=b.scope||this;b.argument=b.argument||{};return b;}}},NODE_TEMPLATE:"<button></button>"});a.FileField=a.Base.create("file-field",a.FormField,[a.WidgetChild],{_renderFieldNode:function(){var b=this.get("contentBox"),c=b.one("#"+this.get("id"));
-if(!c){c=a.Node.create(a.FileField.FILE_INPUT_TEMPLATE);b.appendChild(c);}this._fieldNode=c;}},{FILE_INPUT_TEMPLATE:'<input type="file" />'});a.SubmitButton=a.Base.create("submit-button",a.FormField,[a.WidgetChild],{_renderLabelNode:function(){}});a.ResetButton=a.Base.create("reset-button",a.FormField,[a.WidgetChild],{_renderLabelNode:function(){}});},"gallery-2011.02.23-19-01",{requires:["node","widget-base","widget-htmlparser","io-form","widget-parent","widget-child","base-build","substitute","io-upload-iframe"]});
+YUI.add("gallery-form",function(a){a.Form=a.Base.create("form",a.Widget,[a.WidgetParent],{toString:function(){return this.name;},CONTENT_TEMPLATE:"<form></form>",_ioIds:null,_validateMethod:function(b){if(!a.Lang.isString(b)){return false;}if(b.toLowerCase()!="get"&&b.toLowerCase()!="post"){return false;}return true;},_parseAction:function(b){var c=b.one("form");if(!c){c=b;}if(c){return c.get("action");}},_parseMethod:function(b){var c=b.one("form");if(!c){c=b;}if(c){return c.get("method");}},_parseFields:function(c){var e=c.all("*"),f=c.all("label"),b=[],d={text:a.TextField,hidden:a.HiddenField,file:a.FileField,checkbox:a.CheckboxField,radio:a.RadioField,reset:a.ResetButton,submit:a.SubmitButton,button:(a.Button||a.FormButton)};e.each(function(j,h,g){var n=j.get("nodeName"),l=j.get("id"),i,k,m=[];if(n=="INPUT"){i=j.get("type");k={type:(d[i]?d[i]:a.TextField),name:j.get("name"),value:j.get("value"),checked:j.get("checked")};if(k.type==d.button){k.label=j.get("value");}}else{if(n=="BUTTON"){k={type:d.button,name:j.get("name"),label:j.get("innerHTML")};}else{if(n=="SELECT"){j.all("option").each(function(p,q,o){m.push({label:p.get("innerHTML"),value:p.get("value")});});k={type:a.SelectField,name:j.get("name"),choices:m};}else{if(n=="TEXTAREA"){k={type:a.TextareaField,name:j.get("name"),value:j.get("innerHTML")};}}}}if(k){if(l){k.id=l;f.some(function(p,q,o){if(p.get("htmlFor")==l){k.label=p.get("innerHTML");}});}b.push(k);}j.remove();});return b;},_syncFormAttributes:function(){var b=this.get("contentBox");b.setAttrs({action:this.get("action"),method:this.get("method")});if(this.get("encodingType")===a.Form.MULTIPART_ENCODED){b.setAttribute("enctype","multipart/form-data");}},_runValidation:function(){var b=true;this.each(function(c){if(c.validateField()===false){b=false;}});return b;},_enableInlineValidation:function(){this.each(function(b){b.set("validateInline",true);});},_disableInlineValidation:function(){this.each(function(b){b.set("validateInline",false);});},_handleIOEvent:function(d,b,c){if(this._ioIds[b]!==undefined){this.fire(d,{response:c});}},reset:function(){var b=a.Node.getDOMNode(this.get("contentBox"));if(a.Lang.isFunction(b.reset)){b.reset();}this.each(function(c){c.resetFieldNode();c.set("error",null);});},submit:function(){if(this.get("skipValidationBeforeSubmit")===true||this._runValidation()){var c=this.get("action"),e=this.get("method"),d=this.get("submitViaIO"),g=this.get("io"),f,b;if(d===true){b={method:e,form:{id:this.get("contentBox"),upload:(this.get("encodingType")===a.Form.MULTIPART_ENCODED)}};f=g(c,b);this._ioIds[f.id]=f;}else{this.get("contentBox").submit();}}},getField:function(b){var c;if(a.Lang.isNumber(b)){c=this.item(b);}else{if(a.Lang.isString(b)){this.each(function(d){if(d.get("name")==b){c=d;}});}}return c;},initializer:function(b){this._ioIds={};this.publish("submit");this.publish("reset");this.publish("start");this.publish("success");this.publish("failure");this.publish("complete");this.publish("xdr");},destructor:function(){},renderUI:function(){},bindUI:function(){this.get("contentBox").on("submit",a.bind(function(b){b.halt();},this));this.after("inlineValidationChange",a.bind(function(b){if(b.newVal===true){this._enableInlineValidation();}else{this._disableInlineValidation();}},this));this.after("success",a.bind(function(b){if(this.get("resetAfterSubmit")===true){this.reset();}},this));a.on("io:start",a.bind(this._handleIOEvent,this,"start"));a.on("io:complete",a.bind(this._handleIOEvent,this,"complete"));a.on("io:xdr",a.bind(this._handleIOEvent,this,"xdr"));a.on("io:success",a.bind(this._handleIOEvent,this,"success"));a.on("io:failure",a.bind(this._handleIOEvent,this,"failure"));this.each(a.bind(function(b){if(b.name=="submit-button"){b.on("click",a.bind(this.submit,this));}else{if(b.name=="reset-button"){b.on("click",a.bind(this.reset,this));}}},this));},syncUI:function(){this._syncFormAttributes();if(this.get("inlineValidation")===true){this._enableInlineValidation();}}},{ATTRS:{defaultChildType:{valueFn:function(){return a.TextField;}},method:{value:"post",validator:function(b){return this._validateMethod(b);},setter:function(b){return b.toLowerCase();}},action:{value:".",validator:a.Lang.isString},fields:{setter:function(b){return this.set("children",b);}},inlineValidation:{value:false,validator:a.Lang.isBoolean},resetAfterSubmit:{value:true,validator:a.Lang.isBoolean},encodingType:{value:1,validator:a.Lang.isNumber},skipValidationBeforeSubmit:{value:false,validator:a.Lang.isBoolean},submitViaIO:{value:true,validator:a.Lang.isBoolean},io:{value:a.io}},HTML_PARSER:{action:function(b){return this._parseAction(b);},method:function(b){return this._parseMethod(b);},children:function(b){return this._parseFields(b);}},FORM_TEMPLATE:"<form></form>",URL_ENCODED:1,MULTIPART_ENCODED:2});a.FormField=a.Base.create("form-field",a.Widget,[a.WidgetParent,a.WidgetChild],{toString:function(){return this.name;},FIELD_TEMPLATE:"<input></input>",FIELD_CLASS:"field",LABEL_TEMPLATE:"<label></label>",LABEL_CLASS:"label",HINT_TEMPLATE:"",HINT_CLASS:"hint",ERROR_TEMPLATE:"<span></span>",ERROR_CLASS:"error",_labelNode:null,_hintNode:null,_fieldNode:null,_errorNode:null,_initialValue:null,_validateError:function(b){if(a.Lang.isString(b)){return true;}if(b===null||typeof b=="undefined"){return true;}return false;},_validateValidator:function(c){if(a.Lang.isString(c)){var b=/^(email|phone|ip|date|time|postal|special)$/;if(b.test(c)===true){return true;}}if(a.Lang.isFunction(c)){return true;}return false;},_setValidator:function(c){var b={email:a.FormField.VALIDATE_EMAIL_ADDRESS,phone:a.FormField.VALIDATE_PHONE_NUMBER,ip:a.FormField.VALIDATE_IP_ADDRESS,date:a.FormField.VALIDATE_DATE,time:a.FormField.VALIDATE_TIME,postal:a.FormField.VALIDATE_POSTAL_CODE,special:a.FormField.VALIDATE_NO_SPECIAL_CHARS};return(b[c]?b[c]:c);},_renderNode:function(e,d,c){if(!e){return null;}var b=this.get("contentBox"),g=a.Node.create(e),f=b.one("."+d);g.addClass(d);if(f){f.replace(g);}else{if(c){b.insertBefore(g,c);
+}else{b.appendChild(g);}}return g;},_renderLabelNode:function(){var b=this.get("contentBox"),c=b.one("label");if(!c||c.get("for")!=this.get("id")){c=this._renderNode(this.LABEL_TEMPLATE,this.LABEL_CLASS);}this._labelNode=c;},_renderHintNode:function(){this._hintNode=this._renderNode(this.HINT_TEMPLATE,this.HINT_CLASS);},_renderFieldNode:function(){var b=this.get("contentBox"),c=b.one("#"+this.get("id"));if(!c){c=this._renderNode(this.FIELD_TEMPLATE,this.FIELD_CLASS);}this._fieldNode=c;},_syncLabelNode:function(){var b=this.get("label"),d=this.get("required"),c=this.get("requiredLabel");if(this._labelNode){this._labelNode.set("text","");if(b){this._labelNode.append("<span class='caption'>"+b+"</span>");}if(d&&c){this._labelNode.append("<span class='separator'> </span>");this._labelNode.append("<span class='required'>"+c+"</span>");}this._labelNode.setAttribute("for",this.get("id")+a.FormField.FIELD_ID_SUFFIX);}},_syncHintNode:function(){if(this._hintNode){this._hintNode.set("text",this.get("hint"));}},_syncFieldNode:function(){var b=this.name.split("-")[0];if(!b){return;}this._fieldNode.setAttrs({name:this.get("name"),type:b,id:this.get("id")+a.FormField.FIELD_ID_SUFFIX,value:this.get("value")});this._fieldNode.setAttribute("tabindex",a.FormField.tabIndex);a.FormField.tabIndex++;},_syncError:function(){var b=this.get("error");if(b){this._showError(b);}},_syncDisabled:function(c){var b=this.get("disabled");if(b===true){this._fieldNode.setAttribute("disabled","disabled");}else{this._fieldNode.removeAttribute("disabled");}},_checkRequired:function(){if(this.get("required")===true&&this.get("value").length===0){return false;}return true;},_showError:function(b){var c=this._renderNode(this.ERROR_TEMPLATE,this.ERROR_CLASS,this._labelNode);c.set("text",b);this._errorNode=c;},_clearError:function(){if(this._errorNode){this._errorNode.remove();this._errorNode=null;}},_enableInlineValidation:function(){this.after("valueChange",this.validateField,this);},_disableInlineValidation:function(){this.detach("valueChange",this.validateField,this);},validateField:function(d){var c=this.get("value"),b=this.get("validator");this.set("error",null);if(d&&d.src!="ui"){return false;}if(!this._checkRequired()){this.set("error",a.FormField.REQUIRED_ERROR_TEXT);return false;}else{if(!c){return true;}}return b.call(this,c,this);},resetFieldNode:function(){this.set("value",this._initialValue);this._fieldNode.set("value",this._initialValue);this.fire("nodeReset");},clear:function(){this.set("value","");this._fieldNode.set("value","");this._initialValue=null;this.fire("clear");},initializer:function(){this.publish("blur");this.publish("change");this.publish("focus");this.publish("clear");this.publish("nodeReset");this._initialValue=this.get("value");},destructor:function(b){},renderUI:function(){this._renderLabelNode();this._renderFieldNode();this._renderHintNode();},bindUI:function(){this._fieldNode.on("change",a.bind(function(b){this.set("value",this._fieldNode.get("value"),{src:"ui"});},this));this.on("valueChange",a.bind(function(b){if(b.src!="ui"){this._fieldNode.set("value",b.newVal);}},this));this._fieldNode.on("blur",a.bind(function(b){this.set("value",this._fieldNode.get("value"),{src:"ui"});},this));this._fieldNode.on("focus",a.bind(function(b){this.fire("focus",b);},this));this.on("errorChange",a.bind(function(b){if(b.newVal){this._showError(b.newVal);}else{this._clearError();}},this));this.on("validateInlineChange",a.bind(function(b){if(b.newVal===true){this._enableInlineValidation();}else{this._disableInlineValidation();}},this));this.after("disabledChange",a.bind(function(b){this._syncDisabled();},this));},syncUI:function(){this.get("boundingBox").removeAttribute("tabindex");this._syncLabelNode();this._syncHintNode();this._syncFieldNode();this._syncError();this._syncDisabled();if(this.get("validateInline")===true){this._enableInlineValidation();}}},{ATTRS:{id:{value:a.guid(),validator:a.Lang.isString,writeOnce:true},name:{validator:a.Lang.isString,writeOnce:true},value:{value:"",validator:a.Lang.isString},label:{value:"",validator:a.Lang.isString},hint:{value:"",validator:a.Lang.isString},validator:{value:function(b){return true;},validator:function(b){return this._validateValidator(b);},setter:function(b){return this._setValidator(b);}},error:{value:false,validator:function(b){return this._validateError(b);}},required:{value:false,validator:a.Lang.isBoolean},validateInline:{value:false,validator:a.Lang.isBoolean},requiredLabel:{value:"",validator:a.Lang.isString}},tabIndex:1,VALIDATE_EMAIL_ADDRESS:function(d,c){var b=/^([\w]+(?:\.[\w]+)*)@((?:[\w]+\.)*\w[\w]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;if(b.test(d)===false){c.set("error",a.FormField.INVALID_EMAIL_MESSAGE);return false;}return true;},INVALID_EMAIL_MESSAGE:"Please enter a valid email address",VALIDATE_PHONE_NUMBER:function(d,c){var b=/^((\+\d{1,3}(-| )?\(?\d\)?(-| )?\d{1,5})|(\(?\d{2,6}\)?))(-| )?(\d{3,4})(-| )?(\d{4})(( x| ext)\d{1,5}){0,1}$/;if(b.test(d)===false){c.set("error",a.FormField.INVALID_PHONE_NUMBER);return false;}return true;},INVALID_PHONE_NUMBER:"Please enter a valid phone number",VALIDATE_IP_ADDRESS:function(f,e){var c=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/,b,d=true;if(c.test(f)===false){d=false;}b=f.split(".");a.Array.each(b,function(h,j,g){var k=parseInt(h,10);if(k<0||k>255){d=false;}});if(d===false){e.set("error",a.FormField.INVALID_IP_MESSAGE);}return d;},INVALID_IP_MESSAGE:"Please enter a valid IP address",VALIDATE_DATE:function(d,c){var b=/^([1-9]|1[0-2])(\-|\/)([0-2][0-9]|3[0-1])(\-|\/)(\d{4}|\d{2})$/;if(b.test(d)===false){c.set("error",a.FormField.INVALID_DATE_MESSAGE);return false;}return true;},INVALID_DATE_MESSAGE:"Please enter a a valid date",VALIDATE_TIME:function(d,c){var b=/^([1-9]|1[0-2]):[0-5]\d(:[0-5]\d(\.\d{1,3})?)?$/;if(b.test(d)===false){c.set("error",a.FormField.INVALID_TIME_MESSAGE);return false;}return true;},INVALID_TIME_MESSAGE:"Please enter a valid time",VALIDATE_POSTAL_CODE:function(e,d){var b,c=true;
+if(e.length==6||e.length==7){b=/^[a-zA-Z]\d[a-zA-Z](-|\s)?\d[a-zA-Z]\d$/;}else{if(e.length==5||e.length==10){b=/^\d{5}((-|\s)\d{4})?$/;}else{if(e.length>0){c=false;}}}if(c===false||(b&&b.test(e)===false)){d.set("error",a.FormField.INVALID_POSTAL_CODE_MESSAGE);return false;}return true;},INVALID_POSTAL_CODE_MESSAGE:"Please enter a valid postal code",VALIDATE_NO_SPECIAL_CHARS:function(d,c){var b=/^[a-zA-Z0-9]*$/;if(b.test(d)===false){c.set("error",a.FormField.INVALID_SPECIAL_CHARS);return false;}return true;},INVALID_SPECIAL_CHARS:"Please use only letters and numbers",REQUIRED_ERROR_TEXT:"This field is required",FIELD_ID_SUFFIX:"-field"});a.TextField=a.Base.create("text-field",a.FormField,[a.WidgetChild]);a.PasswordField=a.Base.create("password-field",a.FormField,[a.WidgetChild]);a.CheckboxField=a.Base.create("checkbox-field",a.FormField,[a.WidgetChild],{_syncChecked:function(){this._fieldNode.set("checked",this.get("checked"));},initializer:function(){a.CheckboxField.superclass.initializer.apply(this,arguments);},syncUI:function(){a.CheckboxField.superclass.syncUI.apply(this,arguments);this._syncChecked();},bindUI:function(){a.CheckboxField.superclass.bindUI.apply(this,arguments);this.after("checkedChange",a.bind(function(b){if(b.src!="ui"){this._fieldNode.set("checked",b.newVal);}},this));this._fieldNode.after("change",a.bind(function(b){this.set("checked",b.currentTarget.get("checked"),{src:"ui"});},this));}},{ATTRS:{"checked":{value:false,validator:a.Lang.isBoolean}}});a.RadioField=a.Base.create("radio-field",a.FormField,[a.WidgetChild]);a.HiddenField=a.Base.create("hidden-field",a.FormField,[a.WidgetChild],{_valueDisplayNode:null,_renderValueDisplayNode:function(){if(this.get("displayValue")===true){var c=a.Node.create("<div></div>"),b=this.get("contentBox");b.appendChild(c);this._valueDisplayNode=c;}},renderUI:function(){a.HiddenField.superclass.renderUI.apply(this,arguments);this._renderValueDisplayNode();},bindUI:function(){a.HiddenField.superclass.bindUI.apply(this,arguments);if(this.get("displayValue")===true){this.after("valueChange",a.bind(function(b,c){this._valueDisplayNode.set("innerHTML",c.newVal);},this,true));}},clear:function(){}},{ATTRS:{displayValue:{value:false,writeOnce:true,validator:a.Lang.isBoolean}}});a.TextareaField=a.Base.create("textarea-field",a.FormField,[a.WidgetChild],{FIELD_TEMPLATE:"<textarea></textarea>"});a.ChoiceField=a.Base.create("choice-field",a.FormField,[a.WidgetParent,a.WidgetChild],{LABEL_TEMPLATE:"<span></span>",SINGLE_CHOICE:a.RadioField,MULTI_CHOICE:a.CheckboxField,_validateChoices:function(d){if(!a.Lang.isArray(d)){return false;}var c=0,b=d.length;for(;c<b;c++){if(!a.Lang.isObject(d[c])){delete d[c];continue;}if(!d[c].label||!a.Lang.isString(d[c].label)||!d[c].value||!a.Lang.isString(d[c].value)){delete d[c];continue;}}if(d.length===0){return false;}return true;},_renderFieldNode:function(){var d=this.get("contentBox"),e=d.one("."+this.FIELD_CLASS),f=this.get("choices"),b=this.get("multi"),c=(b===true?this.MULTI_CHOICE:this.SINGLE_CHOICE);if(!e){e=d;}a.Array.each(f,function(l,j,h){var g={value:l.value,id:(this.get("id")+"_choice"+j),name:this.get("name"),label:l.label},k=new c(g);k.render(e);},this);this._fieldNode=e.all("input");},_syncFieldNode:function(){var b=this.get("value").split(",");if(b&&b.length>0){a.Array.each(b,function(c){this._fieldNode.each(function(e,d,f){if(a.Lang.trim(e.get("value"))==a.Lang.trim(c)){e.set("checked",true);return true;}},this);},this);}},_afterChoicesChange:function(c){var b=this.get("contentBox");b.all(".yui3-form-field").remove();this._renderFieldNode();},clear:function(){this._fieldNode.each(function(c,b,d){c.set("checked",false);},this);this.set("value","");},bindUI:function(){this._fieldNode.on("change",a.bind(function(c){var b="";this._fieldNode.each(function(e,d,f){if(e.get("checked")===true){if(b.length>0){b+=",";}b+=e.get("value");}},this);this.set("value",b);},this));this.after("choicesChange",this._afterChoicesChange);}},{ATTRS:{choices:{validator:function(b){return this._validateChoices(b);}},multi:{validator:a.Lang.isBoolean,value:false}}});a.SelectField=a.Base.create("select-field",a.ChoiceField,[a.WidgetParent,a.WidgetChild],{FIELD_TEMPLATE:"<select></select>",DEFAULT_OPTION_TEXT:"Choose one",_renderFieldNode:function(){a.SelectField.superclass.constructor.superclass._renderFieldNode.apply(this,arguments);this._renderOptionNodes();},_renderOptionNodes:function(){var c=this.get("choices"),b;if(this.get("useDefaultOption")===true){b=a.Node.create(a.SelectField.OPTION_TEMPLATE);this._fieldNode.appendChild(b);}a.Array.each(c,function(f,e,d){b=a.Node.create(a.SelectField.OPTION_TEMPLATE);this._fieldNode.appendChild(b);},this);},_syncFieldNode:function(){a.SelectField.superclass.constructor.superclass._syncFieldNode.apply(this,arguments);this._fieldNode.setAttrs({size:this.get("size"),multiple:(this.get("multi")===true?"multiple":"")});},_syncOptionNodes:function(){var f=this.get("choices"),b=this.get("contentBox"),d=b.all("option"),e=this.get("useDefaultOption"),c=this.get("value");if(e===true){f.unshift({label:this.DEFAULT_OPTION_TEXT,value:""});}d.each(function(j,i,h){var g=f[i].label,k=f[i].value;j.setAttrs({innerHTML:g,value:k});if(c==k){j.setAttrs({selected:true,defaultSelected:true});}},this);},_afterChoicesChange:function(b){var c=this._fieldNode.all("option");c.remove();this._renderOptionNodes();this._syncOptionNodes();},clear:function(){this._fieldNode.value="";},bindUI:function(){a.SelectField.superclass.constructor.superclass.bindUI.apply(this,arguments);this.after("choicesChange",this._afterChoicesChange);},syncUI:function(){a.SelectField.superclass.syncUI.apply(this,arguments);this._syncOptionNodes();}},{OPTION_TEMPLATE:"<option></option>",ATTRS:{useDefaultOption:{validator:a.Lang.isBoolean,value:true},choices:{validator:function(b){if(this.get("useDefaultOption")&&a.Lang.isArray(b)&&b.length===0){return true;}else{return this._validateChoices(b);}}},size:{validator:a.Lang.isString,value:"0"}}});
+a.FormButton=a.Base.create("button-field",a.FormField,[a.WidgetChild],{FIELD_TEMPLATE:"<button></button>",LABEL_TEMPLATE:"",_syncFieldNode:function(){this._fieldNode.setAttrs({innerHTML:this.get("label"),id:this.get("id")+a.FormField.FIELD_ID_SUFFIX});this.get("contentBox").addClass("first-child");},_setClickHandler:function(){if(!this._fieldNode){return;}a.Event.purgeElement(this._fieldNode,true,"click");a.on("click",a.bind(this._promptConfirm,this),this._fieldNode);},_promptConfirm:function(d){d.preventDefault();var c=this.get("message"),b=this.get("onclick");if(c){if(!this.get("confirm")(c)){return;}}b.fn.apply(b.scope);},bindUI:function(){this.after("onclickChange",a.bind(this._setClickHandler,this,true));this.after("disabledChange",this._syncDisabled,this);this._setClickHandler();}},{ATTRS:{onclick:{validator:function(b){if(a.Lang.isObject(b)===false){return false;}if(typeof b.fn=="undefined"||a.Lang.isFunction(b.fn)===false){return false;}return true;},value:{fn:function(b){}},setter:function(b){b.scope=b.scope||this;b.argument=b.argument||{};return b;}},message:{validator:a.Lang.isString,value:null},confirm:{validator:a.Lang.isFunction,value:null}}});a.FileField=a.Base.create("file-field",a.FormField,[a.WidgetChild]);a.SubmitButton=a.Base.create("submit-button",a.FormField,[a.WidgetChild],{_renderLabelNode:function(){}});a.ResetButton=a.Base.create("reset-button",a.FormField,[a.WidgetChild],{LABEL_TEMPLATE:""});},"gallery-2011.06.15-19-18",{requires:["node","widget-base","widget-htmlparser","io-form","widget-parent","widget-child","base-build","substitute","io-upload-iframe"]});
View
418 build/gallery-form/gallery-form.js
@@ -248,6 +248,7 @@ Y.Form = Y.Base.create('form', Y.Widget, [Y.WidgetParent], {
var formAction = this.get('action'),
formMethod = this.get('method'),
submitViaIO = this.get('submitViaIO'),
+ io = this.get("io"),
transaction,
cfg;
@@ -260,7 +261,6 @@ Y.Form = Y.Base.create('form', Y.Widget, [Y.WidgetParent], {
}
};
- var io = this.get("io");
transaction = io(formAction, cfg);
this._ioIds[transaction.id] = transaction;
} else {
@@ -523,6 +523,68 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
toString: function() {
return this.name;
},
+
+ /**
+ * @property FormField.FIELD_TEMPLATE
+ * @type String
+ * @description Template used to render the field node
+ */
+ FIELD_TEMPLATE : '<input></input>',
+
+ /**
+ * @property FormField.FIELD_CLASS
+ * @type String
+ * @description CSS class used to locate a placeholder for
+ * the field node and style it.
+ */
+ FIELD_CLASS : 'field',
+
+ /**
+ * @property FormField.LABEL_TEMPLATE
+ * @type String
+ * @description Template used to draw a label node
+ */
+ LABEL_TEMPLATE : '<label></label>',
+
+ /**
+ * @property FormField.LABEL_CLASS
+ * @type String
+ * @description CSS class used to locate a placeholder for
+ * the label node and style it.
+ */
+ LABEL_CLASS : 'label',
+
+ /**
+ * @property FormField.HINT_TEMPLATE
+ * @type String
+ * @description Optionally a template used to draw a hint node. Derived
+ * classes can use it to provide additional information about the field
+ */
+ HINT_TEMPLATE : '',
+
+ /**
+ * @property FormField.HINT_CLASS
+ * @type String
+ * @description CSS class used to locate a placeholder for
+ * the hint node and style it.
+ */
+ HINT_CLASS : 'hint',
+
+ /**
+ * @property FormField.ERROR_TEMPLATE
+ * @type String
+ * @description Template used to draw an error node
+ */
+ ERROR_TEMPLATE : '<span></span>',
+
+ /**
+ * @property FormField.ERROR_CLASS
+ * @type String
+ * @description CSS class used to locate a placeholder for
+ * the error node and style it.
+ */
+ ERROR_CLASS : 'error',
+
/**
* @property _labelNode
* @protected
@@ -531,6 +593,14 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
*/
_labelNode: null,
+ /**
+ * @property _hintNode
+ * @protected
+ * @type Object
+ * @description The hint node with extra text describing the field
+ */
+ _hintNode : null,
+
/**
* @property _fieldNode
* @protected
@@ -617,6 +687,35 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
},
/**
+ * @method _renderNode
+ * @protected
+ * @description Helper method to render new nodes, possibly replacing
+ * markup placeholders.
+ */
+ _renderNode : function (nodeTemplate, nodeClass, nodeBefore) {
+ if (!nodeTemplate) {
+ return null;
+ }
+ var contentBox = this.get('contentBox'),
+ node = Y.Node.create(nodeTemplate),
+ placeHolder = contentBox.one('.' + nodeClass);
+
+ node.addClass(nodeClass);
+
+ if (placeHolder) {
+ placeHolder.replace(node);
+ } else {
+ if (nodeBefore) {
+ contentBox.insertBefore(node, nodeBefore);
+ } else {
+ contentBox.appendChild(node);
+ }
+ }
+
+ return node;
+ },
+
+ /**
* @method _renderLabelNode
* @protected
* @description Draws the form field's label node into the contentBox
@@ -626,14 +725,25 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
labelNode = contentBox.one('label');
if (!labelNode || labelNode.get('for') != this.get('id')) {
- labelNode = Y.Node.create(Y.FormField.LABEL_TEMPLATE);
- contentBox.appendChild(labelNode);
+ labelNode = this._renderNode(this.LABEL_TEMPLATE, this.LABEL_CLASS);
}
this._labelNode = labelNode;
},
/**
+ * @method _renderHintNode
+ * @protected
+ * @description Draws the hint node into the contentBox. If a node is
+ * found in the contentBox with class HINT_CLASS, it will be
+ * considered a markup placeholder and replaced with the hint node.
+ */
+ _renderHintNode : function () {
+ this._hintNode = this._renderNode(this.HINT_TEMPLATE,
+ this.HINT_CLASS);
+ },
+
+ /**
* @method _renderFieldNode
* @protected
* @description Draws the field node into the contentBox
@@ -643,8 +753,7 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
field = contentBox.one('#' + this.get('id'));
if (!field) {
- field = Y.Node.create(Y.FormField.INPUT_TEMPLATE);
- contentBox.appendChild(field);
+ field = this._renderNode(this.FIELD_TEMPLATE, this.FIELD_CLASS);
}
this._fieldNode = field;
@@ -656,16 +765,35 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
* @description Syncs the the label node and this instances attributes
*/
_syncLabelNode: function() {
+ var label = this.get('label'),
+ required = this.get('required'),
+ requiredLabel = this.get('requiredLabel');
if (this._labelNode) {
- this._labelNode.setAttrs({
- innerHTML: this.get('label')
- });
+ this._labelNode.set("text", "");
+ if (label) {
+ this._labelNode.append("<span class='caption'>" + label + "</span>");
+ }
+ if (required && requiredLabel) {
+ this._labelNode.append("<span class='separator'> </span>");
+ this._labelNode.append("<span class='required'>" + requiredLabel + "</span>");
+ }
this._labelNode.setAttribute('for', this.get('id') + Y.FormField.FIELD_ID_SUFFIX);
}
},
/**
- * @method _syncLabelNode
+ * @method _syncHintNode
+ * @protected
+ * @description Syncs the hintNode
+ */
+ _syncHintNode : function () {
+ if (this._hintNode) {
+ this._hintNode.set("text", this.get("hint"));
+ }
+ },
+
+ /**
+ * @method _syncFieldNode
* @protected
* @description Syncs the fieldNode and this instances attributes
*/
@@ -727,12 +855,9 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
* @description Adds an error node with the supplied message
*/
_showError: function(errMsg) {
- var contentBox = this.get('contentBox'),
- errorNode = Y.Node.create('<span>' + errMsg + '</span>');
-
- errorNode.addClass('error');
- contentBox.insertBefore(errorNode, this._labelNode);
+ var errorNode = this._renderNode(this.ERROR_TEMPLATE, this.ERROR_CLASS, this._labelNode);
+ errorNode.set("text", errMsg);
this._errorNode = errorNode;
},
@@ -743,8 +868,7 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
*/
_clearError: function() {
if (this._errorNode) {
- var contentBox = this.get('contentBox');
- contentBox.removeChild(this._errorNode);
+ this._errorNode.remove();
this._errorNode = null;
}
},
@@ -816,6 +940,7 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
renderUI: function() {
this._renderLabelNode();
this._renderFieldNode();
+ this._renderHintNode();
},
bindUI: function() {
@@ -872,6 +997,7 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
syncUI: function() {
this.get('boundingBox').removeAttribute('tabindex');
this._syncLabelNode();
+ this._syncHintNode();
this._syncFieldNode();
this._syncError();
this._syncDisabled();
@@ -937,6 +1063,17 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
},
/**
+ * @attribute hint
+ * @type String
+ * @default ""
+ * @description Extra text explaining what the field is about.
+ */
+ hint : {
+ value : '',
+ validator : Y.Lang.isString
+ },
+
+ /**
* @attribute validator
* @type Function
* @default "function () { return true; }"
@@ -987,6 +1124,17 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
validateInline: {
value: false,
validator: Y.Lang.isBoolean
+ },
+
+ /**
+ * @attribute requiredLabel
+ * @type String
+ * @description Text to append to the labal caption for a required
+ * field, by default nothing will be appended.
+ */
+ requiredLabel : {
+ value : '',
+ validator : Y.Lang.isString
}
},
@@ -1172,20 +1320,6 @@ Y.FormField = Y.Base.create('form-field', Y.Widget, [Y.WidgetParent, Y.WidgetChi
INVALID_SPECIAL_CHARS: "Please use only letters and numbers",
/**
- * @property FormField.INPUT_TEMPLATE
- * @type String
- * @description Template used to draw an input node
- */
- INPUT_TEMPLATE: '<input />',
-
- /**
- * @property FormField.LABEL_TEMPLATE
- * @type String
- * @description Template used to draw a label node
- */
- LABEL_TEMPLATE: '<label></label>',
-
- /**
* @property FormField.REQUIRED_ERROR_TEXT
* @type String
* @description Error text to display for a required field
@@ -1338,31 +1472,9 @@ Y.HiddenField = Y.Base.create('hidden-field', Y.FormField, [Y.WidgetChild], {
* @description A hidden field node
*/
Y.TextareaField = Y.Base.create('textarea-field', Y.FormField, [Y.WidgetChild], {
- _renderFieldNode : function () {
- var contentBox = this.get('contentBox'),
- field = contentBox.one('#' + this.get('id'));
-
- if (!field) {
- field = Y.Node.create(Y.TextareaField.NODE_TEMPLATE);
- field.setAttrs({
- name : this.get('name'),
- innerHTML : this.get('value')
- });
- contentBox.appendChild(field);
- }
- field.setAttribute('tabindex', Y.FormField.tabIndex);
- Y.FormField.tabIndex++;
-
- this._fieldNode = field;
- }
-}, {
- /**
- * @property TextareaField.NODE_TEMPLATE
- * @type String
- * @description Template used to draw a textarea node
- */
- NODE_TEMPLATE : '<textarea></textarea>'
+ FIELD_TEMPLATE : '<textarea></textarea>'
+
});
/**
* @class ChoiceField
@@ -1373,6 +1485,11 @@ Y.TextareaField = Y.Base.create('textarea-field', Y.FormField, [Y.WidgetChild],
* selection of choices
*/
Y.ChoiceField = Y.Base.create('choice-field', Y.FormField, [Y.WidgetParent, Y.WidgetChild], {
+
+ LABEL_TEMPLATE: '<span></span>',
+ SINGLE_CHOICE: Y.RadioField,
+ MULTI_CHOICE: Y.CheckboxField,
+
/**
* @method _validateChoices
* @protected
@@ -1408,22 +1525,16 @@ Y.ChoiceField = Y.Base.create('choice-field', Y.FormField, [Y.WidgetParent, Y.Wi
return true;
},
- _renderLabelNode: function() {
- var contentBox = this.get('contentBox'),
- titleNode = Y.Node.create('<span></span>');
-
- titleNode.set('innerHTML', this.get('label'));
- contentBox.appendChild(titleNode);
-
- this._labelNode = titleNode;
- },
-
_renderFieldNode: function() {
var contentBox = this.get('contentBox'),
- choices = this.get('choices'),
- multiple = this.get('multi'),
- fieldType = (multiple === true ? Y.CheckboxField: Y.RadioField);
+ parent = contentBox.one("." + this.FIELD_CLASS),
+ choices = this.get('choices'),
+ multiple = this.get('multi'),
+ fieldType = (multiple === true ? this.MULTI_CHOICE: this.SINGLE_CHOICE);
+ if (!parent) {
+ parent = contentBox;
+ }
Y.Array.each(choices,
function(c, i, a) {
var cfg = {
@@ -1434,9 +1545,9 @@ Y.ChoiceField = Y.Base.create('choice-field', Y.FormField, [Y.WidgetParent, Y.Wi
},
field = new fieldType(cfg);
- field.render(contentBox);
+ field.render(parent);
}, this);
- this._fieldNode = contentBox.all('input');
+ this._fieldNode = parent.all('input');
},
_syncFieldNode: function() {
@@ -1454,6 +1565,17 @@ Y.ChoiceField = Y.Base.create('choice-field', Y.FormField, [Y.WidgetParent, Y.Wi
}
},
+ /**
+ * @method _afterChoiceChange
+ * @description When the available choices for the choice field change,
+ * the old ones are removed and the new ones are rendered.
+ */
+ _afterChoicesChange: function(event) {
+ var contentBox = this.get("contentBox");
+ contentBox.all(".yui3-form-field").remove();
+ this._renderFieldNode();
+ },
+
clear: function() {
this._fieldNode.each(function(node, index, list) {
node.set('checked', false);
@@ -1477,6 +1599,7 @@ Y.ChoiceField = Y.Base.create('choice-field', Y.FormField, [Y.WidgetParent, Y.Wi
this.set('value', value);
},
this));
+ this.after('choicesChange', this._afterChoicesChange);
}
},
@@ -1513,22 +1636,23 @@ Y.ChoiceField = Y.Base.create('choice-field', Y.FormField, [Y.WidgetParent, Y.Wi
* @description A select field node
*/
Y.SelectField = Y.Base.create('select-field', Y.ChoiceField, [Y.WidgetParent, Y.WidgetChild], {
+
+ FIELD_TEMPLATE : '<select></select>',
+
+ /**
+ * @property SelectField.DEFAULT_OPTION_TEXT
+ * @type String
+ * @description The display title of the default choice in the select box
+ */
+ DEFAULT_OPTION_TEXT : 'Choose one',
+
/**
* @method _renderFieldNode
* @protected
* @description Draws the select node into the contentBox
*/
_renderFieldNode: function() {
- var contentBox = this.get('contentBox'),
- field = contentBox.one('#' + this.get('id'));
-
- if (!field) {
- field = Y.Node.create(Y.SelectField.NODE_TEMPLATE);
- contentBox.appendChild(field);
- }
-
- this._fieldNode = field;
-
+ Y.SelectField.superclass.constructor.superclass._renderFieldNode.apply(this, arguments);
this._renderOptionNodes();
},
@@ -1564,6 +1688,7 @@ Y.SelectField = Y.Base.create('select-field', Y.ChoiceField, [Y.WidgetParent, Y.
Y.SelectField.superclass.constructor.superclass._syncFieldNode.apply(this, arguments);
this._fieldNode.setAttrs({
+ size : this.get('size'),
multiple: (this.get('multi') === true ? 'multiple': '')
});
},
@@ -1582,7 +1707,7 @@ Y.SelectField = Y.Base.create('select-field', Y.ChoiceField, [Y.WidgetParent, Y.
if (useDefaultOption === true) {
choices.unshift({
- label: Y.SelectField.DEFAULT_OPTION_TEXT,
+ label : this.DEFAULT_OPTION_TEXT,
value: ''
});
}
@@ -1607,6 +1732,18 @@ Y.SelectField = Y.Base.create('select-field', Y.ChoiceField, [Y.WidgetParent, Y.
},
/**
+ * @method _afterChoiceChange
+ * @description When the available options for the select field change,
+ * the old ones are removed and the new ones are rendered.
+ */
+ _afterChoicesChange: function(evt) {
+ var options = this._fieldNode.all("option");
+ options.remove();
+ this._renderOptionNodes();
+ this._syncOptionNodes();
+ },
+
+ /**
* @method clear
* @description Restores the selected option to the default
*/
@@ -1616,6 +1753,7 @@ Y.SelectField = Y.Base.create('select-field', Y.ChoiceField, [Y.WidgetParent, Y.
bindUI: function() {
Y.SelectField.superclass.constructor.superclass.bindUI.apply(this, arguments);
+ this.after('choicesChange', this._afterChoicesChange);
},
syncUI: function() {
@@ -1625,26 +1763,12 @@ Y.SelectField = Y.Base.create('select-field', Y.ChoiceField, [Y.WidgetParent, Y.
},
{
/**
- * @property SelectField.NODE_TEMPLATE
- * @type String
- * @description Template used to draw a select node
- */
- NODE_TEMPLATE: '<select></select>',
-
- /**
* @property SelectField.OPTION_TEMPLATE
* @type String
* @description Template used to draw an option node
*/
OPTION_TEMPLATE: '<option></option>',
- /**
- * @property SelectField.DEFAULT_OPTION_TEXT
- * @type String
- * @description The display title of the default choice in the select box
- */
- DEFAULT_OPTION_TEXT: 'Choose one',
-
ATTRS: {
/**
* @attribute useDefaultOption
@@ -1656,19 +1780,42 @@ Y.SelectField = Y.Base.create('select-field', Y.ChoiceField, [Y.WidgetParent, Y.
useDefaultOption: {
validator: Y.Lang.isBoolean,
value: true
+ },
+
+ /**
+ * @attribute choices
+ * @type Array
+ * @description The choices to render into this field
+ */
+ choices: {
+ validator: function(val) {
+ if (this.get("useDefaultOption") &&
+ Y.Lang.isArray(val) &&
+ val.length === 0) {
+ // Empty arrays are okay if useDefaultOption is 'true'
+ return true;
+ } else {
+ return this._validateChoices(val);
+ }
+ }
+ },
+
+ /**
+ * @attribute size
+ * @type String
+ * @default 0
+ * @description Value of 'size' attribute of the select element.
+ */
+ size : {
+ validator : Y.Lang.isString,
+ value : '0'
}
}
});
Y.FormButton = Y.Base.create('button-field', Y.FormField, [Y.WidgetChild], {
- _renderButtonNode : function () {
- var contentBox = this.get('contentBox'), bn;
-
- bn = Y.Node.create(Y.FormButton.NODE_TEMPLATE);
- contentBox.appendChild(bn);
- this._fieldNode = bn;
- },
- _syncLabelNode: function () {},
+ FIELD_TEMPLATE : '<button></button>',
+ LABEL_TEMPLATE: '',
_syncFieldNode : function () {
this._fieldNode.setAttrs({
@@ -1684,17 +1831,26 @@ Y.FormButton = Y.Base.create('button-field', Y.FormField, [Y.WidgetChild], {
return;
}
- var oc = this.get('onclick');
Y.Event.purgeElement(this._fieldNode, true, 'click');
- Y.on('click', Y.bind(oc.fn, oc.scope, true), this._fieldNode);
+ Y.on('click', Y.bind(this._promptConfirm, this), this._fieldNode);
},
- renderUI : function () {
- this._renderButtonNode();
+ _promptConfirm: function(event) {
+ event.preventDefault();
+ var message = this.get("message"),
+ onclick = this.get("onclick");
+
+ if (message) {
+ if (!this.get("confirm")(message)) {
+ return;
+ }
+ }
+ onclick.fn.apply(onclick.scope);
},
bindUI : function () {
this.after('onclickChange', Y.bind(this._setClickHandler, this, true));
+ this.after('disabledChange', this._syncDisabled, this);
this._setClickHandler();
}
}, {
@@ -1720,10 +1876,34 @@ Y.FormButton = Y.Base.create('button-field', Y.FormField, [Y.WidgetChild], {
val.argument = val.argument || {};
return val;
}
- }
- },
+ },
+
+ /**
+ * @attribute message
+ * @type String
+ * @default null
+ * @description Optional confirmation message to be passed to the
+ * confirm function.
+ */
+ message: {
+ validator : Y.Lang.isString,
+ value: null
+ },
- NODE_TEMPLATE : '<button></button>'
+ /**
+ * @attribute confirm
+ * @type Function
+ * @default null
+ * @description Optional confirmation function called when the button
+ * is clicked. It will be be passed the string set in the 'message'
+ * attribute. If it returns 'true' the the onclick handler will be
+ * called, otherwise it will be skipped.
+ */
+ confirm: {
+ validator : Y.Lang.isFunction,
+ value: null
+ }
+ }
});
/**
* @class FileField
@@ -1733,21 +1913,7 @@ Y.FormButton = Y.Base.create('button-field', Y.FormField, [Y.WidgetChild], {
* @description A file field node
*/
-Y.FileField = Y.Base.create('file-field', Y.FormField, [Y.WidgetChild], {
- _renderFieldNode : function () {
- var contentBox = this.get('contentBox'),
- field = contentBox.one('#' + this.get('id'));
-
- if (!field) {
- field = Y.Node.create(Y.FileField.FILE_INPUT_TEMPLATE);
- contentBox.appendChild(field);
- }
-
- this._fieldNode = field;
- }
-}, {
- FILE_INPUT_TEMPLATE : '<input type="file" />'
-});
+Y.FileField = Y.Base.create('file-field', Y.FormField, [Y.WidgetChild]);
/**
* @class SubmitButton
* @extends FormField
@@ -1766,8 +1932,8 @@ Y.SubmitButton = Y.Base.create('submit-button', Y.FormField, [Y.WidgetChild], {
* @description A reset button
*/
Y.ResetButton = Y.Base.create('reset-button', Y.FormField, [Y.WidgetChild], {
- _renderLabelNode: function() {}
+ LABEL_TEMPLATE: ''
});
-}, 'gallery-2011.02.23-19-01' ,{requires:['node', 'widget-base', 'widget-htmlparser', 'io-form', 'widget-parent', 'widget-child', 'base-build', 'substitute', 'io-upload-iframe']});
+}, 'gallery-2011.06.15-19-18' ,{requires:['node', 'widget-base', 'widget-htmlparser', 'io-form', 'widget-parent', 'widget-child', 'base-build', 'substitute', 'io-upload-iframe']});
View
10 build/gallery-formmgr/gallery-formmgr-debug.js
@@ -313,13 +313,13 @@ FormManager.getStatusPrecedence = function(
/**
* Compare two status values.
*
- * @method Y.FormManager.statusTakesPrecendence
+ * @method Y.FormManager.statusTakesPrecedence
* @static
* @param orig_status {String} The name of the original status value.
* @param new_status {String} The name of the new status value.
* @return {boolean} <code>true</code> if <code>new_status</code> takes precedence over <code>orig_status</code>
*/
-FormManager.statusTakesPrecendence = function(
+FormManager.statusTakesPrecedence = function(
/* string */ orig_status,
/* string */ new_status)
{
@@ -1084,7 +1084,7 @@ Y.extend(FormManager, Y.Plugin.Host,
e = Y.one(e);
var p = e.getAncestorByClassName(FormManager.row_marker_class);
- if (p && FormManager.statusTakesPrecendence(FormManager.getElementStatus(p), type))
+ if (p && FormManager.statusTakesPrecedence(FormManager.getElementStatus(p), type))
{
var f = p.all('.'+FormManager.field_marker_class);
if (f)
@@ -1107,7 +1107,7 @@ Y.extend(FormManager, Y.Plugin.Host,
}
var fieldset = e.getAncestorByTagName('fieldset');
- if (fieldset && FormManager.statusTakesPrecendence(FormManager.getElementStatus(fieldset), type))
+ if (fieldset && FormManager.statusTakesPrecedence(FormManager.getElementStatus(fieldset), type))
{
fieldset.removeClass(rowStatusPattern());
fieldset.addClass(FormManager.row_status_prefix + type);
@@ -1194,4 +1194,4 @@ Y.aggregate(FormManager, Y.FormManager);
Y.FormManager = FormManager;
-}, 'gallery-2011.06.08-20-04' ,{requires:['pluginhost-base','gallery-node-optimizations','gallery-formmgr-css-validation'], optional:['gallery-scrollintoview']});
+}, 'gallery-2011.06.15-19-18' ,{requires:['pluginhost-base','gallery-node-optimizations','gallery-formmgr-css-validation'], optional:['gallery-scrollintoview']});
View
4 build/gallery-formmgr/gallery-formmgr-min.js
@@ -1,2 +1,2 @@
-YUI.add("gallery-formmgr",function(d){function j(n,m){m=m||{};j.superclass.constructor.call(this,m);this.form_name=n;this.status_node=d.one(m.status_node);this.enabled=true;this.default_value_map=m.default_value_map;this.validation={fn:{},regex:{}};this.validation_msgs={};this.has_messages=false;this.has_errors=false;this.button_list=[];this.user_button_list=[];this.has_file_inputs=false;}var e="(?:^|\\s)(?:";var h=")(?:\\s|$)";j.row_marker_class="formmgr-row";j.field_marker_class="formmgr-field";j.status_marker_class="formmgr-message-text";j.status_none_class="formmgr-status-hidden";j.status_success_class="formmgr-status-success";j.status_failure_class="formmgr-status-failure";j.row_status_prefix="formmgr-has";var g;var l;var k;function b(){if(!g){g=j.status_success_class+"|"+j.status_failure_class;}return g;}function c(){if(!l){l=j.row_status_prefix+"([^\\s]+)";}return l;}function a(){if(!k){k=new RegExp(e+c()+h);}return k;}j.status_order=["error","warn","success","info"];j.getStatusPrecedence=function(m){for(var n=0;n<j.status_order.length;n++){if(m==j.status_order[n]){return n;}}return j.status_order.length;};j.statusTakesPrecendence=function(n,m){return(!n||j.getStatusPrecedence(m)<j.getStatusPrecedence(n));};j.getElementStatus=function(o){var n=d.one(o).get("className").match(a());return(n&&n.length>1?n[1]:false);};function f(m){if(d.Lang.isString(m)){return m.replace(/^#/,"");}else{if(m instanceof d.Node){return m.get("id");}else{return m.id;}}}j.cleanValues=function(q){var p=false;for(var n=0;n<q.length;n++){var m=q[n];var o=m.type&&m.type.toLowerCase();if(o=="file"){p=true;}else{if(o=="select-multiple"){}else{if(m.value&&!d.DOM.hasClass(m,"yiv-no-trim")){m.value=d.Lang.trim(m.value);}}}}return p;};function i(){var q=(this.button_list.length===0);for(var p=0;p<this.form.elements.length;p++){var t=this.form.elements[p];var o=t.tagName.toLowerCase();var r=(t.type?t.type.toLowerCase():null);if(q&&(r=="submit"||r=="reset"||o=="button")){this.button_list.push(t);}if(!t.name){continue;}var m=this.default_value_map[t.name];if(o=="input"&&r=="file"){t.value="";}else{if(d.Lang.isUndefined(m)){if(o=="input"&&(r=="password"||r=="text")){this.default_value_map[t.name]=t.value;}else{if(o=="input"&&r=="checkbox"){this.default_value_map[t.name]=(t.checked?t.value:"");}else{if(o=="input"&&r=="radio"){var s=this.form[t.name];if(s&&!s.length){this.default_value_map[t.name]=s.value;}else{if(s){this.default_value_map[t.name]=s[0].value;for(var n=0;n<s.length;n++){if(s[n].checked){this.default_value_map[t.name]=s[n].value;break;}}}}}else{if((o=="select"&&r=="select-one")||o=="textarea"){this.default_value_map[t.name]=t.value;}}}}}else{if(o=="input"&&(r=="password"||r=="text")){t.value=m;}else{if(o=="input"&&(r=="checkbox"||r=="radio")){t.checked=(t.value==m);}else{if(o=="select"&&r=="select-one"){t.value=m;if(t.selectedIndex>=0&&t.options[t.selectedIndex].value!==m.toString()){t.selectedIndex=-1;}}else{if(o=="textarea"){t.value=m;}}}}}}}}d.extend(j,d.Plugin.Host,{getForm:function(){if(!this.form){this.form=d.config.doc.forms[this.form_name];}return this.form;},hasFileInputs:function(){return this.has_file_inputs;},setStatusNode:function(m){this.status_node=d.one(m);},setDefaultValues:function(m){this.default_value_map=m;},setDefaultValue:function(n,m){this.default_value_map[n]=m;},saveCurrentValuesAsDefault:function(){this.default_value_map={};this.button_list=[];i.call(this);},setFunction:function(n,m){this.validation.fn[f(n)]=m;},setRegex:function(o,n,m){o=f(o);if(d.Lang.isString(n)){this.validation.regex[o]=new RegExp(n,m);}else{this.validation.regex[o]=n;}if(!this.validation_msgs[o]||!this.validation_msgs[o].regex){d.error(d.substitute("No error message provided for regex validation of {id}!",{id:o}),null,"FormManager");}},setErrorMessages:function(n,m){this.validation_msgs[f(n)]=m;},addErrorMessage:function(o,m,n){o=f(o);if(!this.validation_msgs[o]){this.validation_msgs[o]={};}this.validation_msgs[o][m]=n;},clearForm:function(){this.clearMessages();this.form.reset();this.postPopulateForm();},populateForm:function(){if(!this.default_value_map){this.default_value_map={};}this.clearMessages();i.call(this);this.postPopulateForm();},postPopulateForm:function(){},isChanged:function(){for(var o=0;o<this.form.elements.length;o++){var r=this.form.elements[o];if(!r.name){continue;}var p=(r.type?r.type.toLowerCase():null);var n=r.tagName.toLowerCase();var m=this.default_value_map[r.name];if(m===null||typeof m==="undefined"){m="";}if(n=="input"&&p=="file"){if(r.value){return true;}}else{if(n=="input"&&(p=="password"||p=="text"||p=="file")){if(r.value!=m){return true;}}else{if(n=="input"&&(p=="checkbox"||p=="radio")){var q=(r.value==m);if((q&&!r.checked)||(!q&&r.checked)){return true;}}else{if((n=="select"&&p=="select-one")||n=="textarea"){if(r.value!=m){return true;}}}}}}return false;},prepareForm:function(){this.getForm();if(!this.prePrepareForm.apply(this,arguments)){return false;}this.populateForm();return this.postPrepareForm.apply(this,arguments);},prePrepareForm:function(){return true;},postPrepareForm:function(){return true;},initFocus:function(){for(var o=0;o<this.form.elements.length;o++){var q=this.form.elements[o];if(q.disabled||q.offsetHeight===0){continue;}var m=q.tagName.toLowerCase();var p=(q.type?q.type.toLowerCase():null);if((m=="input"&&(p=="file"||p=="password"||p=="text"))||m=="textarea"){try{q.focus();}catch(n){}q.select();break;}}},validateForm:function(){this.clearMessages();var n=true;var s=this.form.elements;this.has_file_inputs=j.cleanValues(s);for(var o=0;o<s.length;o++){var t=s[o].id;var m=this.validation_msgs[t];var r=j.validateFromCSSData(s[o],m);if(r.error){this.displayMessage(s[o],r.error,"error");n=false;continue;}if(r.keepGoing){if(this.validation.regex[t]&&!this.validation.regex[t].test(s[o].value)){this.displayMessage(s[o],m?m.regex:null,"error");n=false;continue;}}var q=this.validation.fn[t];var p=this;if(d.Lang.isFunction(q)){}else{if(d.Lang.isString(q)){q=p[q];}else{if(q&&q.scope){p=q.scope;
-q=(d.Lang.isString(q.fn)?p[q.fn]:q.fn);}else{q=null;}}}if(q&&!q.call(p,this.form,d.one(s[o]))){n=false;continue;}}if(!this.postValidateForm(this.form)){n=false;}if(!n){this.notifyErrors();}return n;},postValidateForm:function(m){return true;},registerButton:function(m){var n={e:d.Lang.isString(m)||m.tagName?d.one(m):m};this.user_button_list.push(n);},isFormEnabled:function(){return this.enabled;},enableForm:function(){this.setFormEnabled(true);},disableForm:function(){this.setFormEnabled(false);},setFormEnabled:function(m){this.enabled=m;var o=!m;for(var n=0;n<this.button_list.length;n++){this.button_list[n].disabled=o;}for(n=0;n<this.user_button_list.length;n++){var p=this.user_button_list[n];p.e.set("disabled",o);}},hasMessages:function(){return this.has_messages;},hasErrors:function(){return this.has_errors;},getRowStatus:function(n){var m=d.one(n).getAncestorByClassName(j.row_marker_class,true);return j.getElementStatus(m);},clearMessages:function(){this.has_messages=false;this.has_errors=false;if(this.status_node){this.status_node.set("innerHTML","");this.status_node.replaceClass(b(),j.status_none_class);}for(var n=0;n<this.form.elements.length;n++){var r=this.form.elements[n];var m=r.tagName.toLowerCase();var o=(r.type?r.type.toLowerCase():null);if(m=="button"||o=="submit"||o=="reset"){continue;}var q=d.one(r).getAncestorByClassName(j.row_marker_class);if(q&&q.hasClass(c())){q.all("."+j.status_marker_class).set("innerHTML","");q.removeClass(c());q.all("."+j.field_marker_class).removeClass(c());}}d.one(this.form).all("fieldset").removeClass(c());},displayMessage:function(r,n,t,u){if(d.Lang.isUndefined(u)){u=true;}r=d.one(r);var m=r.getAncestorByClassName(j.row_marker_class);if(m&&j.statusTakesPrecendence(j.getElementStatus(m),t)){var q=m.all("."+j.field_marker_class);if(q){q.removeClass(c());}if(n){m.one("."+j.status_marker_class).set("innerHTML",n);}var o=j.row_status_prefix+t;m.replaceClass(c(),o);q=r.getAncestorByClassName(j.field_marker_class,true);if(q){q.replaceClass(c(),o);}var v=r.getAncestorByTagName("fieldset");if(v&&j.statusTakesPrecendence(j.getElementStatus(v),t)){v.removeClass(c());v.addClass(j.row_status_prefix+t);}if(!this.has_messages&&u){m.scrollIntoView();try{r.focus();}catch(s){}}this.has_messages=true;if(t=="error"){this.has_errors=true;}return true;}return false;},notifyErrors:function(){this.displayFormMessage(j.Strings.validation_error,true,false);},displayFormMessage:function(o,n,m){if(d.Lang.isUndefined(m)){m=true;}if(this.status_node){if(!this.status_node.innerHTML){this.status_node.replaceClass(j.status_none_class,(n?j.status_failure_class:j.status_success_class));this.status_node.set("innerHTML",o);}if(m){this.status_node.scrollIntoView();}}else{}}});d.aggregate(j,d.FormManager);d.FormManager=j;},"gallery-2011.06.08-20-04",{requires:["pluginhost-base","gallery-node-optimizations","gallery-formmgr-css-validation"],optional:["gallery-scrollintoview"]});
+YUI.add("gallery-formmgr",function(d){function j(n,m){m=m||{};j.superclass.constructor.call(this,m);this.form_name=n;this.status_node=d.one(m.status_node);this.enabled=true;this.default_value_map=m.default_value_map;this.validation={fn:{},regex:{}};this.validation_msgs={};this.has_messages=false;this.has_errors=false;this.button_list=[];this.user_button_list=[];this.has_file_inputs=false;}var e="(?:^|\\s)(?:";var h=")(?:\\s|$)";j.row_marker_class="formmgr-row";j.field_marker_class="formmgr-field";j.status_marker_class="formmgr-message-text";j.status_none_class="formmgr-status-hidden";j.status_success_class="formmgr-status-success";j.status_failure_class="formmgr-status-failure";j.row_status_prefix="formmgr-has";var g;var l;var k;function b(){if(!g){g=j.status_success_class+"|"+j.status_failure_class;}return g;}function c(){if(!l){l=j.row_status_prefix+"([^\\s]+)";}return l;}function a(){if(!k){k=new RegExp(e+c()+h);}return k;}j.status_order=["error","warn","success","info"];j.getStatusPrecedence=function(m){for(var n=0;n<j.status_order.length;n++){if(m==j.status_order[n]){return n;}}return j.status_order.length;};j.statusTakesPrecedence=function(n,m){return(!n||j.getStatusPrecedence(m)<j.getStatusPrecedence(n));};j.getElementStatus=function(o){var n=d.one(o).get("className").match(a());return(n&&n.length>1?n[1]:false);};function f(m){if(d.Lang.isString(m)){return m.replace(/^#/,"");}else{if(m instanceof d.Node){return m.get("id");}else{return m.id;}}}j.cleanValues=function(q){var p=false;for(var n=0;n<q.length;n++){var m=q[n];var o=m.type&&m.type.toLowerCase();if(o=="file"){p=true;}else{if(o=="select-multiple"){}else{if(m.value&&!d.DOM.hasClass(m,"yiv-no-trim")){m.value=d.Lang.trim(m.value);}}}}return p;};function i(){var q=(this.button_list.length===0);for(var p=0;p<this.form.elements.length;p++){var t=this.form.elements[p];var o=t.tagName.toLowerCase();var r=(t.type?t.type.toLowerCase():null);if(q&&(r=="submit"||r=="reset"||o=="button")){this.button_list.push(t);}if(!t.name){continue;}var m=this.default_value_map[t.name];if(o=="input"&&r=="file"){t.value="";}else{if(d.Lang.isUndefined(m)){if(o=="input"&&(r=="password"||r=="text")){this.default_value_map[t.name]=t.value;}else{if(o=="input"&&r=="checkbox"){this.default_value_map[t.name]=(t.checked?t.value:"");}else{if(o=="input"&&r=="radio"){var s=this.form[t.name];if(s&&!s.length){this.default_value_map[t.name]=s.value;}else{if(s){this.default_value_map[t.name]=s[0].value;for(var n=0;n<s.length;n++){if(s[n].checked){this.default_value_map[t.name]=s[n].value;break;}}}}}else{if((o=="select"&&r=="select-one")||o=="textarea"){this.default_value_map[t.name]=t.value;}}}}}else{if(o=="input"&&(r=="password"||r=="text")){t.value=m;}else{if(o=="input"&&(r=="checkbox"||r=="radio")){t.checked=(t.value==m);}else{if(o=="select"&&r=="select-one"){t.value=m;if(t.selectedIndex>=0&&t.options[t.selectedIndex].value!==m.toString()){t.selectedIndex=-1;}}else{if(o=="textarea"){t.value=m;}}}}}}}}d.extend(j,d.Plugin.Host,{getForm:function(){if(!this.form){this.form=d.config.doc.forms[this.form_name];}return this.form;},hasFileInputs:function(){return this.has_file_inputs;},setStatusNode:function(m){this.status_node=d.one(m);},setDefaultValues:function(m){this.default_value_map=m;},setDefaultValue:function(n,m){this.default_value_map[n]=m;},saveCurrentValuesAsDefault:function(){this.default_value_map={};this.button_list=[];i.call(this);},setFunction:function(n,m){this.validation.fn[f(n)]=m;},setRegex:function(o,n,m){o=f(o);if(d.Lang.isString(n)){this.validation.regex[o]=new RegExp(n,m);}else{this.validation.regex[o]=n;}if(!this.validation_msgs[o]||!this.validation_msgs[o].regex){d.error(d.substitute("No error message provided for regex validation of {id}!",{id:o}),null,"FormManager");}},setErrorMessages:function(n,m){this.validation_msgs[f(n)]=m;},addErrorMessage:function(o,m,n){o=f(o);if(!this.validation_msgs[o]){this.validation_msgs[o]={};}this.validation_msgs[o][m]=n;},clearForm:function(){this.clearMessages();this.form.reset();this.postPopulateForm();},populateForm:function(){if(!this.default_value_map){this.default_value_map={};}this.clearMessages();i.call(this);this.postPopulateForm();},postPopulateForm:function(){},isChanged:function(){for(var o=0;o<this.form.elements.length;o++){var r=this.form.elements[o];if(!r.name){continue;}var p=(r.type?r.type.toLowerCase():null);var n=r.tagName.toLowerCase();var m=this.default_value_map[r.name];if(m===null||typeof m==="undefined"){m="";}if(n=="input"&&p=="file"){if(r.value){return true;}}else{if(n=="input"&&(p=="password"||p=="text"||p=="file")){if(r.value!=m){return true;}}else{if(n=="input"&&(p=="checkbox"||p=="radio")){var q=(r.value==m);if((q&&!r.checked)||(!q&&r.checked)){return true;}}else{if((n=="select"&&p=="select-one")||n=="textarea"){if(r.value!=m){return true;}}}}}}return false;},prepareForm:function(){this.getForm();if(!this.prePrepareForm.apply(this,arguments)){return false;}this.populateForm();return this.postPrepareForm.apply(this,arguments);},prePrepareForm:function(){return true;},postPrepareForm:function(){return true;},initFocus:function(){for(var o=0;o<this.form.elements.length;o++){var q=this.form.elements[o];if(q.disabled||q.offsetHeight===0){continue;}var m=q.tagName.toLowerCase();var p=(q.type?q.type.toLowerCase():null);if((m=="input"&&(p=="file"||p=="password"||p=="text"))||m=="textarea"){try{q.focus();}catch(n){}q.select();break;}}},validateForm:function(){this.clearMessages();var n=true;var s=this.form.elements;this.has_file_inputs=j.cleanValues(s);for(var o=0;o<s.length;o++){var t=s[o].id;var m=this.validation_msgs[t];var r=j.validateFromCSSData(s[o],m);if(r.error){this.displayMessage(s[o],r.error,"error");n=false;continue;}if(r.keepGoing){if(this.validation.regex[t]&&!this.validation.regex[t].test(s[o].value)){this.displayMessage(s[o],m?m.regex:null,"error");n=false;continue;}}var q=this.validation.fn[t];var p=this;if(d.Lang.isFunction(q)){}else{if(d.Lang.isString(q)){q=p[q];}else{if(q&&q.scope){p=q.scope;
+q=(d.Lang.isString(q.fn)?p[q.fn]:q.fn);}else{q=null;}}}if(q&&!q.call(p,this.form,d.one(s[o]))){n=false;continue;}}if(!this.postValidateForm(this.form)){n=false;}if(!n){this.notifyErrors();}return n;},postValidateForm:function(m){return true;},registerButton:function(m){var n={e:d.Lang.isString(m)||m.tagName?d.one(m):m};this.user_button_list.push(n);},isFormEnabled:function(){return this.enabled;},enableForm:function(){this.setFormEnabled(true);},disableForm:function(){this.setFormEnabled(false);},setFormEnabled:function(m){this.enabled=m;var o=!m;for(var n=0;n<this.button_list.length;n++){this.button_list[n].disabled=o;}for(n=0;n<this.user_button_list.length;n++){var p=this.user_button_list[n];p.e.set("disabled",o);}},hasMessages:function(){return this.has_messages;},hasErrors:function(){return this.has_errors;},getRowStatus:function(n){var m=d.one(n).getAncestorByClassName(j.row_marker_class,true);return j.getElementStatus(m);},clearMessages:function(){this.has_messages=false;this.has_errors=false;if(this.status_node){this.status_node.set("innerHTML","");this.status_node.replaceClass(b(),j.status_none_class);}for(var n=0;n<this.form.elements.length;n++){var r=this.form.elements[n];var m=r.tagName.toLowerCase();var o=(r.type?r.type.toLowerCase():null);if(m=="button"||o=="submit"||o=="reset"){continue;}var q=d.one(r).getAncestorByClassName(j.row_marker_class);if(q&&q.hasClass(c())){q.all("."+j.status_marker_class).set("innerHTML","");q.removeClass(c());q.all("."+j.field_marker_class).removeClass(c());}}d.one(this.form).all("fieldset").removeClass(c());},displayMessage:function(r,n,t,u){if(d.Lang.isUndefined(u)){u=true;}r=d.one(r);var m=r.getAncestorByClassName(j.row_marker_class);if(m&&j.statusTakesPrecedence(j.getElementStatus(m),t)){var q=m.all("."+j.field_marker_class);if(q){q.removeClass(c());}if(n){m.one("."+j.status_marker_class).set("innerHTML",n);}var o=j.row_status_prefix+t;m.replaceClass(c(),o);q=r.getAncestorByClassName(j.field_marker_class,true);if(q){q.replaceClass(c(),o);}var v=r.getAncestorByTagName("fieldset");if(v&&j.statusTakesPrecedence(j.getElementStatus(v),t)){v.removeClass(c());v.addClass(j.row_status_prefix+t);}if(!this.has_messages&&u){m.scrollIntoView();try{r.focus();}catch(s){}}this.has_messages=true;if(t=="error"){this.has_errors=true;}return true;}return false;},notifyErrors:function(){this.displayFormMessage(j.Strings.validation_error,true,false);},displayFormMessage:function(o,n,m){if(d.Lang.isUndefined(m)){m=true;}if(this.status_node){if(!this.status_node.innerHTML){this.status_node.replaceClass(j.status_none_class,(n?j.status_failure_class:j.status_success_class));this.status_node.set("innerHTML",o);}if(m){this.status_node.scrollIntoView();}}else{}}});d.aggregate(j,d.FormManager);d.FormManager=j;},"gallery-2011.06.15-19-18",{requires:["pluginhost-base","gallery-node-optimizations","gallery-formmgr-css-validation"],optional:["gallery-scrollintoview"]});
View
10 build/gallery-formmgr/gallery-formmgr.js
@@ -313,13 +313,13 @@ FormManager.getStatusPrecedence = function(
/**
* Compare two status values.
*
- * @method Y.FormManager.statusTakesPrecendence
+ * @method Y.FormManager.statusTakesPrecedence
* @static
* @param orig_status {String} The name of the original status value.
* @param new_status {String} The name of the new status value.
* @return {boolean} <code>true</code> if <code>new_status</code> takes precedence over <code>orig_status</code>
*/
-FormManager.statusTakesPrecendence = function(
+FormManager.statusTakesPrecedence = function(
/* string */ orig_status,
/* string */ new_status)
{
@@ -1084,7 +1084,7 @@ Y.extend(FormManager, Y.Plugin.Host,
e = Y.one(e);
var p = e.getAncestorByClassName(FormManager.row_marker_class);
- if (p && FormManager.statusTakesPrecendence(FormManager.getElementStatus(p), type))
+ if (p && FormManager.statusTakesPrecedence(FormManager.getElementStatus(p), type))
{
var f = p.all('.'+FormManager.field_marker_class);
if (f)
@@ -1107,7 +1107,7 @@ Y.extend(FormManager, Y.Plugin.Host,
}
var fieldset = e.getAncestorByTagName('fieldset');
- if (fieldset && FormManager.statusTakesPrecendence(FormManager.getElementStatus(fieldset), type))
+ if (fieldset && FormManager.statusTakesPrecedence(FormManager.getElementStatus(fieldset), type))
{
fieldset.removeClass(rowStatusPattern());
fieldset.addClass(FormManager.row_status_prefix + type);
@@ -1193,4 +1193,4 @@ Y.aggregate(FormManager, Y.FormManager);
Y.FormManager = FormManager;
-}, 'gallery-2011.06.08-20-04' ,{requires:['pluginhost-base','gallery-node-optimizations','gallery-formmgr-css-validation'], optional:['gallery-scrollintoview']});
+}, 'gallery-2011.06.15-19-18' ,{requires:['pluginhost-base','gallery-node-optimizations','gallery-formmgr-css-validation'], optional:['gallery-scrollintoview']});
View
26 build/gallery-imagecropper/assets/gallery-imagecropper-core.css
@@ -0,0 +1,26 @@
+
+.yui3-imagecropper {
+ position: relative;
+}
+
+.yui3-imagecropper-mask, .yui3-imagecropper-resize-knob {
+ position: absolute;
+}
+
+.yui3-imagecropper-mask, .yui3-imagecropper-resize-mask {
+ width: 100%;
+ height: 100%;
+}
+
+.yui3-imagecropper-mask {
+ top: 0;
+ left: 0;
+ opacity: 0.5;
+ filter: alpha(opacity=50);
+ background: #000;
+}
+
+.yui3-imagecropper-resize-mask {
+ cursor: move;
+ border: 1px dashed #fff;
+}
View
708 build/gallery-imagecropper/gallery-imagecropper-debug.js
@@ -0,0 +1,708 @@
+YUI.add('gallery-imagecropper', function(Y) {
+
+
+/**
+ * @description <p>Creates an Image Cropper control.</p>
+ * @requires widget, resize, gallery-event-arrow
+ * @module gallery-imagecropper
+ */
+
+var Lang = Y.Lang,
+ isNumber = Lang.isNumber,
+ YArray = Y.Array,
+ getClassName = Y.ClassNameManager.getClassName,
+ IMAGE_CROPPER = 'imagecropper',
+ RESIZE = 'resize',
+ MASK = 'mask',
+ KNOB = 'knob',
+
+ _classNames = {
+ cropMask: getClassName(IMAGE_CROPPER, MASK),
+ resizeKnob: getClassName(IMAGE_CROPPER, RESIZE, KNOB),
+ resizeMask: getClassName(IMAGE_CROPPER, RESIZE, MASK)
+ },
+
+/**
+ * @constructor
+ * @class ImageCropper
+ * @description <p>Creates an Image Cropper control.</p>
+ * @extends Widget
+ * @param {Object} config Object literal containing configuration parameters.
+*/
+/**
+ * The identity of the widget.
+ *
+ * @property ImageCropper.NAME
+ * @type String
+ * @default 'imagecropper'
+ * @readOnly
+ * @protected
+ * @static
+ */
+ImageCropper = Y.Base.create('imagecropper', Y.Widget, [], {
+
+ CONTENT_TEMPLATE: '<img/>',
+
+ _toggleKeys: function (e) {
+ if (e.newVal) {
+ this._bindArrows();
+ } else {
+ this._unbindArrows();
+ }
+ },
+
+ _moveResizeKnob: function (e) {
+ e.preventDefault(); // prevent scroll in Firefox
+
+ var resizeKnob = this.get('resizeKnob'),
+ contentBox = this.get('contentBox'),
+
+ knobWidth = resizeKnob.get('offsetWidth'),
+ knobHeight = resizeKnob.get('offsetHeight'),
+
+ tick = e.shiftKey ? this.get('shiftKeyTick') : this.get('keyTick'),
+ direction = e.direction,
+
+ tickH = direction.indexOf('w') > -1 ? -tick : direction.indexOf('e') > -1 ? tick : 0,
+ tickV = direction.indexOf('n') > -1 ? -tick : direction.indexOf('s') > -1 ? tick : 0,
+
+ x = resizeKnob.getX() + tickH,
+ y = resizeKnob.getY() + tickV,
+
+ minX = contentBox.getX(),
+ minY = contentBox.getY(),
+
+ maxX = minX + contentBox.get('offsetWidth') - knobWidth,
+ maxY = minY + contentBox.get('offsetHeight') - knobHeight,
+
+ o;
+
+ if (x < minX) {
+ x = minX;
+ } else if (x > maxX) {
+ x = maxX;
+ }
+ if (y < minY) {
+ y = minY;
+ } else if (y > maxY) {
+ y = maxY;
+ }
+ resizeKnob.setXY([x, y]);
+
+ o = {
+ width: knobWidth,
+ height: knobHeight,
+ left: resizeKnob.get('offsetLeft'),
+ top: resizeKnob.get('offsetTop'),
+ sourceEvent: e.type
+ };
+
+ o[e.type + 'Event'] = e;
+ this.fire('crop:start', o);
+ this.fire('crop:crop', o);
+ this.fire('crop:end', o);
+
+ this._syncResizeMask();
+ },
+
+ _defCropMaskValueFn: function () {
+ return Y.Node.create(ImageCropper.CROP_MASK_TEMPLATE);
+ },
+
+ _defResizeKnobValueFn: function () {
+ return Y.Node.create(ImageCropper.RESIZE_KNOB_TEMPLATE);
+ },
+
+ _defResizeMaskValueFn: function () {
+ return Y.Node.create(ImageCropper.RESIZE_MASK_TEMPLATE);
+ },
+
+ _renderCropMask: function (boundingBox) {
+ var node = this.get('cropMask');
+ if (!node.inDoc()) {
+ boundingBox.append(node);
+ }
+ },
+
+ _renderResizeKnob: function (boundingBox) {
+ var node = this.get('resizeKnob');
+ if (!node.inDoc()) {
+ boundingBox.append(node);
+ }
+ node.setStyle('backgroundImage', 'url(' + this.get('source') + ')');
+ },
+
+ _renderResizeMask: function () {
+ var node = this.get('resizeMask');
+ if (!node.inDoc()) {
+ this.get('resizeKnob').append(node);
+ }
+ },
+
+ _handleSrcChange: function (e) {
+ this.get('contentBox').set('src', e.newVal);
+ this.get('cropResizeMask').setStyle('backgroundImage', 'url(' + e.newVal + ')');
+ },
+
+ _syncResizeKnob: function () {
+ var initialXY = this.get('initialXY');
+
+ this.get('resizeKnob').setStyles({
+ left: initialXY[0],
+ top: initialXY[1],
+ width: this.get('initWidth'),
+ height: this.get('initHeight')
+ });
+ },
+
+ _syncResizeMask: function () {
+ var resizeKnob = this.get('resizeKnob');
+ resizeKnob.setStyle('backgroundPosition', (-resizeKnob.get('offsetLeft')) + 'px ' + (-resizeKnob.get('offsetTop')) + 'px');
+ },
+
+ _syncResizeAttr: function (e) {
+ if (this._resize) {
+ this._resize.con.set(e.attrName, e.newVal);
+ }
+ },
+
+ _icEventProxy: function (target, ns, eventType) {
+ var sourceEvent = ns + ':' + eventType,
+ resizeKnob = this.get('resizeKnob');
+
+ target.on(sourceEvent, function (e) {
+
+ var o = {
+ width: resizeKnob.get('offsetWidth'),
+ height: resizeKnob.get('offsetHeight'),
+ left: resizeKnob.get('offsetLeft'),
+ top: resizeKnob.get('offsetTop')
+ };
+ o[ns + 'Event'] = e;
+
+ /**
+ * @event resize:start
+ * @description Relay of the Resize utility event.
+ * @param {EventFacade} event An Event Facade object with the following specific property added:
+ * <dl>
+ * <dt>resizeEvent</dt><dd>The Event Facade object provided by the Resize utility.</dd>
+ * </dl>
+ * @type {CustomEvent}
+ */
+ /**
+ * @event resize:resize
+ * @description Relay of the Resize utility event.
+ * @param {EventFacade} event An Event Facade object with the following specific property added:
+ * <dl>
+ * <dt>resizeEvent</dt><dd>The Event Facade object provided by the Resize utility.</dd>
+ * </dl>
+ * @type {CustomEvent}
+ */
+ /**
+ * @event resize:end
+ * @description Relay of the Resize utility event.
+ * @param {EventFacade} event An Event Facade object with the following specific property added:
+ * <dl>
+ * <dt>resizeEvent</dt><dd>The Event Facade object provided by the Resize utility.</dd>
+ * </dl>
+ * @type {CustomEvent}
+ */
+ /**
+ * @event drag:start
+ * @description Relay of the Drag utility event.
+ * @param {EventFacade} event An Event Facade object with the following specific property added:
+ * <dl>
+ * <dt>drag</dt><dd>The Event Facade object provided by the Drag utility.</dd>
+ * </dl>
+ * @type {CustomEvent}
+ */
+ /**
+ * @event drag:resize
+ * @description Relay of the Drag utility event.
+ * @param {EventFacade} event An Event Facade object with the following specific property added:
+ * <dl>
+ * <dt>drag</dt><dd>The Event Facade object provided by the Drag utility.</dd>
+ * </dl>
+ * @type {CustomEvent}
+ */
+ /**
+ * @event drag:end
+ * @description Relay of the Drag utility event.
+ * @param {EventFacade} event An Event Facade object with the following specific property added:
+ * <dl>
+ * <dt>drag</dt><dd>The Event Facade object provided by the Drag utility.</dd>
+ * </dl>
+ * @type {CustomEvent}
+ */
+ this.fire(sourceEvent, o);
+
+ o.sourceEvent = sourceEvent;
+
+ /**
+ * @event crop:start
+ * @description Fires at the start of a crop operation. Unifies drag:start and and resize:start.
+ * @param {EventFacade} event An Event Facade object with the following specific property added:
+ * <dl>
+ * <dt>left</dt><dd>The current X position of the crop area relative to the base image.</dd>
+ * <dt>top</dt><dd>The current Y position of the crop area relative to the base image.</dd>
+ * <dt>width</dt><dd>The new width of the crop area.</dd>
+ * <dt>height</dt><dd>The new height of the crop area.</dd>
+ * </dl>
+ * @type {CustomEvent}
+ */
+ /**
+ * @event crop:crop
+ * @description Fires every time the crop area changes. Unifies drag:drag and resize:resize.
+ * @param {EventFacade} event An Event Facade object with the following specific property added:
+ * <dl>
+ * <dt>left</dt><dd>The current X position of the crop area relative to the base image.</dd>
+ * <dt>top</dt><dd>The current Y position of the crop area relative to the base image.</dd>
+ * <dt>width</dt><dd>The new width of the crop area.</dd>
+ * <dt>height</dt><dd>The new height of the crop area.</dd>
+ * </dl>
+ * @type {CustomEvent}
+ */
+ /**
+ * @event crop:end
+ * @description Fires at the end of a crop operation. Unifies drag:end and resize:end.
+ * @param {EventFacade} event An Event Facade object with the following specific property added:
+ * <dl>
+ * <dt>left</dt><dd>The current X position of the crop area relative to the base image.</dd>
+ * <dt>top</dt><dd>The current Y position of the crop area relative to the base image.</dd>
+ * <dt>width</dt><dd>The new width of the crop area.</dd>
+ * <dt>height</dt><dd>The new height of the crop area.</dd>
+ * </dl>
+ * @type {CustomEvent}
+ */
+ this.fire('crop:' + (eventType == ns ? 'crop' : eventType), o);
+
+ }, this);
+ },
+
+ _bindArrows: function () {
+ this._arrowHandler = this.get('resizeKnob').on('arrow', this._moveResizeKnob, this);
+ },
+
+ _unbindArrows: function () {
+ if (this._arrowHandler) {
+ this._arrowHandler.detach();
+ }
+ },
+
+ _bindResize: function (resizeKnob, contentBox) {
+ var resize = this._resize = new Y.Resize({
+ node: resizeKnob
+ });
+ resize.on('resize:resize', this._syncResizeMask, this);
+ resize.plug(Y.Plugin.ResizeConstrained, {
+ constrain: contentBox,
+ minHeight: this.get('minHeight'),
+ minWidth: this.get('minWidth'),
+ preserveRatio: this.get('preserveRatio')
+ });
+ YArray.each(ImageCropper.RESIZE_EVENTS, Y.bind(this._icEventProxy, this, resize, 'resize'));
+ },
+
+ _bindDrag: function (resizeKnob, contentBox) {
+ var drag = this._drag = new Y.DD.Drag({
+ node: resizeKnob,
+ handles: [this.get('resizeMask')]
+ });
+ drag.on('drag:drag', this._syncResizeMask, this);
+ drag.plug(Y.Plugin.DDConstrained, {
+ constrain2node: contentBox
+ });
+ YArray.each(ImageCropper.DRAG_EVENTS, Y.bind(this._icEventProxy, this, drag, 'drag'));
+ },
+
+ initializer: function () {
+ this.set('initialXY', this.get('initialXY') || [10, 10]);
+ this.set('initWidth', this.get('initWidth'));
+ this.set('initHeight', this.get('initHeight'));
+
+ this.after('sourceChange', this._handleSrcChange);
+ this.after('useKeysChange', this._toggleKeys);
+
+ this._icHandlers = [];
+
+ YArray.each(ImageCropper.RESIZE_ATTRS, function (attr) {
+ this.after(attr + 'Change', this._syncResizeAttr);
+ }, this);
+ },
+
+ renderUI: function () {
+ var boundingBox = this.get('boundingBox');
+
+ this._renderCropMask(boundingBox);
+ this._renderResizeKnob(boundingBox);
+ this._renderResizeMask();
+ },
+
+ bindUI: function () {
+ var contentBox = this.get('contentBox'),
+ resizeKnob = this.get('resizeKnob');
+
+ this._icHandlers.push(
+ resizeKnob.on('focus', this._attachKeyBehavior, this),
+ resizeKnob.on('blur', this._detachKeyBehavior, this),
+ resizeKnob.on('mousedown', resizeKnob.focus, resizeKnob)
+ );
+
+ this._bindArrows();
+
+ this._bindResize(resizeKnob, contentBox);
+ this._bindDrag(resizeKnob, contentBox);
+ },
+
+ syncUI: function () {
+ this.get('contentBox').set('src', this.get('source'));
+
+ this._syncResizeKnob();
+ this._syncResizeMask();
+ },
+
+ /**
+ * Returns the coordinates needed to crop the image
+ *
+ * @method getCropCoords
+ * @return {Object} The top, left, height, width and image url of the image being cropped
+ */
+ getCropCoords: function () {
+ var resizeKnob = this.get('resizeKnob'),
+ result, xy;
+
+ if (resizeKnob.inDoc()) {
+ result = {
+ left: resizeKnob.get('offsetLeft'),
+ top: resizeKnob.get('offsetTop'),
+ width: resizeKnob.get('offsetWidth'),
+ height: resizeKnob.get('offsetHeight')
+ };
+ } else {
+ xy = this.get('initialXY');
+ result = {
+ left: xy[0],
+ top: xy[1],
+ width: this.get('initWidth'),
+ height: this.get('initHeight')
+ };
+ }
+ result.image = this.get('source');
+
+ return result;
+ },
+
+ /**
+ * Resets the crop element back to it's original position
+ *
+ * @method reset
+ * @chainable
+ */
+ reset: function () {
+ this.get('resizeKnob').setXY(this.get('initialXY')).setStyles({
+ width: this.get('initWidth'),
+ height: this.get('initHeight')
+ });
+ this._syncResizeMask();
+ return this;
+ },
+
+ destructor: function () {
+ if (this._resize) {
+ this._resize.destroy();
+ }
+ if (this._drag) {
+ this._drag.destroy();
+ }
+
+ YArray.each(this._icHandlers, function (handler) {
+ handler.detach();
+ });
+ this._unbindArrows();
+
+ this._drag = this._resize = null;
+ }
+
+}, {
+
+ /**
+ * Template that will contain the ImageCropper's mask.
+ *
+ * @property ImageCropper.CROP_MASK_TEMPLATE
+ * @type {HTML}
+ * @default &lt;div class="[...-mask]">&lt;/div>
+ * @protected
+ * @static
+ */
+ CROP_MASK_TEMPLATE: '<div class="' + _classNames.cropMask + '"></div>',
+ /**
+ * Template that will contain the ImageCropper's resize node.
+ *
+ * @property ImageCropper.RESIZE_KNOB_TEMPLATE
+ * @type {HTML}
+ * @default &lt;div class="[...-resize-knob]" tabindex="0">&lt;/div>
+ * @protected
+ * @static
+ */
+ RESIZE_KNOB_TEMPLATE: '<div class="' + _classNames.resizeKnob + '" tabindex="0"></div>',
+ /**
+ * Template that will contain the ImageCropper's resize mask.
+ *
+ * @property ImageCropper.RESIZE_MASK_TEMPLATE
+ * @type {HTML}
+ * @default &lt;div class="[...-resize-mask]">&lt;/div>
+ * @protected
+ * @static
+ */
+ RESIZE_MASK_TEMPLATE: '<div class="' + _classNames.resizeMask + '"></div>',
+
+ /**
+ * Array of events to relay from the Resize utility to the ImageCropper
+ *
+ * @property ImageCropper.RESIZE_EVENTS
+ * @type {Array}
+ * @private
+ * @static
+ */
+ RESIZE_EVENTS: ['start', 'resize', 'end'],
+ /**
+ * Array of attributes to relay from the ImageCropper to the Resize utility
+ *
+ * @property ImageCropper.RESIZE_ATTRS
+ * @type {Array}
+ * @private
+ * @static
+ */
+ RESIZE_ATTRS: ['minWidth', 'minHeight', 'preserveRatio'],
+ /**
+ * Array of events to relay from the Drag utility to the ImageCropper
+ *
+ * @property ImageCropper.DRAG_EVENTS
+ * @type {Array}
+ * @private
+ * @static
+ */
+ DRAG_EVENTS: ['start', 'drag', 'end'],
+
+ HTML_PARSER: {
+
+ source: function (srcNode) {
+ return srcNode.get('src');
+ },
+
+ cropMask: '.' + _classNames.cropMask,
+ resizeKnob: '.' + _classNames.resizeKnob,
+ resizeMask: '.' + _classNames.resizeMask
+
+ },
+
+ /**
+ * Static property used to define the default attribute configuration of
+ * the Widget.
+ *
+ * @property ImageCropper.ATTRS
+ * @type {Object}
+ * @protected
+ * @static
+ */
+ ATTRS: {
+
+ /**
+ * The source attribute of the image we are cropping
+ *
+ * @attribute source
+ * @type {String}
+ */
+ source: { value: '' },
+
+ /**
+ * The resize mask used to highlight the crop area
+ *
+ * @attribute resizeMask
+ * @type {Node}
+ */
+ resizeMask: {
+ setter: function (node) {