<commit_before>(function( jQuery ) {

var rclass = /[\n\t\r]/g,
	rspaces = /\s+/,
	rreturn = /\r/g,
	rtype = /^(?:button|input)$/i,
	rfocusable = /^(?:button|input|object|select|textarea)$/i,
	rclickable = /^a(?:rea)?$/i,
	rradiocheck = /^(?:radio|checkbox)$/i;

jQuery.fn.extend({
	attr: function( name, value ) {
		return jQuery.access( this, name, value, true, jQuery.attr );
	},

	removeAttr: function( name ) {
		return this.each(function() {
			if ( this.nodeType === 1 ) {
				jQuery.removeAttr( this, name );
			}
		});
	},

	prop: function( name, value ) {
		return jQuery.access( this, name, value, true, jQuery.prop );
	},

	removeProp: function( name ) {
		return this.each(function() {
			// try/catch handles cases where IE balks (such as removing a property on window)
			try {
				this[ name ] = undefined;
				delete this[ name ];
			} catch( e ) {}
		});
	},

	addClass: function( value ) {
		if ( jQuery.isFunction( value ) ) {
			return this.each(function(i) {
				var self = jQuery(this);
				self.addClass( value.call(this, i, self.attr("class") || "") );
			});
		}

		if ( value && typeof value === "string" ) {
			var classNames = (value || "").split( rspaces );

			for ( var i = 0, l = this.length; i < l; i++ ) {
				var elem = this[i];

				if ( elem.nodeType === 1 ) {
					if ( !elem.className ) {
						elem.className = value;

					} else {
						var className = " " + elem.className + " ",
							setClass = elem.className;

						for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
							if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
								setClass += " " + classNames[c];
							}
						}
						elem.className = jQuery.trim( setClass );
					}
				}
			}
		}

		return this;
	},

	removeClass: function( value ) {
		if ( jQuery.isFunction(value) ) {
			return this.each(function(i) {
				var self = jQuery(this);
				self.removeClass( value.call(this, i, self.attr("class")) );
			});
		}

		if ( (value && typeof value === "string") || value === undefined ) {
			var classNames = (value || "").split( rspaces );

			for ( var i = 0, l = this.length; i < l; i++ ) {
				var elem = this[i];

				if ( elem.nodeType === 1 && elem.className ) {
					if ( value ) {
						var className = (" " + elem.className + " ").replace(rclass, " ");
						for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
							className = className.replace(" " + classNames[c] + " ", " ");
						}
						elem.className = jQuery.trim( className );

					} else {
						elem.className = "";
					}
				}
			}
		}

		return this;
	},

	toggleClass: function( value, stateVal ) {
		var type = typeof value,
			isBool = typeof stateVal === "boolean";

		if ( jQuery.isFunction( value ) ) {
			return this.each(function(i) {
				var self = jQuery(this);
				self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
			});
		}

		return this.each(function() {
			if ( type === "string" ) {
				// toggle individual class names
				var className,
					i = 0,
					self = jQuery( this ),
					state = stateVal,
					classNames = value.split( rspaces );

				while ( (className = classNames[ i++ ]) ) {
					// check each className given, space seperated list
					state = isBool ? state : !self.hasClass( className );
					self[ state ? "addClass" : "removeClass" ]( className );
				}

			} else if ( type === "undefined" || type === "boolean" ) {
				if ( this.className ) {
					// store className if set
					jQuery._data( this, "__className__", this.className );
				}

				// toggle whole className
				this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
			}
		});
	},

	hasClass: function( selector ) {
		var className = " " + selector + " ";
		for ( var i = 0, l = this.length; i < l; i++ ) {
			if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
				return true;
			}
		}

		return false;
	},

	val: function( value ) {
		if ( !arguments.length ) {
			var elem = this[0];

			if ( elem ) {
				if ( jQuery.nodeName( elem, "option" ) ) {
					// attributes.value is undefined in Blackberry 4.7 but
					// uses .value. See #6932
					var val = elem.attributes.value;
					return !val || val.specified ? elem.value : elem.text;
				}

				// We need to handle select boxes special
				if ( jQuery.nodeName( elem, "select" ) ) {
					var index = elem.selectedIndex,
						values = [],
						options = elem.options,
						one = elem.type === "select-one";

					// Nothing was selected
					if ( index < 0 ) {
						return null;
					}

					// Loop through all the selected options
					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
						var option = options[ i ];

						// Don't return options that are disabled or in a disabled optgroup
						if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
								(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {

							// Get the specific value for the option
							value = jQuery(option).val();

							// We don't need an array for one selects
							if ( one ) {
								return value;
							}

							// Multi-Selects return an array
							values.push( value );
						}
					}

					// Fixes Bug #2551 -- select.val() broken in IE after form.reset()
					if ( one && !values.length && options.length ) {
						return jQuery( options[ index ] ).val();
					}

					return values;
				}

				// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
				if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
					return elem.getAttribute("value") === null ? "on" : elem.value;
				}

				// Everything else, we just grab the value
				return (elem.value || "").replace(rreturn, "");

			}

			return undefined;
		}

		var isFunction = jQuery.isFunction(value);

		return this.each(function(i) {
			var self = jQuery(this), val = value;

			if ( this.nodeType !== 1 ) {
				return;
			}

			if ( isFunction ) {
				val = value.call(this, i, self.val());
			}

			// Treat null/undefined as ""; convert numbers to string
			if ( val == null ) {
				val = "";
			} else if ( typeof val === "number" ) {
				val += "";
			} else if ( jQuery.isArray(val) ) {
				val = jQuery.map(val, function (value) {
					return value == null ? "" : value + "";
				});
			}

			if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
				this.checked = jQuery.inArray( self.val(), val ) >= 0;

			} else if ( jQuery.nodeName( this, "select" ) ) {
				var values = jQuery.makeArray(val);

				jQuery( "option", this ).each(function() {
					this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
				});

				if ( !values.length ) {
					this.selectedIndex = -1;
				}

			} else {
				this.value = val;
			}
		});
	}
});

jQuery.extend({
	attrFn: {
		val: true,
		css: true,
		html: true,
		text: true,
		data: true,
		width: true,
		height: true,
		offset: true
	},

	attrFix: {},

	attr: function( elem, name, value, pass ) {

		// don't get/set attributes on text, comment and attribute nodes
		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || elem.nodeType === 2 ) {
			return undefined;
		}

		if ( pass && name in jQuery.attrFn ) {
			return jQuery(elem)[name](value);
		}

		var ret,
			notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
			hooks;

		// Normalize the name if needed
		name = notxml && jQuery.attrFix[ name ] || name;

		hooks = jQuery.attrHooks[ name ];

		if ( value !== undefined ) {

			if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value )) !== undefined ) {
				return ret;

			} else if ( value === null ) {
				jQuery.removeAttr( elem, name );
				return undefined;

			} else {
				elem.setAttribute( name, value );
				return value;
			}

		} else {

			if ( hooks && "get" in hooks && notxml && ((ret = hooks.get( elem )) !== undefined || name === "tabIndex") ) {
				return ret;

			} else {
				var attr = elem.getAttribute( name );

				// Non-existent attributes return null, we normalize to undefined
				return attr === null || attr === "undefined" || attr === "null" ? undefined : attr;
			}
		}
	},

	removeAttr: function( elem, name ) {
		name = jQuery.attrFix[ name ] || name;

		jQuery.support.getSetAttribute ? elem.removeAttribute( name ) :
			// set property to null if getSetAttribute not supported (IE6-7)
			// setting className to null makes the class "null"
			name === "className" ? elem.className = "" : elem.setAttribute( name, null );
	},

	attrHooks: {
		type: {
			set: function( elem, value ) {
				// We can't allow the type property to be changed (since it causes problems in IE)
				if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
					jQuery.error( "type property can't be changed" );
				}
			}
		}
	},

	// TODO: Check to see if we really need any here.
	propFix: {

	},

	prop: function( elem, name, value ) {

		// don't get/set properties on text, comment and attribute nodes
		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || elem.nodeType === 2 ) {
			return undefined;
		}

		var ret, hooks, notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem );

		// Try to normalize/fix the name
		name = notxml && jQuery.propFix[ name ] || name;

		hooks = jQuery.propHooks[ name ];

		if ( value !== undefined ) {
			if ( hooks && "set" in hooks && (ret = hooks.set( elem, value )) !== undefined ) {
				return ret;

			} else {
				return (elem[ name ] = value);
			}

		} else {
			if ( hooks && "get" in hooks && (ret = hooks.get( elem )) !== undefined ) {
				return ret;

			} else {
				return elem[ name ];
			}
		}
	},

	propHooks: {}
});

// IE6/7 do not support getting/setting some attributes with get/setAttribute
if ( !jQuery.support.getSetAttribute ) {
	jQuery.attrFix = jQuery.extend( jQuery.attrFix, {
		"for": "htmlFor",
		"class": "className",
		readonly: "readOnly",
		maxlength: "maxLength",
		cellspacing: "cellSpacing",
		rowspan: "rowSpan",
		colspan: "colSpan",
		tabindex: "tabIndex",
		usemap: "useMap",
		frameborder: "frameBorder"
	});

	// Action attribute in ie6/7 returns form objects
	jQuery.attrHooks.action = jQuery.extend( jQuery.attrHooks.action, {
		get: function( elem ) {
			return elem.nodeName === "FORM" ? elem.getAttributeNode("action").nodeValue : elem.getAttribute("action");
		},
		set: function( elem, value ) {
			elem.nodeName === "FORM" ? elem.getAttributeNode("action").nodeValue = value : elem.setAttribute("action", value);
			return value;
		}
	});
}

// Remove certain attrs if set to false
jQuery.each([ "selected", "checked", "readonly", "disabled" ], function( i, name ) {
	name = jQuery.attrFix[ name ] || name;

	jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
		set: function( elem, value ) {
			if ( !value ) { // '', undefined, false, null will remove attr
				jQuery.removeAttr( elem, name );
				return false;
			}

			elem.setAttribute( name, value );
			return value;
		}
	});
});

// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
jQuery.attrHooks[ jQuery.attrFix.tabindex || "tabindex" ] = {
	get: function( elem ) {
		var attributeNode = elem.getAttributeNode("tabIndex");

		return attributeNode && attributeNode.specified ?
			parseInt( attributeNode.value, 10 ) :
			rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
				0 :
				undefined;
	}
};

// Some attributes require a special call on IE
if ( !jQuery.support.hrefNormalized ) {
	jQuery.each([ "href", "src", "style" ], function( i, name ) {
		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
			get: function( elem ) {
				return elem.getAttribute( name, 2 );
			}
		});
	});
}

if ( !jQuery.support.style ) {
	jQuery.attrHooks.style = {
		get: function( elem ) {
			return elem.style.cssText;
		},

		set: function( elem, value ) {
			return (elem.style.cssText = "" + value);
		}
	};
}

// Safari mis-reports the default selected property of an option
// Accessing the parent's selectedIndex property fixes it
if ( !jQuery.support.optSelected ) {

	jQuery.propHooks.selected = {
		get: function( elem ) {
			var parent = elem.parentNode;

			if ( parent ) {
				parent.selectedIndex;

				// TODO: We may need an attrHook for selected that simply defers to prop?
				// The attr is undefined if the option is created with createElement and not on the DOM

				// Make sure that it also works with optgroups, see #5701
				if ( parent.parentNode ) {
					parent.parentNode.selectedIndex;
				}
			}
		}
	};
}

})( jQuery );<commit_msg>Don't use extend when setting the action attrHook for IE6/7<commit_after>(function( jQuery ) {

var rclass = /[\n\t\r]/g,
	rspaces = /\s+/,
	rreturn = /\r/g,
	rtype = /^(?:button|input)$/i,
	rfocusable = /^(?:button|input|object|select|textarea)$/i,
	rclickable = /^a(?:rea)?$/i,
	rradiocheck = /^(?:radio|checkbox)$/i;

jQuery.fn.extend({
	attr: function( name, value ) {
		return jQuery.access( this, name, value, true, jQuery.attr );
	},

	removeAttr: function( name ) {
		return this.each(function() {
			if ( this.nodeType === 1 ) {
				jQuery.removeAttr( this, name );
			}
		});
	},

	prop: function( name, value ) {
		return jQuery.access( this, name, value, true, jQuery.prop );
	},

	removeProp: function( name ) {
		return this.each(function() {
			// try/catch handles cases where IE balks (such as removing a property on window)
			try {
				this[ name ] = undefined;
				delete this[ name ];
			} catch( e ) {}
		});
	},

	addClass: function( value ) {
		if ( jQuery.isFunction( value ) ) {
			return this.each(function(i) {
				var self = jQuery(this);
				self.addClass( value.call(this, i, self.attr("class") || "") );
			});
		}

		if ( value && typeof value === "string" ) {
			var classNames = (value || "").split( rspaces );

			for ( var i = 0, l = this.length; i < l; i++ ) {
				var elem = this[i];

				if ( elem.nodeType === 1 ) {
					if ( !elem.className ) {
						elem.className = value;

					} else {
						var className = " " + elem.className + " ",
							setClass = elem.className;

						for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
							if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
								setClass += " " + classNames[c];
							}
						}
						elem.className = jQuery.trim( setClass );
					}
				}
			}
		}

		return this;
	},

	removeClass: function( value ) {
		if ( jQuery.isFunction(value) ) {
			return this.each(function(i) {
				var self = jQuery(this);
				self.removeClass( value.call(this, i, self.attr("class")) );
			});
		}

		if ( (value && typeof value === "string") || value === undefined ) {
			var classNames = (value || "").split( rspaces );

			for ( var i = 0, l = this.length; i < l; i++ ) {
				var elem = this[i];

				if ( elem.nodeType === 1 && elem.className ) {
					if ( value ) {
						var className = (" " + elem.className + " ").replace(rclass, " ");
						for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
							className = className.replace(" " + classNames[c] + " ", " ");
						}
						elem.className = jQuery.trim( className );

					} else {
						elem.className = "";
					}
				}
			}
		}

		return this;
	},

	toggleClass: function( value, stateVal ) {
		var type = typeof value,
			isBool = typeof stateVal === "boolean";

		if ( jQuery.isFunction( value ) ) {
			return this.each(function(i) {
				var self = jQuery(this);
				self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
			});
		}

		return this.each(function() {
			if ( type === "string" ) {
				// toggle individual class names
				var className,
					i = 0,
					self = jQuery( this ),
					state = stateVal,
					classNames = value.split( rspaces );

				while ( (className = classNames[ i++ ]) ) {
					// check each className given, space seperated list
					state = isBool ? state : !self.hasClass( className );
					self[ state ? "addClass" : "removeClass" ]( className );
				}

			} else if ( type === "undefined" || type === "boolean" ) {
				if ( this.className ) {
					// store className if set
					jQuery._data( this, "__className__", this.className );
				}

				// toggle whole className
				this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
			}
		});
	},

	hasClass: function( selector ) {
		var className = " " + selector + " ";
		for ( var i = 0, l = this.length; i < l; i++ ) {
			if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
				return true;
			}
		}

		return false;
	},

	val: function( value ) {
		if ( !arguments.length ) {
			var elem = this[0];

			if ( elem ) {
				if ( jQuery.nodeName( elem, "option" ) ) {
					// attributes.value is undefined in Blackberry 4.7 but
					// uses .value. See #6932
					var val = elem.attributes.value;
					return !val || val.specified ? elem.value : elem.text;
				}

				// We need to handle select boxes special
				if ( jQuery.nodeName( elem, "select" ) ) {
					var index = elem.selectedIndex,
						values = [],
						options = elem.options,
						one = elem.type === "select-one";

					// Nothing was selected
					if ( index < 0 ) {
						return null;
					}

					// Loop through all the selected options
					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
						var option = options[ i ];

						// Don't return options that are disabled or in a disabled optgroup
						if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
								(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {

							// Get the specific value for the option
							value = jQuery(option).val();

							// We don't need an array for one selects
							if ( one ) {
								return value;
							}

							// Multi-Selects return an array
							values.push( value );
						}
					}

					// Fixes Bug #2551 -- select.val() broken in IE after form.reset()
					if ( one && !values.length && options.length ) {
						return jQuery( options[ index ] ).val();
					}

					return values;
				}

				// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
				if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
					return elem.getAttribute("value") === null ? "on" : elem.value;
				}

				// Everything else, we just grab the value
				return (elem.value || "").replace(rreturn, "");

			}

			return undefined;
		}

		var isFunction = jQuery.isFunction(value);

		return this.each(function(i) {
			var self = jQuery(this), val = value;

			if ( this.nodeType !== 1 ) {
				return;
			}

			if ( isFunction ) {
				val = value.call(this, i, self.val());
			}

			// Treat null/undefined as ""; convert numbers to string
			if ( val == null ) {
				val = "";
			} else if ( typeof val === "number" ) {
				val += "";
			} else if ( jQuery.isArray(val) ) {
				val = jQuery.map(val, function (value) {
					return value == null ? "" : value + "";
				});
			}

			if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
				this.checked = jQuery.inArray( self.val(), val ) >= 0;

			} else if ( jQuery.nodeName( this, "select" ) ) {
				var values = jQuery.makeArray(val);

				jQuery( "option", this ).each(function() {
					this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
				});

				if ( !values.length ) {
					this.selectedIndex = -1;
				}

			} else {
				this.value = val;
			}
		});
	}
});

jQuery.extend({
	attrFn: {
		val: true,
		css: true,
		html: true,
		text: true,
		data: true,
		width: true,
		height: true,
		offset: true
	},

	attrFix: {},

	attr: function( elem, name, value, pass ) {

		// don't get/set attributes on text, comment and attribute nodes
		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || elem.nodeType === 2 ) {
			return undefined;
		}

		if ( pass && name in jQuery.attrFn ) {
			return jQuery(elem)[name](value);
		}

		var ret,
			notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
			hooks;

		// Normalize the name if needed
		name = notxml && jQuery.attrFix[ name ] || name;

		hooks = jQuery.attrHooks[ name ];

		if ( value !== undefined ) {

			if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value )) !== undefined ) {
				return ret;

			} else if ( value === null ) {
				jQuery.removeAttr( elem, name );
				return undefined;

			} else {
				elem.setAttribute( name, value );
				return value;
			}

		} else {

			if ( hooks && "get" in hooks && notxml && ((ret = hooks.get( elem )) !== undefined || name === "tabIndex") ) {
				return ret;

			} else {
				var attr = elem.getAttribute( name );

				// Non-existent attributes return null, we normalize to undefined
				return attr === null || attr === "undefined" || attr === "null" ? undefined : attr;
			}
		}
	},

	removeAttr: function( elem, name ) {
		name = jQuery.attrFix[ name ] || name;

		jQuery.support.getSetAttribute ? elem.removeAttribute( name ) :
			// set property to null if getSetAttribute not supported (IE6-7)
			// setting className to null makes the class "null"
			name === "className" ? elem.className = "" : elem.setAttribute( name, null );
	},

	attrHooks: {
		type: {
			set: function( elem, value ) {
				// We can't allow the type property to be changed (since it causes problems in IE)
				if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
					jQuery.error( "type property can't be changed" );
				}
			}
		}
	},

	// TODO: Check to see if we really need any here.
	propFix: {

	},

	prop: function( elem, name, value ) {

		// don't get/set properties on text, comment and attribute nodes
		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || elem.nodeType === 2 ) {
			return undefined;
		}

		var ret, hooks, notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem );

		// Try to normalize/fix the name
		name = notxml && jQuery.propFix[ name ] || name;

		hooks = jQuery.propHooks[ name ];

		if ( value !== undefined ) {
			if ( hooks && "set" in hooks && (ret = hooks.set( elem, value )) !== undefined ) {
				return ret;

			} else {
				return (elem[ name ] = value);
			}

		} else {
			if ( hooks && "get" in hooks && (ret = hooks.get( elem )) !== undefined ) {
				return ret;

			} else {
				return elem[ name ];
			}
		}
	},

	propHooks: {}
});

// IE6/7 do not support getting/setting some attributes with get/setAttribute
if ( !jQuery.support.getSetAttribute ) {
	jQuery.attrFix = jQuery.extend( jQuery.attrFix, {
		"for": "htmlFor",
		"class": "className",
		readonly: "readOnly",
		maxlength: "maxLength",
		cellspacing: "cellSpacing",
		rowspan: "rowSpan",
		colspan: "colSpan",
		tabindex: "tabIndex",
		usemap: "useMap",
		frameborder: "frameBorder"
	});

	// Action attribute in ie6/7 returns form objects
	jQuery.attrHooks.action = {
		get: function( elem ) {
			return elem.nodeName === "FORM" ? elem.getAttributeNode("action").nodeValue : elem.getAttribute("action");
		},
		set: function( elem, value ) {
			elem.nodeName === "FORM" ? elem.getAttributeNode("action").nodeValue = value : elem.setAttribute("action", value);
			return value;
		}
	};
}

// Remove certain attrs if set to false
jQuery.each([ "selected", "checked", "readonly", "disabled" ], function( i, name ) {
	name = jQuery.attrFix[ name ] || name;

	jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
		set: function( elem, value ) {
			if ( !value ) { // '', undefined, false, null will remove attr
				jQuery.removeAttr( elem, name );
				return false;
			}

			elem.setAttribute( name, value );
			return value;
		}
	});
});

// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
jQuery.attrHooks[ jQuery.attrFix.tabindex || "tabindex" ] = {
	get: function( elem ) {
		var attributeNode = elem.getAttributeNode("tabIndex");

		return attributeNode && attributeNode.specified ?
			parseInt( attributeNode.value, 10 ) :
			rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
				0 :
				undefined;
	}
};

// Some attributes require a special call on IE
if ( !jQuery.support.hrefNormalized ) {
	jQuery.each([ "href", "src", "style" ], function( i, name ) {
		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
			get: function( elem ) {
				return elem.getAttribute( name, 2 );
			}
		});
	});
}

if ( !jQuery.support.style ) {
	jQuery.attrHooks.style = {
		get: function( elem ) {
			return elem.style.cssText;
		},

		set: function( elem, value ) {
			return (elem.style.cssText = "" + value);
		}
	};
}

// Safari mis-reports the default selected property of an option
// Accessing the parent's selectedIndex property fixes it
if ( !jQuery.support.optSelected ) {

	jQuery.propHooks.selected = {
		get: function( elem ) {
			var parent = elem.parentNode;

			if ( parent ) {
				parent.selectedIndex;

				// TODO: We may need an attrHook for selected that simply defers to prop?
				// The attr is undefined if the option is created with createElement and not on the DOM

				// Make sure that it also works with optgroups, see #5701
				if ( parent.parentNode ) {
					parent.parentNode.selectedIndex;
				}
			}
		}
	};
}

})( jQuery );<|endoftext|>


<commit_before>import hbs from 'htmlbars-inline-precompile';

export default {
  title: 'Components|Gutter Menu',
};

export let Standard = () => {
  return {
    template: hbs`

Gutter menu

Places

Place One

Place Two

Features

Feature One

Feature Two

      `,
  };
};

export let RichComponents = () => {
  return {
    template: hbs`

Gutter navigation with rich components

Places

                    <PowerSelect @selected={{or selection "One"}} @options={{array "One" "Two" "Three"}} @onChange={{action (mut selection)}} as |option|>
                      {{option}}
                    </PowerSelect>

Place One

Place Two

Features

Feature One

Feature Two

In order to keep the gutter navigation streamlined and easy to navigation, rich components should be avoided when possible. When not possible, they should be kept near the top.

      `,
  };
};

export let ManyItems = () => {
  return {
    template: hbs`

Hypothetical gutter navigation with many items

Places

                {{#each (array "One Two" "Three" "Four" "Five" "Six" "Seven") as |item|}}

Place {{item}}

                {{/each}}

Features

                {{#each (array "One Two" "Three" "Four" "Five" "Six" "Seven") as |item|}}

Feature {{item}}

                {{/each}}

Other

The one that didn't fit in

Things

                {{#each (array "One Two" "Three" "Four" "Five" "Six" "Seven") as |item|}}

Thing {{item}}

                {{/each}}

There will only ever be one gutter menu in the Nomad UI, but it helps to imagine a situation where there are many navigation items in the gutter.

      `,
  };
};

export let IconItems = () => {
  return {
    template: hbs`

Hypothetical gutter navigation with icon items

Places

{{x-icon "clock"}} Place One

{{x-icon "history"}} Place Two

Features

{{x-icon "warning"}} Feature One

{{x-icon "media-pause"}} Feature Two

In the future, the gutter menu may have icons.

      `,
  };
};

export let Global = () => {
  return {
    template: hbs`

Global gutter navigation

          <GutterMenu>
            {{!-- Page content here --}}
          </GutterMenu>

Since there will only ever be one gutter menu in the UI, it makes sense to express the menu as a singleton component. This is what that singleton component looks like.

Note: Normally the gutter menu is rendered within a page layout and is fixed position. The columns shown in this example are only to imitate the actual width without applying fixed positioning.

      `,
  };
};
<commit_msg>Add new gutter menu tag pattern to Storybook<commit_after>import hbs from 'htmlbars-inline-precompile';

export default {
  title: 'Components|Gutter Menu',
};

export let Standard = () => {
  return {
    template: hbs`

Gutter menu

Places

Place One

Place Two

Features

Feature One

Feature Two

      `,
  };
};

export let RichComponents = () => {
  return {
    template: hbs`

Gutter navigation with rich components

Places

                    <PowerSelect @selected={{or selection "One"}} @options={{array "One" "Two" "Three"}} @onChange={{action (mut selection)}} as |option|>
                      {{option}}
                    </PowerSelect>

Place One

Place Two

Features

Feature One

Feature Two

In order to keep the gutter navigation streamlined and easy to navigation, rich components should be avoided when possible. When not possible, they should be kept near the top.

      `,
  };
};

export let ManyItems = () => {
  return {
    template: hbs`

Hypothetical gutter navigation with many items

Places

                {{#each (array "One Two" "Three" "Four" "Five" "Six" "Seven") as |item|}}

Place {{item}}

                {{/each}}

Features

                {{#each (array "One Two" "Three" "Four" "Five" "Six" "Seven") as |item|}}

Feature {{item}}

                {{/each}}

Other

The one that didn't fit in

Things

                {{#each (array "One Two" "Three" "Four" "Five" "Six" "Seven") as |item|}}

Thing {{item}}

                {{/each}}

There will only ever be one gutter menu in the Nomad UI, but it helps to imagine a situation where there are many navigation items in the gutter.

      `,
  };
};

export let IconItems = () => {
  return {
    template: hbs`

Hypothetical gutter navigation with icon items

Places

{{x-icon "clock"}} Place One

{{x-icon "history"}} Place Two

Features

{{x-icon "warning"}} Feature One

{{x-icon "media-pause"}} Feature Two

In the future, the gutter menu may have icons.

      `,
  };
};

export let TaggedItems = () => {
  return {
    template: hbs`

Hypothetical gutter navigation with icon items

Places

Place One Beta

{{x-icon "history"}} Place Two

Features

{{x-icon "warning"}} Feature One

{{x-icon "media-pause"}} Feature Two 3

Tags can be used to denote beta features or low-priority notifications.

    `,
  };
};

export let Global = () => {
  return {
    template: hbs`

Global gutter navigation

          <GutterMenu>
            {{!-- Page content here --}}
          </GutterMenu>

Since there will only ever be one gutter menu in the UI, it makes sense to express the menu as a singleton component. This is what that singleton component looks like.

Note: Normally the gutter menu is rendered within a page layout and is fixed position. The columns shown in this example are only to imitate the actual width without applying fixed positioning.

      `,
  };
};
<|endoftext|>


<commit_before>ns.date = function(options) {
    var toString = Object.prototype.toString,
        datatype = toString.call(options).slice(8,-1)
        params;
    options = options || {};
    params = {
        'type': options.type || 'from',
        'date': options.date ? new Date(options.date) : new Date(),
        'placeholder': options.placeholder || 'Select a date'
    };
    if (options === 'to' || options === 'from') {
        return ns.date({
            'type': options
        })
    }
    if (datatype === 'Date' || datatype === 'String') {
        return ns.date({
            'date': options
        })
    }

    return new ns.models.date(params);
}<commit_msg>datepicker fix<commit_after>ns.date = function(options) {
    var toString = Object.prototype.toString,
        datatype = toString.call(options).slice(8,-1),
        params;
    options = options || {};
    params = {
        'type': options.type || 'from',
        'date': options.date ? new Date(options.date) : new Date(),
        'placeholder': options.placeholder || 'Select a date'
    };
    if (options === 'to' || options === 'from') {
        return ns.date({
            'type': options
        })
    }
    if (datatype === 'Date' || datatype === 'String') {
        return ns.date({
            'date': options
        })
    }

    return new ns.models.date(params);
}<|endoftext|>


<commit_before>'use strict';

const rp = require('request-promise-native');
const he = require('he');

const Microservices = require('../configs/microservices');

const self = module.exports = {

    // creates a thumbnail for a given slide
    createThumbnail: function(slideContent, slideId, theme='default', force=false) {
        let encodedContent = he.encode(slideContent, { allowUnsafeSymbols: true });

        return rp.post({
            uri: `${Microservices.file.uri}/thumbnail/slide/${slideId}/${theme}`,
            body: encodedContent,
            headers: {
                'Content-Type': 'text/plain'
            },
        });
    },

};
<commit_msg>Actually force thumb recreation with POST /deck/:id/thumbnails<commit_after>'use strict';

const rp = require('request-promise-native');
const he = require('he');

const Microservices = require('../configs/microservices');

const self = module.exports = {

    // creates a thumbnail for a given slide
    createThumbnail: function(slideContent, slideId, theme='default', force=false) {
        let encodedContent = he.encode(slideContent, { allowUnsafeSymbols: true });

        return rp.post({
            uri: `${Microservices.file.uri}/thumbnail/slide/${slideId}/${theme}`,
            qs: { force },
            body: encodedContent,
            headers: {
                'Content-Type': 'text/plain'
            },
        });
    },

};
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014
 *
 * This file is licensed under the Affero General Public License version 3
 * or later.
 *
 * See the COPYING-README file.
 *
 */

/* global trashBinApp */
(function() {

	/**
	 * Construct a new FileActions instance
	 */
	var FileActions = function() {
		this.initialize();
	}
	FileActions.prototype = {
		actions: {},
		defaults: {},
		icons: {},
		currentFile: null,
		initialize: function() {
			this.clear();
		},
		/**
		 * Merges the actions from the given fileActions into
		 * this instance.
		 *
		 * @param fileActions instance of OCA.Files.FileActions
		 */
		merge: function(fileActions) {
			var self = this;
			// merge first level to avoid unintended overwriting
			_.each(fileActions.actions, function(sourceMimeData, mime) {
				var targetMimeData = self.actions[mime];
				if (!targetMimeData) {
					targetMimeData = {};
				}
				self.actions[mime] = _.extend(targetMimeData, sourceMimeData);
			});

			this.defaults = _.extend(this.defaults, fileActions.defaults);
			this.icons = _.extend(this.icons, fileActions.icons);
		},
		register: function (mime, name, permissions, icon, action, displayName) {
			if (!this.actions[mime]) {
				this.actions[mime] = {};
			}
			if (!this.actions[mime][name]) {
				this.actions[mime][name] = {};
			}
			if (!displayName) {
				displayName = t('files', name);
			}
			this.actions[mime][name]['action'] = action;
			this.actions[mime][name]['permissions'] = permissions;
			this.actions[mime][name]['displayName'] = displayName;
			this.icons[name] = icon;
		},
		clear: function() {
			this.actions = {};
			this.defaults = {};
			this.icons = {};
			this.currentFile = null;
		},
		setDefault: function (mime, name) {
			this.defaults[mime] = name;
		},
		get: function (mime, type, permissions) {
			var actions = this.getActions(mime, type, permissions);
			var filteredActions = {};
			$.each(actions, function (name, action) {
				filteredActions[name] = action.action;
			});
			return filteredActions;
		},
		getActions: function (mime, type, permissions) {
			var actions = {};
			if (this.actions.all) {
				actions = $.extend(actions, this.actions.all);
			}
			if (type) {//type is 'dir' or 'file'
				if (this.actions[type]) {
					actions = $.extend(actions, this.actions[type]);
				}
			}
			if (mime) {
				var mimePart = mime.substr(0, mime.indexOf('/'));
				if (this.actions[mimePart]) {
					actions = $.extend(actions, this.actions[mimePart]);
				}
				if (this.actions[mime]) {
					actions = $.extend(actions, this.actions[mime]);
				}
			}
			var filteredActions = {};
			$.each(actions, function (name, action) {
				if (action.permissions & permissions) {
					filteredActions[name] = action;
				}
			});
			return filteredActions;
		},
		getDefault: function (mime, type, permissions) {
			var mimePart;
			if (mime) {
				mimePart = mime.substr(0, mime.indexOf('/'));
			}
			var name = false;
			if (mime && this.defaults[mime]) {
				name = this.defaults[mime];
			} else if (mime && this.defaults[mimePart]) {
				name = this.defaults[mimePart];
			} else if (type && this.defaults[type]) {
				name = this.defaults[type];
			} else {
				name = this.defaults.all;
			}
			var actions = this.get(mime, type, permissions);
			return actions[name];
		},
		/**
		 * Display file actions for the given element
		 * @param parent "td" element of the file for which to display actions
		 * @param triggerEvent if true, triggers the fileActionsReady on the file
		 * list afterwards (false by default)
		 * @param fileList OCA.Files.FileList instance on which the action is
		 * done, defaults to OCA.Files.App.fileList
		 */
		display: function (parent, triggerEvent, fileList) {
			if (!fileList) {
				console.warn('FileActions.display() MUST be called with a OCA.Files.FileList instance');
			}
			this.currentFile = parent;
			var self = this;
			var actions = this.getActions(this.getCurrentMimeType(), this.getCurrentType(), this.getCurrentPermissions());
			var file = this.getCurrentFile();
			var nameLinks;
			if (parent.closest('tr').data('renaming')) {
				return;
			}

			// recreate fileactions
			nameLinks = parent.children('a.name');
			nameLinks.find('.fileactions, .nametext .action').remove();
			nameLinks.append('');
			var defaultAction = this.getDefault(this.getCurrentMimeType(), this.getCurrentType(), this.getCurrentPermissions());

			var actionHandler = function (event) {
				event.stopPropagation();
				event.preventDefault();

				self.currentFile = event.data.elem;
				// also set on global object for legacy apps
				window.FileActions.currentFile = self.currentFile;

				var file = self.getCurrentFile();
				var $tr = $(this).closest('tr');

				event.data.actionFunc(file, {
					$file: $tr,
					fileList: fileList || OCA.Files.App.fileList,
					fileActions: self,
					dir: $tr.attr('data-path') || fileList.getCurrentDirectory()
				});
			};

			var addAction = function (name, action, displayName) {

				if ((name === 'Download' || action !== defaultAction) && name !== 'Delete') {

					var img = self.icons[name],
						actionText = displayName,
						actionContainer = 'a.name>span.fileactions';

					if (name === 'Rename') {
						// rename has only an icon which appears behind
						// the file name
						actionText = '';
						actionContainer = 'a.name span.nametext';
					}
					if (img.call) {
						img = img(file);
					}
					var html = '';
					if (img) {
						html += '';
					}
					html += ' ' + actionText + '';

					var element = $(html);
					element.data('action', name);
					element.on('click', {a: null, elem: parent, actionFunc: actions[name].action}, actionHandler);
					parent.find(actionContainer).append(element);
				}

			};

			$.each(actions, function (name, action) {
				if (name !== 'Share') {
					displayName = action.displayName;
					ah = action.action;

					addAction(name, ah, displayName);
				}
			});
			if(actions.Share){
				displayName = t('files', 'Share');
				addAction('Share', actions.Share, displayName);
			}

			// remove the existing delete action
			parent.parent().children().last().find('.action.delete').remove();
			if (actions['Delete']) {
				var img = self.icons['Delete'];
				var html;
				if (img.call) {
					img = img(file);
				}
				if (typeof trashBinApp !== 'undefined' && trashBinApp) {
					html = '';
				} else {
					html = '';
				}
				var element = $(html);
				element.data('action', actions['Delete']);
				element.on('click', {a: null, elem: parent, actionFunc: actions['Delete'].action}, actionHandler);
				parent.parent().children().last().append(element);
			}

			if (triggerEvent){
				fileList.$fileList.trigger(jQuery.Event("fileActionsReady", {fileList: fileList}));
			}
		},
		getCurrentFile: function () {
			return this.currentFile.parent().attr('data-file');
		},
		getCurrentMimeType: function () {
			return this.currentFile.parent().attr('data-mime');
		},
		getCurrentType: function () {
			return this.currentFile.parent().attr('data-type');
		},
		getCurrentPermissions: function () {
			return this.currentFile.parent().data('permissions');
		},

		/**
		 * Register the actions that are used by default for the files app.
		 */
		registerDefaultActions: function() {
			this.register('all', 'Delete', OC.PERMISSION_DELETE, function () {
				return OC.imagePath('core', 'actions/delete');
			}, function (filename, context) {
				context.fileList.do_delete(filename);
				$('.tipsy').remove();
			});

			// t('files', 'Rename')
			this.register('all', 'Rename', OC.PERMISSION_UPDATE, function () {
				return OC.imagePath('core', 'actions/rename');
			}, function (filename, context) {
				context.fileList.rename(filename);
			});

			this.register('dir', 'Open', OC.PERMISSION_READ, '', function (filename, context) {
				var dir = context.fileList.getCurrentDirectory();
				if (dir !== '/') {
					dir = dir + '/';
				}
				context.fileList.changeDirectory(dir + filename);
			});

			this.setDefault('dir', 'Open');

			this.register('all', 'Download', OC.PERMISSION_READ, function () {
				return OC.imagePath('core', 'actions/download');
			}, function (filename, context) {
				var dir = context.dir || context.fileList.getCurrentDirectory();
				var url = context.fileList.getDownloadUrl(filename, dir);
				if (url) {
					OC.redirect(url);
				}
			});
		}
	};

	OCA.Files.FileActions = FileActions;

	// global file actions to be used by all lists
	OCA.Files.fileActions = new OCA.Files.FileActions();
	OCA.Files.legacyFileActions = new OCA.Files.FileActions();

	// for backward compatibility
	//
	// legacy apps are expecting a stateful global FileActions object to register
	// their actions on. Since legacy apps are very likely to break with other
	// FileList views than the main one ("All files"), actions registered
	// through window.FileActions will be limited to the main file list.
	window.FileActions = OCA.Files.legacyFileActions;
	window.FileActions.register = function (mime, name, permissions, icon, action, displayName) {
		console.warn('FileActions.register() is deprecated, please use OCA.Files.fileActions.register() instead', arguments);
		OCA.Files.FileActions.prototype.register.call(
				window.FileActions, mime, name, permissions, icon, action, displayName
		);
	};
	window.FileActions.setDefault = function (mime, name) {
		console.warn('FileActions.setDefault() is deprecated, please use OCA.Files.fileActions.setDefault() instead', mime, name);
		OCA.Files.FileActions.prototype.setDefault.call(window.FileActions, mime, name);
	};
})();

<commit_msg>Fixed file actions fallback<commit_after>/*
 * Copyright (c) 2014
 *
 * This file is licensed under the Affero General Public License version 3
 * or later.
 *
 * See the COPYING-README file.
 *
 */

/* global trashBinApp */
(function() {

	/**
	 * Construct a new FileActions instance
	 */
	var FileActions = function() {
		this.initialize();
	}
	FileActions.prototype = {
		actions: {},
		defaults: {},
		icons: {},
		currentFile: null,
		initialize: function() {
			this.clear();
		},
		/**
		 * Merges the actions from the given fileActions into
		 * this instance.
		 *
		 * @param fileActions instance of OCA.Files.FileActions
		 */
		merge: function(fileActions) {
			var self = this;
			// merge first level to avoid unintended overwriting
			_.each(fileActions.actions, function(sourceMimeData, mime) {
				var targetMimeData = self.actions[mime];
				if (!targetMimeData) {
					targetMimeData = {};
				}
				self.actions[mime] = _.extend(targetMimeData, sourceMimeData);
			});

			this.defaults = _.extend(this.defaults, fileActions.defaults);
			this.icons = _.extend(this.icons, fileActions.icons);
		},
		register: function (mime, name, permissions, icon, action, displayName) {
			if (!this.actions[mime]) {
				this.actions[mime] = {};
			}
			if (!this.actions[mime][name]) {
				this.actions[mime][name] = {};
			}
			if (!displayName) {
				displayName = t('files', name);
			}
			this.actions[mime][name]['action'] = action;
			this.actions[mime][name]['permissions'] = permissions;
			this.actions[mime][name]['displayName'] = displayName;
			this.icons[name] = icon;
		},
		clear: function() {
			this.actions = {};
			this.defaults = {};
			this.icons = {};
			this.currentFile = null;
		},
		setDefault: function (mime, name) {
			this.defaults[mime] = name;
		},
		get: function (mime, type, permissions) {
			var actions = this.getActions(mime, type, permissions);
			var filteredActions = {};
			$.each(actions, function (name, action) {
				filteredActions[name] = action.action;
			});
			return filteredActions;
		},
		getActions: function (mime, type, permissions) {
			var actions = {};
			if (this.actions.all) {
				actions = $.extend(actions, this.actions.all);
			}
			if (type) {//type is 'dir' or 'file'
				if (this.actions[type]) {
					actions = $.extend(actions, this.actions[type]);
				}
			}
			if (mime) {
				var mimePart = mime.substr(0, mime.indexOf('/'));
				if (this.actions[mimePart]) {
					actions = $.extend(actions, this.actions[mimePart]);
				}
				if (this.actions[mime]) {
					actions = $.extend(actions, this.actions[mime]);
				}
			}
			var filteredActions = {};
			$.each(actions, function (name, action) {
				if (action.permissions & permissions) {
					filteredActions[name] = action;
				}
			});
			return filteredActions;
		},
		getDefault: function (mime, type, permissions) {
			var mimePart;
			if (mime) {
				mimePart = mime.substr(0, mime.indexOf('/'));
			}
			var name = false;
			if (mime && this.defaults[mime]) {
				name = this.defaults[mime];
			} else if (mime && this.defaults[mimePart]) {
				name = this.defaults[mimePart];
			} else if (type && this.defaults[type]) {
				name = this.defaults[type];
			} else {
				name = this.defaults.all;
			}
			var actions = this.get(mime, type, permissions);
			return actions[name];
		},
		/**
		 * Display file actions for the given element
		 * @param parent "td" element of the file for which to display actions
		 * @param triggerEvent if true, triggers the fileActionsReady on the file
		 * list afterwards (false by default)
		 * @param fileList OCA.Files.FileList instance on which the action is
		 * done, defaults to OCA.Files.App.fileList
		 */
		display: function (parent, triggerEvent, fileList) {
			if (!fileList) {
				console.warn('FileActions.display() MUST be called with a OCA.Files.FileList instance');
				// using default list instead, which could be wrong
				fileList = OCA.Files.App.fileList;
			}
			this.currentFile = parent;
			var self = this;
			var actions = this.getActions(this.getCurrentMimeType(), this.getCurrentType(), this.getCurrentPermissions());
			var file = this.getCurrentFile();
			var nameLinks;
			if (parent.closest('tr').data('renaming')) {
				return;
			}

			// recreate fileactions
			nameLinks = parent.children('a.name');
			nameLinks.find('.fileactions, .nametext .action').remove();
			nameLinks.append('');
			var defaultAction = this.getDefault(this.getCurrentMimeType(), this.getCurrentType(), this.getCurrentPermissions());

			var actionHandler = function (event) {
				event.stopPropagation();
				event.preventDefault();

				self.currentFile = event.data.elem;
				// also set on global object for legacy apps
				window.FileActions.currentFile = self.currentFile;

				var file = self.getCurrentFile();
				var $tr = $(this).closest('tr');

				event.data.actionFunc(file, {
					$file: $tr,
					fileList: fileList,
					fileActions: self,
					dir: $tr.attr('data-path') || fileList.getCurrentDirectory()
				});
			};

			var addAction = function (name, action, displayName) {

				if ((name === 'Download' || action !== defaultAction) && name !== 'Delete') {

					var img = self.icons[name],
						actionText = displayName,
						actionContainer = 'a.name>span.fileactions';

					if (name === 'Rename') {
						// rename has only an icon which appears behind
						// the file name
						actionText = '';
						actionContainer = 'a.name span.nametext';
					}
					if (img.call) {
						img = img(file);
					}
					var html = '';
					if (img) {
						html += '';
					}
					html += ' ' + actionText + '';

					var element = $(html);
					element.data('action', name);
					element.on('click', {a: null, elem: parent, actionFunc: actions[name].action}, actionHandler);
					parent.find(actionContainer).append(element);
				}

			};

			$.each(actions, function (name, action) {
				if (name !== 'Share') {
					displayName = action.displayName;
					ah = action.action;

					addAction(name, ah, displayName);
				}
			});
			if(actions.Share){
				displayName = t('files', 'Share');
				addAction('Share', actions.Share, displayName);
			}

			// remove the existing delete action
			parent.parent().children().last().find('.action.delete').remove();
			if (actions['Delete']) {
				var img = self.icons['Delete'];
				var html;
				if (img.call) {
					img = img(file);
				}
				if (typeof trashBinApp !== 'undefined' && trashBinApp) {
					html = '';
				} else {
					html = '';
				}
				var element = $(html);
				element.data('action', actions['Delete']);
				element.on('click', {a: null, elem: parent, actionFunc: actions['Delete'].action}, actionHandler);
				parent.parent().children().last().append(element);
			}

			if (triggerEvent){
				fileList.$fileList.trigger(jQuery.Event("fileActionsReady", {fileList: fileList}));
			}
		},
		getCurrentFile: function () {
			return this.currentFile.parent().attr('data-file');
		},
		getCurrentMimeType: function () {
			return this.currentFile.parent().attr('data-mime');
		},
		getCurrentType: function () {
			return this.currentFile.parent().attr('data-type');
		},
		getCurrentPermissions: function () {
			return this.currentFile.parent().data('permissions');
		},

		/**
		 * Register the actions that are used by default for the files app.
		 */
		registerDefaultActions: function() {
			this.register('all', 'Delete', OC.PERMISSION_DELETE, function () {
				return OC.imagePath('core', 'actions/delete');
			}, function (filename, context) {
				context.fileList.do_delete(filename);
				$('.tipsy').remove();
			});

			// t('files', 'Rename')
			this.register('all', 'Rename', OC.PERMISSION_UPDATE, function () {
				return OC.imagePath('core', 'actions/rename');
			}, function (filename, context) {
				context.fileList.rename(filename);
			});

			this.register('dir', 'Open', OC.PERMISSION_READ, '', function (filename, context) {
				var dir = context.fileList.getCurrentDirectory();
				if (dir !== '/') {
					dir = dir + '/';
				}
				context.fileList.changeDirectory(dir + filename);
			});

			this.setDefault('dir', 'Open');

			this.register('all', 'Download', OC.PERMISSION_READ, function () {
				return OC.imagePath('core', 'actions/download');
			}, function (filename, context) {
				var dir = context.dir || context.fileList.getCurrentDirectory();
				var url = context.fileList.getDownloadUrl(filename, dir);
				if (url) {
					OC.redirect(url);
				}
			});
		}
	};

	OCA.Files.FileActions = FileActions;

	// global file actions to be used by all lists
	OCA.Files.fileActions = new OCA.Files.FileActions();
	OCA.Files.legacyFileActions = new OCA.Files.FileActions();

	// for backward compatibility
	//
	// legacy apps are expecting a stateful global FileActions object to register
	// their actions on. Since legacy apps are very likely to break with other
	// FileList views than the main one ("All files"), actions registered
	// through window.FileActions will be limited to the main file list.
	window.FileActions = OCA.Files.legacyFileActions;
	window.FileActions.register = function (mime, name, permissions, icon, action, displayName) {
		console.warn('FileActions.register() is deprecated, please use OCA.Files.fileActions.register() instead', arguments);
		OCA.Files.FileActions.prototype.register.call(
				window.FileActions, mime, name, permissions, icon, action, displayName
		);
	};
	window.FileActions.setDefault = function (mime, name) {
		console.warn('FileActions.setDefault() is deprecated, please use OCA.Files.fileActions.setDefault() instead', mime, name);
		OCA.Files.FileActions.prototype.setDefault.call(window.FileActions, mime, name);
	};
})();

<|endoftext|>


<commit_before>/*jshint node:true*/
module.exports = {
  description: 'A textbox that will guess the date you want and assign it to your model or query-params.',
  name: 'ember-cli-date-textbox',
  normalizeEntityName: function () {
  },
  afterInstall: function (/*options*/) {
    var self = this;
    return self.addAddonsToProject([{name: 'ember-cli-text-support-mixins'}])
      .then(function () => {
        return self.addBowerPackagesToProject([
          {name: 'datejs-parse-plus'},
          {name: 'moment'},
          {name: 'moment-timezone'}
        ]);
      });
  }
};
<commit_msg>bugfix blueprints<commit_after>/*jshint node:true*/
module.exports = {
  description: 'A textbox that will guess the date you want and assign it to your model or query-params.',
  name: 'ember-cli-date-textbox',
  normalizeEntityName: function () {
  },
  afterInstall: function (/*options*/) {
    var self = this;
    return self.addAddonsToProject([{name: 'ember-cli-text-support-mixins'}])
      .then(function () {
        return self.addBowerPackagesToProject([
          {name: 'datejs-parse-plus'},
          {name: 'moment'},
          {name: 'moment-timezone'}
        ]);
      });
  }
};
<|endoftext|>


<commit_before>module.exports = {
  // Hack for previous versions of Ember CLI
  normalizeEntityName: function() {},

  afterInstall: function(options) {
    return this.addBowerPackageToProject('jquery-mockjax', 'latest');
  },

  initialize: function(container, application) {
  }
};
<commit_msg>fix blueprint to install latest mockjax<commit_after>module.exports = {
  // Hack for previous versions of Ember CLI
  normalizeEntityName: function() {},

  afterInstall: function(options) {
    return this.addBowerPackageToProject('jquery-mockjax', '2.0.1');
  },

  initialize: function(container, application) {
  }
};
<|endoftext|>


<commit_before>/*globals define, document, console, eval, GME*/

define('webgme.classes',
    [
        'client',
        'blob/BlobClient',
        'executor/ExecutorClient',
        'js/Utils/InterpreterManager'
    ], function (Client, BlobClient, ExecutorClient, InterpreterManager) {
        GME.classes.Client = Client;
        GME.classes.BlobClient = BlobClient;
        GME.classes.ExecutorClient = ExecutorClient;
        GME.classes.InterpreterManager = InterpreterManager;

        if (document.body.getAttribute("on-gme-init")) {
            eval(document.body.getAttribute("on-gme-init"));
        } else {
            console.warn('To use GME, define a javascript function and set the body element\'s on-gme-init property.');
        }
    });
<commit_msg>guarding on-gme-init handler by docReady<commit_after>/*globals define, document, console, eval, GME*/

define('webgme.classes',
    [
        'client',
        'blob/BlobClient',
        'executor/ExecutorClient',
        'js/Utils/InterpreterManager'
    ], function (Client, BlobClient, ExecutorClient, InterpreterManager) {

        // Setting global classes

        GME.classes.Client = Client;
        GME.classes.BlobClient = BlobClient;
        GME.classes.ExecutorClient = ExecutorClient;
        GME.classes.InterpreterManager = InterpreterManager;

        // Pure JavaScript equivalent to jQuery's $.ready() from https://github.com/jfriend00/docReady

        (function(funcName, baseObj) {
            // The public function name defaults to window.docReady
            // but you can pass in your own object and own function name and those will be used
            // if you want to put them in a different namespace
            funcName = funcName || "docReady";
            baseObj = baseObj || window;
            var readyList = [];
            var readyFired = false;
            var readyEventHandlersInstalled = false;

            // call this when the document is ready
            // this function protects itself against being called more than once
            function ready() {
                if (!readyFired) {
                    // this must be set to true before we start calling callbacks
                    readyFired = true;
                    for (var i = 0; i < readyList.length; i++) {
                        // if a callback here happens to add new ready handlers,
                        // the docReady() function will see that it already fired
                        // and will schedule the callback to run right after
                        // this event loop finishes so all handlers will still execute
                        // in order and no new ones will be added to the readyList
                        // while we are processing the list
                        readyList[i].fn.call(window, readyList[i].ctx);
                    }
                    // allow any closures held by these functions to free
                    readyList = [];
                }
            }

            function readyStateChange() {
                if ( document.readyState === "complete" ) {
                    ready();
                }
            }

            // This is the one public interface
            // docReady(fn, context);
            // the context argument is optional - if present, it will be passed
            // as an argument to the callback
            baseObj[funcName] = function(callback, context) {
                // if ready has already fired, then just schedule the callback
                // to fire asynchronously, but right away
                if (readyFired) {
                    setTimeout(function() {callback(context);}, 1);
                    return;
                } else {
                    // add the function and context to the list
                    readyList.push({fn: callback, ctx: context});
                }
                // if document already ready to go, schedule the ready function to run
                if (document.readyState === "complete") {
                    setTimeout(ready, 1);
                } else if (!readyEventHandlersInstalled) {
                    // otherwise if we don't have event handlers installed, install them
                    if (document.addEventListener) {
                        // first choice is DOMContentLoaded event
                        document.addEventListener("DOMContentLoaded", ready, false);
                        // backup is window load event
                        window.addEventListener("load", ready, false);
                    } else {
                        // must be IE
                        document.attachEvent("onreadystatechange", readyStateChange);
                        window.attachEvent("onload", ready);
                    }
                    readyEventHandlersInstalled = true;
                }
            }
        })("docReady", window);

        // See if there is handler attached to body tag when ready

        docReady(function() {

            if (document.body.getAttribute("on-gme-init")) {
                eval(document.body.getAttribute("on-gme-init"));
            } else {
                console.warn('To use GME, define a javascript function and set the body element\'s on-gme-init property.');
            }
        });

    });
<|endoftext|>


<commit_before>define(["lib/htmlparser"], function(htmlparser) {
    describe("HTMLParser", function() {
        describe("HTML syntax", function() {
            it("Colon in attribute name", function() {
                var input = "",
                    handler = jasmine.createSpyObj("handler", ["start"]);
                htmlparser.HTMLParser(input, handler);
                expect(handler.start.calls.length).toEqual(1);
                expect(handler.start).toHaveBeenCalledWith("html", [{name: "xml:lang", value: "en", escaped: "en"}], false);
            });

            it("Colon in tag name", function() {
                var input = "<tal:span></tal:span>",
                    handler = jasmine.createSpyObj("handler", ["start"]);
                htmlparser.HTMLParser(input, handler);
                expect(handler.start.calls.length).toEqual(1);
                expect(handler.start).toHaveBeenCalledWith("tal:span", [], false);
            });

            xit("Two consecutive double quotes in attribute", function() {
                var input = "",
                    handler = jasmine.createSpyObj("handler", ["start"]);
                htmlparser.HTMLParser(input, handler);
                expect(handler.start.calls.length).toEqual(1);
                expect(handler.start).toHaveBeenCalledWith("a", [{name: "data-test", value: "\"\"", escaped: "\\\"\\\""}], false);
            });
        });
    });
});
<commit_msg>spec was meanwhile succeeding<commit_after>define(["lib/htmlparser"], function(htmlparser) {
    describe("HTMLParser", function() {
        describe("HTML syntax", function() {
            it("Colon in attribute name", function() {
                var input = "",
                    handler = jasmine.createSpyObj("handler", ["start"]);
                htmlparser.HTMLParser(input, handler);
                expect(handler.start.calls.length).toEqual(1);
                expect(handler.start).toHaveBeenCalledWith("html", [{name: "xml:lang", value: "en", escaped: "en"}], false);
            });

            it("Colon in tag name", function() {
                var input = "<tal:span></tal:span>",
                    handler = jasmine.createSpyObj("handler", ["start"]);
                htmlparser.HTMLParser(input, handler);
                expect(handler.start.calls.length).toEqual(1);
                expect(handler.start).toHaveBeenCalledWith("tal:span", [], false);
            });

            it("Two consecutive double quotes in attribute", function() {
                var input = "",
                    handler = jasmine.createSpyObj("handler", ["start"]);
                htmlparser.HTMLParser(input, handler);
                expect(handler.start.calls.length).toEqual(1);
                expect(handler.start).toHaveBeenCalledWith("a", [{name: "data-test", value: "\"\"", escaped: "\\\"\\\""}], false);
            });
        });
    });
});
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014
 *
 * This file is licensed under the Affero General Public License version 3
 * or later.
 *
 * See the COPYING-README file.
 *
 */

/* global Files */

(function() {

	var TEMPLATE_MENU =
		'
' +
		'
' +
		'{{uploadLabel}}' +
		'
' +
		'{{#each items}}' +
		'
' +
		'{{displayName}}' +
		'
' +
		'{{/each}}' +
		'
';

	var TEMPLATE_FILENAME_FORM =
		'<form class="filenameform">' +
		'<input id="{{cid}}-input-{{fileType}}" type="text" value="{{fileName}}" autocomplete="off" autocapitalize="off">' +
		'<input type="submit" value=" " class="icon-confirm" />'
		'</form>';

	/**
	 * Construct a new NewFileMenu instance
	 * @constructs NewFileMenu
	 *
	 * @memberof OCA.Files
	 */
	var NewFileMenu = OC.Backbone.View.extend({
		tagName: 'div',
		// Menu is opened by default because it's rendered on "add-button" click
		className: 'newFileMenu popovermenu bubble menu open menu-left',

		events: {
			'click .menuitem': '_onClickAction'
		},

		/**
		 * @type OCA.Files.FileList
		 */
		fileList: null,

		initialize: function(options) {
			var self = this;
			var $uploadEl = $('#file_upload_start');
			if ($uploadEl.length) {
				$uploadEl.on('fileuploadstart', function() {
					self.trigger('actionPerformed', 'upload');
				});
			} else {
				console.warn('Missing upload element "file_upload_start"');
			}

			this.fileList = options && options.fileList;

			this._menuItems = [{
				id: 'folder',
				displayName: t('files', 'New folder'),
				templateName: t('files', 'New folder'),
				iconClass: 'icon-folder',
				fileType: 'folder',
				actionHandler: function(name) {
					self.fileList.createDirectory(name);
				}
		        }];

			OC.Plugins.attach('OCA.Files.NewFileMenu', this);
		},

		template: function(data) {
			if (!OCA.Files.NewFileMenu._TEMPLATE) {
				OCA.Files.NewFileMenu._TEMPLATE = Handlebars.compile(TEMPLATE_MENU);
			}
			return OCA.Files.NewFileMenu._TEMPLATE(data);
		},

		/**
		 * Event handler whenever an action has been clicked within the menu
		 *
		 * @param {Object} event event object
		 */
		_onClickAction: function(event) {
			var $target = $(event.target);
			if (!$target.hasClass('menuitem')) {
				$target = $target.closest('.menuitem');
			}
			var action = $target.attr('data-action');
			// note: clicking the upload label will automatically
			// set the focus on the "file_upload_start" hidden field
			// which itself triggers the upload dialog.
			// Currently the upload logic is still in file-upload.js and filelist.js
			if (action === 'upload') {
				OC.hideMenus();
			} else {
				event.preventDefault();
				this.$el.find('.menuitem.active').removeClass('active');
				$target.addClass('active');
				this._promptFileName($target);
			}
		},

		_promptFileName: function($target) {
			var self = this;
			if (!OCA.Files.NewFileMenu._TEMPLATE_FORM) {
				OCA.Files.NewFileMenu._TEMPLATE_FORM = Handlebars.compile(TEMPLATE_FILENAME_FORM);
			}

			if ($target.find('form').length) {
				$target.find('input[type=\'text\']').focus();
				return;
			}

			// discard other forms
			this.$el.find('form').remove();
			this.$el.find('.displayname').removeClass('hidden');

			$target.find('.displayname').addClass('hidden');

			var newName = $target.attr('data-templatename');
			var fileType = $target.attr('data-filetype');
			var $form = $(OCA.Files.NewFileMenu._TEMPLATE_FORM({
				fileName: newName,
				cid: this.cid,
				fileType: fileType
			}));

			//this.trigger('actionPerformed', action);
			$target.append($form);

			// here comes the OLD code
			var $input = $form.find('input[type=\'text\']');
			var $submit = $form.find('input[type=\'submit\']');

			var lastPos;
			var checkInput = function () {
				var filename = $input.val();
				try {
					if (!Files.isFileNameValid(filename)) {
						// Files.isFileNameValid(filename) throws an exception itself
					} else if (self.fileList.inList(filename)) {
						throw t('files', '{newName} already exists', {newName: filename}, undefined, {
							escape: false
						});
					} else {
						return true;
					}
				} catch (error) {
					$input.attr('title', error);
					$input.tooltip({placement: 'right', trigger: 'manual', 'container': '.newFileMenu'});
					$input.tooltip('fixTitle');
					$input.tooltip('show');
					$input.addClass('error');
				}
				return false;
			};

			// verify filename on typing
			$input.keyup(function() {
				if (checkInput()) {
					$input.tooltip('hide');
					$input.removeClass('error');
				}
			});

			$submit.click(function(event) {
				event.stopPropagation();
				event.preventDefault();
				$form.submit();
			});

			$input.focus();
			// pre select name up to the extension
			lastPos = newName.lastIndexOf('.');
			if (lastPos === -1) {
				lastPos = newName.length;
			}
			$input.selectRange(0, lastPos);

			$form.submit(function(event) {
				event.stopPropagation();
				event.preventDefault();

				if (checkInput()) {
					var newname = $input.val();

					/* Find the right actionHandler that should be called.
					 * Actions is retrieved by using `actionSpec.id` */
					action = _.filter(self._menuItems, function(item) {
						return item.id == $target.attr('data-action');
					}).pop();
					action.actionHandler(newname);

					$form.remove();
					$target.find('.displayname').removeClass('hidden');
					OC.hideMenus();
				}
			});
		},

		/**
		* Add a new item menu entry in the “New” file menu (in
		* last position). By clicking on the item, the
		* `actionHandler` function is called.
		*
		* @param {Object} actionSpec item’s properties
		*/
		addMenuEntry: function(actionSpec) {
			this._menuItems.push({
				id: actionSpec.id,
				displayName: actionSpec.displayName,
				templateName: actionSpec.templateName,
				iconClass: actionSpec.iconClass,
				fileType: actionSpec.fileType,
				actionHandler: actionSpec.actionHandler,
		        });
		},

		/**
		 * Renders the menu with the currently set items
		 */
		render: function() {
			this.$el.html(this.template({
				uploadMaxHumanFileSize: 'TODO',
				uploadLabel: t('files', 'Upload file'),
				items: this._menuItems
			}));
			OC.Util.scaleFixForIE8(this.$('.svg'));

			// Trigger upload action also with keyboard navigation on enter
			this.$el.find('[for="file_upload_start"]').on('keypress', function() {
				$('#file_upload_start').trigger('click');
			});
		},

		/**
		 * Displays the menu under the given element
		 *
		 * @param {Object} $target target element
		 */
		showAt: function($target) {
			this.render();
			OC.showMenu(null, this.$el);
		}
	});

	OCA.Files.NewFileMenu = NewFileMenu;

})();
<commit_msg>Trigger upload actions only for Enter & Space keys<commit_after>/*
 * Copyright (c) 2014
 *
 * This file is licensed under the Affero General Public License version 3
 * or later.
 *
 * See the COPYING-README file.
 *
 */

/* global Files */

(function() {

	var TEMPLATE_MENU =
		'
' +
		'
' +
		'{{uploadLabel}}' +
		'
' +
		'{{#each items}}' +
		'
' +
		'{{displayName}}' +
		'
' +
		'{{/each}}' +
		'
';

	var TEMPLATE_FILENAME_FORM =
		'<form class="filenameform">' +
		'<input id="{{cid}}-input-{{fileType}}" type="text" value="{{fileName}}" autocomplete="off" autocapitalize="off">' +
		'<input type="submit" value=" " class="icon-confirm" />'
		'</form>';

	/**
	 * Construct a new NewFileMenu instance
	 * @constructs NewFileMenu
	 *
	 * @memberof OCA.Files
	 */
	var NewFileMenu = OC.Backbone.View.extend({
		tagName: 'div',
		// Menu is opened by default because it's rendered on "add-button" click
		className: 'newFileMenu popovermenu bubble menu open menu-left',

		events: {
			'click .menuitem': '_onClickAction'
		},

		/**
		 * @type OCA.Files.FileList
		 */
		fileList: null,

		initialize: function(options) {
			var self = this;
			var $uploadEl = $('#file_upload_start');
			if ($uploadEl.length) {
				$uploadEl.on('fileuploadstart', function() {
					self.trigger('actionPerformed', 'upload');
				});
			} else {
				console.warn('Missing upload element "file_upload_start"');
			}

			this.fileList = options && options.fileList;

			this._menuItems = [{
				id: 'folder',
				displayName: t('files', 'New folder'),
				templateName: t('files', 'New folder'),
				iconClass: 'icon-folder',
				fileType: 'folder',
				actionHandler: function(name) {
					self.fileList.createDirectory(name);
				}
		        }];

			OC.Plugins.attach('OCA.Files.NewFileMenu', this);
		},

		template: function(data) {
			if (!OCA.Files.NewFileMenu._TEMPLATE) {
				OCA.Files.NewFileMenu._TEMPLATE = Handlebars.compile(TEMPLATE_MENU);
			}
			return OCA.Files.NewFileMenu._TEMPLATE(data);
		},

		/**
		 * Event handler whenever an action has been clicked within the menu
		 *
		 * @param {Object} event event object
		 */
		_onClickAction: function(event) {
			var $target = $(event.target);
			if (!$target.hasClass('menuitem')) {
				$target = $target.closest('.menuitem');
			}
			var action = $target.attr('data-action');
			// note: clicking the upload label will automatically
			// set the focus on the "file_upload_start" hidden field
			// which itself triggers the upload dialog.
			// Currently the upload logic is still in file-upload.js and filelist.js
			if (action === 'upload') {
				OC.hideMenus();
			} else {
				event.preventDefault();
				this.$el.find('.menuitem.active').removeClass('active');
				$target.addClass('active');
				this._promptFileName($target);
			}
		},

		_promptFileName: function($target) {
			var self = this;
			if (!OCA.Files.NewFileMenu._TEMPLATE_FORM) {
				OCA.Files.NewFileMenu._TEMPLATE_FORM = Handlebars.compile(TEMPLATE_FILENAME_FORM);
			}

			if ($target.find('form').length) {
				$target.find('input[type=\'text\']').focus();
				return;
			}

			// discard other forms
			this.$el.find('form').remove();
			this.$el.find('.displayname').removeClass('hidden');

			$target.find('.displayname').addClass('hidden');

			var newName = $target.attr('data-templatename');
			var fileType = $target.attr('data-filetype');
			var $form = $(OCA.Files.NewFileMenu._TEMPLATE_FORM({
				fileName: newName,
				cid: this.cid,
				fileType: fileType
			}));

			//this.trigger('actionPerformed', action);
			$target.append($form);

			// here comes the OLD code
			var $input = $form.find('input[type=\'text\']');
			var $submit = $form.find('input[type=\'submit\']');

			var lastPos;
			var checkInput = function () {
				var filename = $input.val();
				try {
					if (!Files.isFileNameValid(filename)) {
						// Files.isFileNameValid(filename) throws an exception itself
					} else if (self.fileList.inList(filename)) {
						throw t('files', '{newName} already exists', {newName: filename}, undefined, {
							escape: false
						});
					} else {
						return true;
					}
				} catch (error) {
					$input.attr('title', error);
					$input.tooltip({placement: 'right', trigger: 'manual', 'container': '.newFileMenu'});
					$input.tooltip('fixTitle');
					$input.tooltip('show');
					$input.addClass('error');
				}
				return false;
			};

			// verify filename on typing
			$input.keyup(function() {
				if (checkInput()) {
					$input.tooltip('hide');
					$input.removeClass('error');
				}
			});

			$submit.click(function(event) {
				event.stopPropagation();
				event.preventDefault();
				$form.submit();
			});

			$input.focus();
			// pre select name up to the extension
			lastPos = newName.lastIndexOf('.');
			if (lastPos === -1) {
				lastPos = newName.length;
			}
			$input.selectRange(0, lastPos);

			$form.submit(function(event) {
				event.stopPropagation();
				event.preventDefault();

				if (checkInput()) {
					var newname = $input.val();

					/* Find the right actionHandler that should be called.
					 * Actions is retrieved by using `actionSpec.id` */
					action = _.filter(self._menuItems, function(item) {
						return item.id == $target.attr('data-action');
					}).pop();
					action.actionHandler(newname);

					$form.remove();
					$target.find('.displayname').removeClass('hidden');
					OC.hideMenus();
				}
			});
		},

		/**
		* Add a new item menu entry in the “New” file menu (in
		* last position). By clicking on the item, the
		* `actionHandler` function is called.
		*
		* @param {Object} actionSpec item’s properties
		*/
		addMenuEntry: function(actionSpec) {
			this._menuItems.push({
				id: actionSpec.id,
				displayName: actionSpec.displayName,
				templateName: actionSpec.templateName,
				iconClass: actionSpec.iconClass,
				fileType: actionSpec.fileType,
				actionHandler: actionSpec.actionHandler,
		        });
		},

		/**
		 * Renders the menu with the currently set items
		 */
		render: function() {
			this.$el.html(this.template({
				uploadMaxHumanFileSize: 'TODO',
				uploadLabel: t('files', 'Upload file'),
				items: this._menuItems
			}));
			OC.Util.scaleFixForIE8(this.$('.svg'));

			// Trigger upload action also with keyboard navigation on enter
			this.$el.find('[for="file_upload_start"]').on('keyup', function(event) {
				if (event.key === " " || event.key === "Enter") {
					$('#file_upload_start').trigger('click');
				}
			});
		},

		/**
		 * Displays the menu under the given element
		 *
		 * @param {Object} $target target element
		 */
		showAt: function($target) {
			this.render();
			OC.showMenu(null, this.$el);
		}
	});

	OCA.Files.NewFileMenu = NewFileMenu;

})();
<|endoftext|>


<commit_before>enyo.kind({
	name:"App",
	kind:"Control",
	hatsize: 48,
	hatmargin: 8,
	rows: 10,
	score: 0,
	canplay: true,
	moves: [],
	components:[
		{name:"bottom", classes:"overlap center bottom"},
		{name:"hats", style:"display: none;", components: [
			{kind:"Image", onload:"loadHandler", src:"images/game_bear.png"},
			{kind:"Image", onload:"loadHandler", src:"images/game_bunny_02.png"},
			{kind:"Image", onload:"loadHandler", src:"images/game_carrot.png"},
			{kind:"Image", onload:"loadHandler", src:"images/game_lemon.png"},
			{kind:"Image", onload:"loadHandler", src:"images/game_panda.png"},
			{kind:"Image", onload:"loadHandler", src:"images/game_piratePig.png"},
		]},
		// why can't there just be one standard that isn't wav?
		{name:"sounds", style:"display: none;", components:[
			{name:"three", kind:"Audio", src:["sounds/3.ogg", "sounds/3.mp3", "sounds/3.wav"], onEnded: "endedHandler"},
			{name:"four", kind:"Audio", src:["sounds/4.ogg", "sounds/4.mp3", "sounds/4.wav"], onEnded: "endedHandler"},
			{name:"fiveplus", kind:"Audio", src:["sounds/5.ogg", "sounds/5.mp3", "sounds/5.wav"], onEnded: "endedHandler"},
			{name:"whiff", kind:"Audio", src:["sounds/whiff.ogg", "sounds/whiff.mp3", "sounds/whiff.wav"], onEnded:"endedHandler"},
			{name:"theme", kind:"Audio", src:["sounds/theme.ogg", "sounds/theme.mp3", "sounds/theme.wav"], onEnded:"endedHandler"}
		]},
		{name:"title", style:"width: 560px; height: 100px;", classes:"hcenter banner", components:[
			{name:"score", classes:"score", content:"0"},
		]},
		{name:"backgroundbox", kind:"Canvas", attributes:{height:"560px", width:"560px"}, classes:"overlap hcenter", components:[
			{name:"background", kind:"canvas.Rectangle", bounds:{t:0, l:0, w:560, h:560}, color:"rgba(255,255,255,0.9)"},
		]},
		{name:"selectbox", kind:"Canvas", attributes:{height:"560px", width:"560px"}, classes:"overlap hcenter", components:[
			{name:"selector", kind:"Selector", color:"red"}
		]},
		{name:"hatbox", kind:"Canvas", attributes:{height:"560px", width:"560px"}, classes:"overlap hcenter border", ontap:"hatTap"}
	],
	create: function() {
		this.inherited(arguments);
		this.addClass("bg");
		// sounds only occur on user actions on ios
		if (navigator.userAgent.match(/i(?:pad|phone)/i)) {
			this.ios = true;
		}
	},
	loadHandler: function() {
		this.loaded = (this.loaded || 0) + 1;
		if (this.loaded == this.$.hats.getClientControls().length) {
			this.initHats();
		}
	},
	endedHandler: function() {
		enyo.job.stop(this.id + "enableSound");
		this.canplay = true;
	},
	getImage: function(inIndex) {
		return this.$.hats.getClientControls()[inIndex].hasNode();
	},
	getType: function() {
		return enyo.irand(this.$.hats.getClientControls().length);
	},
	scale: function() {
		var b = this.getBounds();
		var h = b.height;
		var w = b.width;
		if (w < this.rows * 36 || h < (this.rows+1) * 36) {
			this.hatsize = 28;
			this.hatmargin = 4;
		} else if (w < this.rows * 56 || h < (this.rows+1) * 56) {
			this.hatsize = 32;
			this.hatmargin = 4;
		} else if (w > this.rows * 100 && h > (this.rows+1) * 100) {
			this.hatsize = 62;
			this.hatmargin = 10;
		} else {
			this.hatsize = 48;
			this.hatmargin = 8;
		}
		var s = (this.hatsize + this.hatmargin) * this.rows;
		this.$.title.applyStyle("width", s + "px");
		this.$.title.applyStyle("height", s/10 + "px");
		this.$.score.applyStyle("line-height", s/10 + "px");
		this.$.background.bounds.w = s;
		this.$.background.bounds.h = s;
		this.$.selector.setSize(this.hatsize);
		this.$.selector.setMargin(this.hatmargin);
		var hc = this.$.hatbox.getClientControls();
		for (var i = 0, h; h = hc[i]; i++) {
			h.setSize(this.hatsize);
			h.setMargin(this.hatmargin);
			h.iChanged();
			h.jChanged();
		}
		for (var i = 0, c; c = ["background", "select", "hat"][i]; i++) {
			this.$[c+"box"].setAttribute("width", s);
			this.$[c+"box"].setAttribute("height", s);
			this.$[c+"box"].update();
		}
	},
	initHats: function() {
		this.scale();
		this.$.hatbox.destroyClientControls();
		var col;
		this.map = [];
		var src, t, l;
		for (var i = 0; i < this.rows; i++) {
			// i = which column = x = left
			col = this.map[i] = [];
			for (var j = 0; j < this.rows; j++) {
				// j = which row = y = top
				var nhat = this.newHat(i,j);
				col.push(nhat);
			}
		}
		this.playSound(-1);
		this.start();
		this.splatMatches(this.checkMatches());
	},
	start: function() {
		this.pulse = setInterval(enyo.bind(this, "heartbeat"), 30);
	},
	stop: function() {
		clearInterval(this.pulse);
	},
	playSound: function(inNum, inUserEvent) {
		var iosplay = this.ios ? inUserEvent : true;
		if (this.canplay && iosplay) {
			this.canplay = false;
			var n;
			var delay = 0;
			if (inNum >= 5) {
				n = this.$.fiveplus;
				delay = 2800;
			} else if (inNum == 4) {
				n = this.$.four;
				delay = 800;
			} else if (inNum <= 3 && inNum > 0) {
				n = this.$.three;
				delay = 100;
			} else if (inNum == -1) {
				n = this.$.theme;
				delay = 6000;
			} else {
				n = this.$.whiff;
				delay = 2000;
			}
			n.play();
			enyo.job(this.id+"enableSound", enyo.bind(this,"endedHandler"), delay);
		}
	},
	hatTap: function(inSender, inEvent) {
		var t = inEvent.target;
		var x = inEvent.pageX - t.offsetLeft;
		var y = inEvent.pageY - t.offsetTop;
		var col = Math.floor(x / (this.hatsize + this.hatmargin));
		var row = Math.floor(y / (this.hatsize + this.hatmargin));
		var oh = this.map[col][row];
		var matches = 0;
		if (oh.animating) {
			return;
		}
		if (!this.selected) {
			this.selected = oh;
			this.$.selector.show(col, row);
		} else {
			var d = this.selected.distance(oh);
			// manhattan distance
			var md = Math.abs(d.di) + Math.abs(d.dj);
			if (md == 1) {
				matches = this.exchange(this.selected, oh);
			}
			// don't play sound if you tap the selected square again
			if (md != 0) {
				this.playSound(matches, true);
			}
			this.selected = null;
			this.$.selector.hide();
		}
		this.$.selectbox.update();
	},
	distance: function(inHatA, inHatB) {
		return Math.abs(inHatA.i - inHatB.i) + Math.abs(inHatA.j - inHatB.j);
	},
	exchange: function(inA, inB) {
		var d = inA.distance(inB);
		var na = {i: inA.i + d.di, j: inA.j + d.dj};
		var nb = {i: inB.i - d.di, j: inB.j - d.dj};
		this.map[na.i][na.j] = inA;
		this.map[nb.i][nb.j] = inB;
		var matches = this.checkMatches();
		if (matches.length) {
			if (d.di) {
				this.moves.push(inA.moveX(d.di));
				this.moves.push(inB.moveX(-d.di));
			} else {
				this.moves.push(inA.moveY(d.dj));
				this.moves.push(inB.moveY(-d.dj));
			}
		}
		this.map[inA.i][inA.j] = inA;
		this.map[inB.i][inB.j] = inB;
		return matches.length;
	},
	checkMatches: function() {
		var matches = [];
		this._checkMatches(
			enyo.bind(this,"get"),
			enyo.bind(this,"make"),
			matches
		);
		this._checkMatches(
			enyo.bind(this,"rget"),
			enyo.bind(this,"rmake"),
			matches
		);
		return matches;
	},
	get: function(a,b) {
		return this.map[a][b].type;
	},
	rget: function(a,b) {
		return this.map[b][a].type;
	},
	make: function(a,b) {
		return {i:a,j:b};
	},
	rmake: function(a,b) {
		return {i:b,j:a};
	},
	_checkMatches: function(get, make, matches) {
		for (var i=0, t, c, k0; i<this.rows; i++) {
			c = 0;
			t = -1;
			for (var j=0, tt; j<this.rows; j++) {
				tt = get(i, j);
				if (t == -1) {
					t = tt;
					continue;
				}
				if (tt == t) {
					c++;
				}
				if (tt != t || j == this.rows-1) {
					k0 = j - c - 1;
					if (c >= 2) {
						if (j == this.rows-1 && tt == t) {
							k0++;
						}
						this.score += Math.pow(c,2) * 50;
						for (var k=k0; c>-1; k++,c--) {
							matches.push(make(i, k));
						}
					}
					c = 0;
					t = tt;
				}
			}
		}
	},
	splatMatches: function(inMatches) {
		for (var i=0, m; m=inMatches[i]; i++) {
			this.splat(m.i, m.j);
		}
		if (inMatches.length) {
			this.playSound(inMatches.length);
		}
		this.$.score.setContent(this.score);
	},
	splat: function(i, j) {
		var hat0 = this.map[i][j];
		if (hat0.animating) {
			return;
		}
		this.map[hat0.i][hat0.j] = null;
		for (var i=hat0.i, j=hat0.j-1; j>=0; j--) {
			var hat = this.map[i][j];
			if (hat) {
				this.map[i][j] = null;
				this.map[i][j+1] = hat;
				this.moves.push(hat.moveDown());
			}
		}
		var nhat = this.map[hat0.i][0] = this.newHat(hat0.i, -1);
		this.moves.push(nhat.moveDown());
		this.moves.push(hat0.splat());
	},
	heartbeat: function() {
		if (this.moves.length) {
			var live = [];
			for (var i = 0, m; m = this.moves[i]; i++) {
				if (m.move()) {
					live.push(m);
				}
			}
			this.moves = live;
			if (this.moves.length == 0) {
				this.splatMatches(this.checkMatches());
				// stabilze board
				var hc = this.$.hatbox.getClientControls();
				for (var i = 0, h; h = hc[i]; i++) {
					h.iChanged();
					h.jChanged();
				}
			}
			this.$.hatbox.update();
		}
	},
	newHat: function(i,j) {
		var type = this.getType()
		var image = this.getImage(type);
		return this.$.hatbox.createComponent({kind: "Hat", i: i, j: j, owner: this, image:image, type:type, bounds:{}, size:this.hatsize, margin:this.hatmargin});
	},
	resizeHandler: function() {
		enyo.job(this.id + "resize", enyo.bind(this, "rescale"), 100);
	},
	rescale: function() {
		this.stop();
		this.scale();
		this.start();
	},
	touchstartHandler: function() {
		if (this.ios && !this.iosfirstsound) {
			this.iosfirstsound = true;
			this.playSound(-1, true);
		}
	}
});
<commit_msg>remove set style from title<commit_after>enyo.kind({
	name:"App",
	kind:"Control",
	hatsize: 48,
	hatmargin: 8,
	rows: 10,
	score: 0,
	canplay: true,
	moves: [],
	components:[
		{name:"bottom", classes:"overlap center bottom"},
		{name:"hats", style:"display: none;", components: [
			{kind:"Image", onload:"loadHandler", src:"images/game_bear.png"},
			{kind:"Image", onload:"loadHandler", src:"images/game_bunny_02.png"},
			{kind:"Image", onload:"loadHandler", src:"images/game_carrot.png"},
			{kind:"Image", onload:"loadHandler", src:"images/game_lemon.png"},
			{kind:"Image", onload:"loadHandler", src:"images/game_panda.png"},
			{kind:"Image", onload:"loadHandler", src:"images/game_piratePig.png"},
		]},
		// why can't there just be one standard that isn't wav?
		{name:"sounds", style:"display: none;", components:[
			{name:"three", kind:"Audio", src:["sounds/3.ogg", "sounds/3.mp3", "sounds/3.wav"], onEnded: "endedHandler"},
			{name:"four", kind:"Audio", src:["sounds/4.ogg", "sounds/4.mp3", "sounds/4.wav"], onEnded: "endedHandler"},
			{name:"fiveplus", kind:"Audio", src:["sounds/5.ogg", "sounds/5.mp3", "sounds/5.wav"], onEnded: "endedHandler"},
			{name:"whiff", kind:"Audio", src:["sounds/whiff.ogg", "sounds/whiff.mp3", "sounds/whiff.wav"], onEnded:"endedHandler"},
			{name:"theme", kind:"Audio", src:["sounds/theme.ogg", "sounds/theme.mp3", "sounds/theme.wav"], onEnded:"endedHandler"}
		]},
		{name:"title", classes:"hcenter banner", components:[
			{name:"score", classes:"score", content:"0"},
		]},
		{name:"backgroundbox", kind:"Canvas", attributes:{height:"560px", width:"560px"}, classes:"overlap hcenter", components:[
			{name:"background", kind:"canvas.Rectangle", bounds:{t:0, l:0, w:560, h:560}, color:"rgba(255,255,255,0.9)"},
		]},
		{name:"selectbox", kind:"Canvas", attributes:{height:"560px", width:"560px"}, classes:"overlap hcenter", components:[
			{name:"selector", kind:"Selector", color:"red"}
		]},
		{name:"hatbox", kind:"Canvas", attributes:{height:"560px", width:"560px"}, classes:"overlap hcenter border", ontap:"hatTap"}
	],
	create: function() {
		this.inherited(arguments);
		this.addClass("bg");
		// sounds only occur on user actions on ios
		if (navigator.userAgent.match(/i(?:pad|phone)/i)) {
			this.ios = true;
		}
	},
	loadHandler: function() {
		this.loaded = (this.loaded || 0) + 1;
		if (this.loaded == this.$.hats.getClientControls().length) {
			this.initHats();
		}
	},
	endedHandler: function() {
		enyo.job.stop(this.id + "enableSound");
		this.canplay = true;
	},
	getImage: function(inIndex) {
		return this.$.hats.getClientControls()[inIndex].hasNode();
	},
	getType: function() {
		return enyo.irand(this.$.hats.getClientControls().length);
	},
	scale: function() {
		var b = this.getBounds();
		var h = b.height;
		var w = b.width;
		if (w < this.rows * 36 || h < (this.rows+1) * 36) {
			this.hatsize = 28;
			this.hatmargin = 4;
		} else if (w < this.rows * 56 || h < (this.rows+1) * 56) {
			this.hatsize = 32;
			this.hatmargin = 4;
		} else if (w > this.rows * 100 && h > (this.rows+1) * 100) {
			this.hatsize = 62;
			this.hatmargin = 10;
		} else {
			this.hatsize = 48;
			this.hatmargin = 8;
		}
		var s = (this.hatsize + this.hatmargin) * this.rows;
		this.$.title.applyStyle("width", s + "px");
		this.$.title.applyStyle("height", s/10 + "px");
		this.$.score.applyStyle("line-height", s/10 + "px");
		this.$.background.bounds.w = s;
		this.$.background.bounds.h = s;
		this.$.selector.setSize(this.hatsize);
		this.$.selector.setMargin(this.hatmargin);
		var hc = this.$.hatbox.getClientControls();
		for (var i = 0, h; h = hc[i]; i++) {
			h.setSize(this.hatsize);
			h.setMargin(this.hatmargin);
			h.iChanged();
			h.jChanged();
		}
		for (var i = 0, c; c = ["background", "select", "hat"][i]; i++) {
			this.$[c+"box"].setAttribute("width", s);
			this.$[c+"box"].setAttribute("height", s);
			this.$[c+"box"].update();
		}
	},
	initHats: function() {
		this.scale();
		this.$.hatbox.destroyClientControls();
		var col;
		this.map = [];
		var src, t, l;
		for (var i = 0; i < this.rows; i++) {
			// i = which column = x = left
			col = this.map[i] = [];
			for (var j = 0; j < this.rows; j++) {
				// j = which row = y = top
				var nhat = this.newHat(i,j);
				col.push(nhat);
			}
		}
		this.playSound(-1);
		this.start();
		this.splatMatches(this.checkMatches());
	},
	start: function() {
		this.pulse = setInterval(enyo.bind(this, "heartbeat"), 30);
	},
	stop: function() {
		clearInterval(this.pulse);
	},
	playSound: function(inNum, inUserEvent) {
		var iosplay = this.ios ? inUserEvent : true;
		if (this.canplay && iosplay) {
			this.canplay = false;
			var n;
			var delay = 0;
			if (inNum >= 5) {
				n = this.$.fiveplus;
				delay = 2800;
			} else if (inNum == 4) {
				n = this.$.four;
				delay = 800;
			} else if (inNum <= 3 && inNum > 0) {
				n = this.$.three;
				delay = 100;
			} else if (inNum == -1) {
				n = this.$.theme;
				delay = 6000;
			} else {
				n = this.$.whiff;
				delay = 2000;
			}
			n.play();
			enyo.job(this.id+"enableSound", enyo.bind(this,"endedHandler"), delay);
		}
	},
	hatTap: function(inSender, inEvent) {
		var t = inEvent.target;
		var x = inEvent.pageX - t.offsetLeft;
		var y = inEvent.pageY - t.offsetTop;
		var col = Math.floor(x / (this.hatsize + this.hatmargin));
		var row = Math.floor(y / (this.hatsize + this.hatmargin));
		var oh = this.map[col][row];
		var matches = 0;
		if (oh.animating) {
			return;
		}
		if (!this.selected) {
			this.selected = oh;
			this.$.selector.show(col, row);
		} else {
			var d = this.selected.distance(oh);
			// manhattan distance
			var md = Math.abs(d.di) + Math.abs(d.dj);
			if (md == 1) {
				matches = this.exchange(this.selected, oh);
			}
			// don't play sound if you tap the selected square again
			if (md != 0) {
				this.playSound(matches, true);
			}
			this.selected = null;
			this.$.selector.hide();
		}
		this.$.selectbox.update();
	},
	distance: function(inHatA, inHatB) {
		return Math.abs(inHatA.i - inHatB.i) + Math.abs(inHatA.j - inHatB.j);
	},
	exchange: function(inA, inB) {
		var d = inA.distance(inB);
		var na = {i: inA.i + d.di, j: inA.j + d.dj};
		var nb = {i: inB.i - d.di, j: inB.j - d.dj};
		this.map[na.i][na.j] = inA;
		this.map[nb.i][nb.j] = inB;
		var matches = this.checkMatches();
		if (matches.length) {
			if (d.di) {
				this.moves.push(inA.moveX(d.di));
				this.moves.push(inB.moveX(-d.di));
			} else {
				this.moves.push(inA.moveY(d.dj));
				this.moves.push(inB.moveY(-d.dj));
			}
		}
		this.map[inA.i][inA.j] = inA;
		this.map[inB.i][inB.j] = inB;
		return matches.length;
	},
	checkMatches: function() {
		var matches = [];
		this._checkMatches(
			enyo.bind(this,"get"),
			enyo.bind(this,"make"),
			matches
		);
		this._checkMatches(
			enyo.bind(this,"rget"),
			enyo.bind(this,"rmake"),
			matches
		);
		return matches;
	},
	get: function(a,b) {
		return this.map[a][b].type;
	},
	rget: function(a,b) {
		return this.map[b][a].type;
	},
	make: function(a,b) {
		return {i:a,j:b};
	},
	rmake: function(a,b) {
		return {i:b,j:a};
	},
	_checkMatches: function(get, make, matches) {
		for (var i=0, t, c, k0; i<this.rows; i++) {
			c = 0;
			t = -1;
			for (var j=0, tt; j<this.rows; j++) {
				tt = get(i, j);
				if (t == -1) {
					t = tt;
					continue;
				}
				if (tt == t) {
					c++;
				}
				if (tt != t || j == this.rows-1) {
					k0 = j - c - 1;
					if (c >= 2) {
						if (j == this.rows-1 && tt == t) {
							k0++;
						}
						this.score += Math.pow(c,2) * 50;
						for (var k=k0; c>-1; k++,c--) {
							matches.push(make(i, k));
						}
					}
					c = 0;
					t = tt;
				}
			}
		}
	},
	splatMatches: function(inMatches) {
		for (var i=0, m; m=inMatches[i]; i++) {
			this.splat(m.i, m.j);
		}
		if (inMatches.length) {
			this.playSound(inMatches.length);
		}
		this.$.score.setContent(this.score);
	},
	splat: function(i, j) {
		var hat0 = this.map[i][j];
		if (hat0.animating) {
			return;
		}
		this.map[hat0.i][hat0.j] = null;
		for (var i=hat0.i, j=hat0.j-1; j>=0; j--) {
			var hat = this.map[i][j];
			if (hat) {
				this.map[i][j] = null;
				this.map[i][j+1] = hat;
				this.moves.push(hat.moveDown());
			}
		}
		var nhat = this.map[hat0.i][0] = this.newHat(hat0.i, -1);
		this.moves.push(nhat.moveDown());
		this.moves.push(hat0.splat());
	},
	heartbeat: function() {
		if (this.moves.length) {
			var live = [];
			for (var i = 0, m; m = this.moves[i]; i++) {
				if (m.move()) {
					live.push(m);
				}
			}
			this.moves = live;
			if (this.moves.length == 0) {
				this.splatMatches(this.checkMatches());
				// stabilze board
				var hc = this.$.hatbox.getClientControls();
				for (var i = 0, h; h = hc[i]; i++) {
					h.iChanged();
					h.jChanged();
				}
			}
			this.$.hatbox.update();
		}
	},
	newHat: function(i,j) {
		var type = this.getType()
		var image = this.getImage(type);
		return this.$.hatbox.createComponent({kind: "Hat", i: i, j: j, owner: this, image:image, type:type, bounds:{}, size:this.hatsize, margin:this.hatmargin});
	},
	resizeHandler: function() {
		enyo.job(this.id + "resize", enyo.bind(this, "rescale"), 100);
	},
	rescale: function() {
		this.stop();
		this.scale();
		this.start();
	},
	touchstartHandler: function() {
		if (this.ios && !this.iosfirstsound) {
			this.iosfirstsound = true;
			this.playSound(-1, true);
		}
	}
});
<|endoftext|>