",
+ options: {
+ disabled: false,
+
+ // callbacks
+ create: null
+ },
+ _createWidget: function (options, element) {
+ element = $(element || this.defaultElement || this)[0];
+ this.element = $(element);
+ this.uuid = widget_uuid++;
+ this.eventNamespace = "." + this.widgetName + this.uuid;
+
+ this.bindings = $();
+ this.hoverable = $();
+ this.focusable = $();
+
+ if (element !== this) {
+ $.data(element, this.widgetFullName, this);
+ this._on(true, this.element, {
+ remove: function (event) {
+ if (event.target === element) {
+ this.destroy();
+ }
+ }
+ });
+ this.document = $(element.style ?
+ // element within the document
+ element.ownerDocument :
+ // element is window or document
+ element.document || element);
+ this.window = $(this.document[0].defaultView || this.document[0].parentWindow);
+ }
+
+ this.options = $.widget.extend({},
+ this.options,
+ this._getCreateOptions(),
+ options);
+
+ this._create();
+ this._trigger("create", null, this._getCreateEventData());
+ this._init();
+ },
+ _getCreateOptions: $.noop,
+ _getCreateEventData: $.noop,
+ _create: $.noop,
+ _init: $.noop,
+
+ destroy: function () {
+ this._destroy();
+ // we can probably remove the unbind calls in 2.0
+ // all event bindings should go through this._on()
+ this.element
+ .unbind(this.eventNamespace)
+ .removeData(this.widgetFullName)
+ // support: jquery <1.6.3
+ // http://bugs.jquery.com/ticket/9413
+ .removeData($.camelCase(this.widgetFullName));
+ this.widget()
+ .unbind(this.eventNamespace)
+ .removeAttr("aria-disabled")
+ .removeClass(
+ this.widgetFullName + "-disabled " +
+ "ui-state-disabled");
+
+ // clean up events and states
+ this.bindings.unbind(this.eventNamespace);
+ this.hoverable.removeClass("ui-state-hover");
+ this.focusable.removeClass("ui-state-focus");
+ },
+ _destroy: $.noop,
+
+ widget: function () {
+ return this.element;
+ },
+
+ option: function (key, value) {
+ var options = key,
+ parts,
+ curOption,
+ i;
+
+ if (arguments.length === 0) {
+ // don't return a reference to the internal hash
+ return $.widget.extend({}, this.options);
+ }
+
+ if (typeof key === "string") {
+ // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
+ options = {};
+ parts = key.split(".");
+ key = parts.shift();
+ if (parts.length) {
+ curOption = options[key] = $.widget.extend({}, this.options[key]);
+ for (i = 0; i < parts.length - 1; i++) {
+ curOption[parts[i]] = curOption[parts[i]] || {};
+ curOption = curOption[parts[i]];
+ }
+ key = parts.pop();
+ if (arguments.length === 1) {
+ return curOption[key] === undefined ? null : curOption[key];
+ }
+ curOption[key] = value;
+ } else {
+ if (arguments.length === 1) {
+ return this.options[key] === undefined ? null : this.options[key];
+ }
+ options[key] = value;
+ }
+ }
+
+ this._setOptions(options);
+
+ return this;
+ },
+ _setOptions: function (options) {
+ var key;
+
+ for (key in options) {
+ this._setOption(key, options[key]);
+ }
+
+ return this;
+ },
+ _setOption: function (key, value) {
+ this.options[key] = value;
+
+ if (key === "disabled") {
+ this.widget()
+ .toggleClass(this.widgetFullName + "-disabled", !!value);
+
+ // If the widget is becoming disabled, then nothing is interactive
+ if (value) {
+ this.hoverable.removeClass("ui-state-hover");
+ this.focusable.removeClass("ui-state-focus");
+ }
+ }
+
+ return this;
+ },
+
+ enable: function () {
+ return this._setOptions({disabled: false});
+ },
+ disable: function () {
+ return this._setOptions({disabled: true});
+ },
+
+ _on: function (suppressDisabledCheck, element, handlers) {
+ var delegateElement,
+ instance = this;
+
+ // no suppressDisabledCheck flag, shuffle arguments
+ if (typeof suppressDisabledCheck !== "boolean") {
+ handlers = element;
+ element = suppressDisabledCheck;
+ suppressDisabledCheck = false;
+ }
+
+ // no element argument, shuffle and use this.element
+ if (!handlers) {
+ handlers = element;
+ element = this.element;
+ delegateElement = this.widget();
+ } else {
+ element = delegateElement = $(element);
+ this.bindings = this.bindings.add(element);
+ }
+
+ $.each(handlers, function (event, handler) {
+ function handlerProxy() {
+ // allow widgets to customize the disabled handling
+ // - disabled as an array instead of boolean
+ // - disabled class as method for disabling individual parts
+ if (!suppressDisabledCheck &&
+ ( instance.options.disabled === true ||
+ $(this).hasClass("ui-state-disabled") )) {
+ return;
+ }
+ return ( typeof handler === "string" ? instance[handler] : handler )
+ .apply(instance, arguments);
+ }
+
+ // copy the guid so direct unbinding works
+ if (typeof handler !== "string") {
+ handlerProxy.guid = handler.guid =
+ handler.guid || handlerProxy.guid || $.guid++;
+ }
+
+ var match = event.match(/^([\w:-]*)\s*(.*)$/),
+ eventName = match[1] + instance.eventNamespace,
+ selector = match[2];
+ if (selector) {
+ delegateElement.delegate(selector, eventName, handlerProxy);
+ } else {
+ element.bind(eventName, handlerProxy);
+ }
+ });
+ },
+
+ _off: function (element, eventName) {
+ eventName = (eventName || "").split(" ").join(this.eventNamespace + " ") +
+ this.eventNamespace;
+ element.unbind(eventName).undelegate(eventName);
+
+ // Clear the stack to avoid memory leaks (#10056)
+ this.bindings = $(this.bindings.not(element).get());
+ this.focusable = $(this.focusable.not(element).get());
+ this.hoverable = $(this.hoverable.not(element).get());
+ },
+
+ _delay: function (handler, delay) {
+ function handlerProxy() {
+ return ( typeof handler === "string" ? instance[handler] : handler )
+ .apply(instance, arguments);
+ }
+
+ var instance = this;
+ return setTimeout(handlerProxy, delay || 0);
+ },
+
+ _hoverable: function (element) {
+ this.hoverable = this.hoverable.add(element);
+ this._on(element, {
+ mouseenter: function (event) {
+ $(event.currentTarget).addClass("ui-state-hover");
+ },
+ mouseleave: function (event) {
+ $(event.currentTarget).removeClass("ui-state-hover");
+ }
+ });
+ },
+
+ _focusable: function (element) {
+ this.focusable = this.focusable.add(element);
+ this._on(element, {
+ focusin: function (event) {
+ $(event.currentTarget).addClass("ui-state-focus");
+ },
+ focusout: function (event) {
+ $(event.currentTarget).removeClass("ui-state-focus");
+ }
+ });
+ },
+
+ _trigger: function (type, event, data) {
+ var prop, orig,
+ callback = this.options[type];
+
+ data = data || {};
+ event = $.Event(event);
+ event.type = ( type === this.widgetEventPrefix ?
+ type :
+ this.widgetEventPrefix + type ).toLowerCase();
+ // the original event may come from any element
+ // so we need to reset the target on the new event
+ event.target = this.element[0];
+
+ // copy original event properties over to the new event
+ orig = event.originalEvent;
+ if (orig) {
+ for (prop in orig) {
+ if (!( prop in event )) {
+ event[prop] = orig[prop];
+ }
+ }
+ }
+
+ this.element.trigger(event, data);
+ return !( $.isFunction(callback) &&
+ callback.apply(this.element[0], [event].concat(data)) === false ||
+ event.isDefaultPrevented() );
+ }
+};
+
+$.each({show: "fadeIn", hide: "fadeOut"}, function (method, defaultEffect) {
+ $.Widget.prototype["_" + method] = function (element, options, callback) {
+ if (typeof options === "string") {
+ options = {effect: options};
+ }
+ var hasOptions,
+ effectName = !options ?
+ method :
+ options === true || typeof options === "number" ?
+ defaultEffect :
+ options.effect || defaultEffect;
+ options = options || {};
+ if (typeof options === "number") {
+ options = {duration: options};
+ }
+ hasOptions = !$.isEmptyObject(options);
+ options.complete = callback;
+ if (options.delay) {
+ element.delay(options.delay);
+ }
+ if (hasOptions && $.effects && $.effects.effect[effectName]) {
+ element[method](options);
+ } else if (effectName !== method && element[effectName]) {
+ element[effectName](options.duration, options.easing, callback);
+ } else {
+ element.queue(function (next) {
+ $(this)[method]();
+ if (callback) {
+ callback.call(element[0]);
+ }
+ next();
+ });
+ }
+ };
+});
+
+var widget = $.widget;
+
+// Source: js/initiator.js
+$.fn.reverse = Array.prototype.reverse;
+
+$.Metro = function(params){
+ params = $.extend({
+ }, params);
+};
+
+$.Metro.hotkeys = [];
+
+$.Metro.initWidgets = function(){
+ var widgets = $("[data-role]");
+
+ var hotkeys = $("[data-hotkey]");
+ $.each(hotkeys, function(){
+ var element = $(this);
+ var hotkey = element.data('hotkey').toLowerCase();
+
+ //if ($.Metro.hotkeys.indexOf(hotkey) > -1) {
+ // return;
+ //}
+ if (element.data('hotKeyBonded') === true ) {
+ return;
+ }
+
+ $.Metro.hotkeys.push(hotkey);
+
+ $(document).on('keyup', null, hotkey, function(e){
+ if (element === undefined) return;
+
+ if (element[0].tagName === 'A' &&
+ element.attr('href') !== undefined &&
+ element.attr('href').trim() !== '' &&
+ element.attr('href').trim() !== '#') {
+ document.location.href = element.attr('href');
+ } else {
+ element.click();
+ }
+ return false;
+ });
+
+ element.data('hotKeyBonded', true);
+ });
+
+ $.each(widgets, function(){
+ var $this = $(this), w = this;
+ var roles = $this.data('role').split(/\s*,\s*/);
+ roles.map(function(func){
+ try {
+ //$(w)[func]();
+ if ($.fn[func] !== undefined && $this.data(func+'-initiated') !== true) {
+ $.fn[func].call($this);
+ $this.data(func+'-initiated', true);
+ }
+ } catch(e) {
+ if (window.METRO_DEBUG) {
+ console.log(e.message, e.stack);
+ }
+ }
+ });
+ });
+};
+
+$.Metro.init = function(){
+ $.Metro.initWidgets();
+
+ if (window.METRO_AUTO_REINIT) {
+ if (!window.canObserveMutation) {
+ var originalDOM = $('body').html(),
+ actualDOM;
+
+ setInterval(function () {
+ actualDOM = $('body').html();
+
+ if (originalDOM !== actualDOM) {
+ originalDOM = actualDOM;
+
+ $.Metro.initWidgets();
+ }
+ }, 100);
+ } else {
+ var observer, observerOptions, observerCallback;
+ observerOptions = {
+ 'childList': true,
+ 'subtree': true
+ };
+ observerCallback = function(mutations){
+
+ //console.log(mutations);
+
+ mutations.map(function(record){
+
+ if (record.addedNodes) {
+
+ /*jshint loopfunc: true */
+ var obj, widgets, plugins, hotkeys;
+
+ for(var i = 0, l = record.addedNodes.length; i < l; i++) {
+ obj = $(record.addedNodes[i]);
+
+ plugins = obj.find("[data-role]");
+
+ hotkeys = obj.find("[data-hotkey]");
+
+ $.each(hotkeys, function(){
+ var element = $(this);
+ var hotkey = element.data('hotkey').toLowerCase();
+
+ //if ($.Metro.hotkeys.indexOf(hotkey) > -1) {
+ // return;
+ //}
+
+ if (element.data('hotKeyBonded') === true ) {
+ return;
+ }
+
+ $.Metro.hotkeys.push(hotkey);
+
+ $(document).on('keyup', null, hotkey, function () {
+ if (element === undefined) return;
+
+ if (element[0].tagName === 'A' &&
+ element.attr('href') !== undefined &&
+ element.attr('href').trim() !== '' &&
+ element.attr('href').trim() !== '#') {
+ document.location.href = element.attr('href');
+ } else {
+ element.click();
+ }
+ return false;
+ });
+
+ element.data('hotKeyBonded', true);
+ //console.log($.Metro.hotkeys);
+ });
+
+ if (obj.data('role') !== undefined) {
+ widgets = $.merge(plugins, obj);
+ } else {
+ widgets = plugins;
+ }
+
+ if (widgets.length) {
+ $.each(widgets, function(){
+ var _this = $(this);
+ var roles = _this.data('role').split(/\s*,\s*/);
+ roles.map(function(func){
+ try {
+ if ($.fn[func] !== undefined && _this.data(func+'-initiated') !== true) {
+ $.fn[func].call(_this);
+ _this.data(func+'-initiated', true);
+ }
+ } catch(e) {
+ if (window.METRO_DEBUG) {
+ console.log(e.message, e.stack);
+ }
+ }
+ });
+ });
+ }
+ }
+ }
+ });
+ };
+
+ //console.log($(document));
+ observer = new MutationObserver(observerCallback);
+ observer.observe(document, observerOptions);
+ }
+ }
+};
+
+// Source: js/utils/easing.js
+ $.easing['jswing'] = $.easing['swing'];
+
+ $.extend($.easing, {
+ def: 'easeOutQuad',
+ swing: function (x, t, b, c, d) {
+ //alert($.easing.default);
+ return $.easing[$.easing.def](x, t, b, c, d);
+ },
+ easeInQuad: function (x, t, b, c, d) {
+ return c * (t /= d) * t + b;
+ },
+ easeOutQuad: function (x, t, b, c, d) {
+ return -c * (t /= d) * (t - 2) + b;
+ },
+ easeInOutQuad: function (x, t, b, c, d) {
+ if ((t /= d / 2) < 1) return c / 2 * t * t + b;
+ return -c / 2 * ((--t) * (t - 2) - 1) + b;
+ },
+ easeInCubic: function (x, t, b, c, d) {
+ return c * (t /= d) * t * t + b;
+ },
+ easeOutCubic: function (x, t, b, c, d) {
+ return c * ((t = t / d - 1) * t * t + 1) + b;
+ },
+ easeInOutCubic: function (x, t, b, c, d) {
+ if ((t /= d / 2) < 1) return c / 2 * t * t * t + b;
+ return c / 2 * ((t -= 2) * t * t + 2) + b;
+ },
+ easeInQuart: function (x, t, b, c, d) {
+ return c * (t /= d) * t * t * t + b;
+ },
+ easeOutQuart: function (x, t, b, c, d) {
+ return -c * ((t = t / d - 1) * t * t * t - 1) + b;
+ },
+ easeInOutQuart: function (x, t, b, c, d) {
+ if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;
+ return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
+ },
+ easeInQuint: function (x, t, b, c, d) {
+ return c * (t /= d) * t * t * t * t + b;
+ },
+ easeOutQuint: function (x, t, b, c, d) {
+ return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
+ },
+ easeInOutQuint: function (x, t, b, c, d) {
+ if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b;
+ return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
+ },
+ easeInSine: function (x, t, b, c, d) {
+ return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;
+ },
+ easeOutSine: function (x, t, b, c, d) {
+ return c * Math.sin(t / d * (Math.PI / 2)) + b;
+ },
+ easeInOutSine: function (x, t, b, c, d) {
+ return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
+ },
+ easeInExpo: function (x, t, b, c, d) {
+ return (t == 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;
+ },
+ easeOutExpo: function (x, t, b, c, d) {
+ return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
+ },
+ easeInOutExpo: function (x, t, b, c, d) {
+ if (t == 0) return b;
+ if (t == d) return b + c;
+ if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
+ return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
+ },
+ easeInCirc: function (x, t, b, c, d) {
+ return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
+ },
+ easeOutCirc: function (x, t, b, c, d) {
+ return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;
+ },
+ easeInOutCirc: function (x, t, b, c, d) {
+ if ((t /= d / 2) < 1) return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
+ return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
+ },
+ easeInElastic: function (x, t, b, c, d) {
+ var s = 1.70158;
+ var p = 0;
+ var a = c;
+ if (t == 0) return b;
+ if ((t /= d) == 1) return b + c;
+ if (!p) p = d * .3;
+ if (a < Math.abs(c)) {
+ a = c;
+ s = p / 4;
+ }
+ else s = p / (2 * Math.PI) * Math.asin(c / a);
+ return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
+ },
+ easeOutElastic: function (x, t, b, c, d) {
+ var s = 1.70158;
+ var p = 0;
+ var a = c;
+ if (t == 0) return b;
+ if ((t /= d) == 1) return b + c;
+ if (!p) p = d * .3;
+ if (a < Math.abs(c)) {
+ a = c;
+ s = p / 4;
+ }
+ else s = p / (2 * Math.PI) * Math.asin(c / a);
+ return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
+ },
+ easeInOutElastic: function (x, t, b, c, d) {
+ var s = 1.70158;
+ var p = 0;
+ var a = c;
+ if (t == 0) return b;
+ if ((t /= d / 2) == 2) return b + c;
+ if (!p) p = d * (.3 * 1.5);
+ if (a < Math.abs(c)) {
+ a = c;
+ s = p / 4;
+ }
+ else s = p / (2 * Math.PI) * Math.asin(c / a);
+ if (t < 1) return -.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
+ return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
+ },
+ easeInBack: function (x, t, b, c, d, s) {
+ if (s == undefined) s = 1.70158;
+ return c * (t /= d) * t * ((s + 1) * t - s) + b;
+ },
+ easeOutBack: function (x, t, b, c, d, s) {
+ if (s == undefined) s = 1.70158;
+ return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
+ },
+ easeInOutBack: function (x, t, b, c, d, s) {
+ if (s == undefined) s = 1.70158;
+ if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
+ return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
+ },
+ easeInBounce: function (x, t, b, c, d) {
+ return c - $.easing.easeOutBounce(x, d - t, 0, c, d) + b;
+ },
+ easeOutBounce: function (x, t, b, c, d) {
+ if ((t /= d) < (1 / 2.75)) {
+ return c * (7.5625 * t * t) + b;
+ } else if (t < (2 / 2.75)) {
+ return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
+ } else if (t < (2.5 / 2.75)) {
+ return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
+ } else {
+ return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
+ }
+ },
+ easeInOutBounce: function (x, t, b, c, d) {
+ if (t < d / 2) return $.easing.easeInBounce(x, t * 2, 0, c, d) * .5 + b;
+ return $.easing.easeOutBounce(x, t * 2 - d, 0, c, d) * .5 + c * .5 + b;
+ }
+});
+
+// Source: js/utils/hotkeys.js
+$.hotkeys = {
+ version: "0.8",
+
+ specialKeys: {
+ 8: "backspace",
+ 9: "tab",
+ 10: "return",
+ 13: "return",
+ 16: "shift",
+ 17: "ctrl",
+ 18: "alt",
+ 19: "pause",
+ 20: "capslock",
+ 27: "esc",
+ 32: "space",
+ 33: "pageup",
+ 34: "pagedown",
+ 35: "end",
+ 36: "home",
+ 37: "left",
+ 38: "up",
+ 39: "right",
+ 40: "down",
+ 45: "insert",
+ 46: "del",
+ 59: ";",
+ 61: "=",
+ 96: "0",
+ 97: "1",
+ 98: "2",
+ 99: "3",
+ 100: "4",
+ 101: "5",
+ 102: "6",
+ 103: "7",
+ 104: "8",
+ 105: "9",
+ 106: "*",
+ 107: "+",
+ 109: "-",
+ 110: ".",
+ 111: "/",
+ 112: "f1",
+ 113: "f2",
+ 114: "f3",
+ 115: "f4",
+ 116: "f5",
+ 117: "f6",
+ 118: "f7",
+ 119: "f8",
+ 120: "f9",
+ 121: "f10",
+ 122: "f11",
+ 123: "f12",
+ 144: "numlock",
+ 145: "scroll",
+ 173: "-",
+ 186: ";",
+ 187: "=",
+ 188: ",",
+ 189: "-",
+ 190: ".",
+ 191: "/",
+ 192: "`",
+ 219: "[",
+ 220: "\\",
+ 221: "]",
+ 222: "'"
+ },
+
+ shiftNums: {
+ "`": "~",
+ "1": "!",
+ "2": "@",
+ "3": "#",
+ "4": "$",
+ "5": "%",
+ "6": "^",
+ "7": "&",
+ "8": "*",
+ "9": "(",
+ "0": ")",
+ "-": "_",
+ "=": "+",
+ ";": ": ",
+ "'": "\"",
+ ",": "<",
+ ".": ">",
+ "/": "?",
+ "\\": "|"
+ },
+
+ // excludes: button, checkbox, file, hidden, image, password, radio, reset, search, submit, url
+ textAcceptingInputTypes: [
+ "text", "password", "number", "email", "url", "range", "date", "month", "week", "time", "datetime",
+ "datetime-local", "search", "color", "tel"],
+
+ // default input types not to bind to unless bound directly
+ textInputTypes: /textarea|input|select/i,
+
+ options: {
+ filterInputAcceptingElements: true,
+ filterTextInputs: true,
+ filterContentEditable: true
+ }
+};
+
+function keyHandler(handleObj) {
+ if (typeof handleObj.data === "string") {
+ handleObj.data = {
+ keys: handleObj.data
+ };
+ }
+
+ // Only care when a possible input has been specified
+ if (!handleObj.data || !handleObj.data.keys || typeof handleObj.data.keys !== "string") {
+ return;
+ }
+
+ var origHandler = handleObj.handler,
+ keys = handleObj.data.keys.toLowerCase().split(" ");
+
+ handleObj.handler = function(event) {
+ // Don't fire in text-accepting inputs that we didn't directly bind to
+ if (this !== event.target &&
+ ($.hotkeys.options.filterInputAcceptingElements &&
+ $.hotkeys.textInputTypes.test(event.target.nodeName) ||
+ ($.hotkeys.options.filterContentEditable && $(event.target).attr('contenteditable')) ||
+ ($.hotkeys.options.filterTextInputs &&
+ $.inArray(event.target.type, $.hotkeys.textAcceptingInputTypes) > -1))) {
+ return;
+ }
+
+ var special = event.type !== "keypress" && $.hotkeys.specialKeys[event.which],
+ character = String.fromCharCode(event.which).toLowerCase(),
+ modif = "",
+ possible = {};
+
+ $.each(["alt", "ctrl", "shift"], function(index, specialKey) {
+
+ if (event[specialKey + 'Key'] && special !== specialKey) {
+ modif += specialKey + '+';
+ }
+ });
+
+ // metaKey is triggered off ctrlKey erronously
+ if (event.metaKey && !event.ctrlKey && special !== "meta") {
+ modif += "meta+";
+ }
+
+ if (event.metaKey && special !== "meta" && modif.indexOf("alt+ctrl+shift+") > -1) {
+ modif = modif.replace("alt+ctrl+shift+", "hyper+");
+ }
+
+ if (special) {
+ possible[modif + special] = true;
+ }
+ else {
+ possible[modif + character] = true;
+ possible[modif + $.hotkeys.shiftNums[character]] = true;
+
+ // "$" can be triggered as "Shift+4" or "Shift+$" or just "$"
+ if (modif === "shift+") {
+ possible[$.hotkeys.shiftNums[character]] = true;
+ }
+ }
+
+ for (var i = 0, l = keys.length; i < l; i++) {
+ if (possible[keys[i]]) {
+ return origHandler.apply(this, arguments);
+ }
+ }
+ };
+}
+
+$.each(["keydown", "keyup", "keypress"], function() {
+ $.event.special[this] = {
+ add: keyHandler
+ };
+});
+
+// Source: js/utils/mousewheel.js
+var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'];
+var toBind = 'onwheel' in document || document.documentMode >= 9 ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'];
+var lowestDelta, lowestDeltaXY;
+
+if ( $.event.fixHooks ) {
+ for ( var i = toFix.length; i; ) {
+ $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
+ }
+}
+
+$.event.special.mousewheel = {
+ setup: function() {
+ if ( this.addEventListener ) {
+ for ( var i = toBind.length; i; ) {
+ this.addEventListener( toBind[--i], handler, false );
+ }
+ } else {
+ this.onmousewheel = handler;
+ }
+ },
+
+ teardown: function() {
+ if ( this.removeEventListener ) {
+ for ( var i = toBind.length; i; ) {
+ this.removeEventListener( toBind[--i], handler, false );
+ }
+ } else {
+ this.onmousewheel = null;
+ }
+ }
+};
+
+$.fn.extend({
+ mousewheel: function(fn) {
+ return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
+ },
+
+ unmousewheel: function(fn) {
+ return this.unbind("mousewheel", fn);
+ }
+});
+
+
+function handler(event) {
+ var orgEvent = event || window.event,
+ args = [].slice.call(arguments, 1),
+ delta = 0,
+ deltaX = 0,
+ deltaY = 0,
+ absDelta = 0,
+ absDeltaXY = 0,
+ fn;
+ event = $.event.fix(orgEvent);
+ event.type = "mousewheel";
+
+ // Old school scrollwheel delta
+ if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta; }
+ if ( orgEvent.detail ) { delta = orgEvent.detail * -1; }
+
+ // New school wheel delta (wheel event)
+ if ( orgEvent.deltaY ) {
+ deltaY = orgEvent.deltaY * -1;
+ delta = deltaY;
+ }
+ if ( orgEvent.deltaX ) {
+ deltaX = orgEvent.deltaX;
+ delta = deltaX * -1;
+ }
+
+ // Webkit
+ if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY; }
+ if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = orgEvent.wheelDeltaX * -1; }
+
+ // Look for lowest delta to normalize the delta values
+ absDelta = Math.abs(delta);
+ if ( !lowestDelta || absDelta < lowestDelta ) { lowestDelta = absDelta; }
+ absDeltaXY = Math.max(Math.abs(deltaY), Math.abs(deltaX));
+ if ( !lowestDeltaXY || absDeltaXY < lowestDeltaXY ) { lowestDeltaXY = absDeltaXY; }
+
+ // Get a whole value for the deltas
+ fn = delta > 0 ? 'floor' : 'ceil';
+ delta = Math[fn](delta / lowestDelta);
+ deltaX = Math[fn](deltaX / lowestDeltaXY);
+ deltaY = Math[fn](deltaY / lowestDeltaXY);
+
+ // Add event and delta to the front of the arguments
+ args.unshift(event, delta, deltaX, deltaY);
+
+ return ($.event.dispatch || $.event.handle).apply(this, args);
+}
+
+// Source: js/utils/pre-code.js
+function preCode(selector) {
+ var els = Array.prototype.slice.call(document.querySelectorAll(selector), 0);
+
+ els.forEach(function(el, idx, arr){
+ var txt = el.textContent
+ .replace(/^[\r\n]+/, "") // strip leading newline
+ .replace(/\s+$/g, "");
+
+ if (/^\S/gm.test(txt)) {
+ el.textContent = txt;
+ return;
+ }
+
+ var mat, str, re = /^[\t ]+/gm, len, min = 1e3;
+
+ while (mat = re.exec(txt)) {
+ len = mat[0].length;
+
+ if (len < min) {
+ min = len;
+ str = mat[0];
+ }
+ }
+
+ if (min == 1e3)
+ return;
+
+ el.textContent = txt.replace(new RegExp("^" + str, 'gm'), "");
+ });
+}
+
+document.addEventListener("DOMContentLoaded", function() {
+ preCode("pre code, textarea");
+}, false);
+// Source: js/utils/touch-handler.js
+var hasTouch = 'ontouchend' in window, eventTimer;
+var moveDirection = 'undefined', startX, startY, deltaX, deltaY, mouseDown = false;
+
+var addTouchEvents = function(element) {
+ if (hasTouch) {
+ element.addEventListener("touchstart", touch2Mouse, true);
+ element.addEventListener("touchmove", touch2Mouse, true);
+ element.addEventListener("touchend", touch2Mouse, true);
+ }
+};
+
+function touch2Mouse(e) {
+ var theTouch = e.changedTouches[0];
+ var mouseEv;
+
+ switch (e.type) {
+ case "touchstart":
+ mouseEv = "mousedown";
+ break;
+ case "touchend":
+ mouseEv = "mouseup";
+ break;
+ case "touchmove":
+ mouseEv = "mousemove";
+ break;
+ default:
+ return;
+ }
+
+
+ if (mouseEv == "mousedown") {
+ eventTimer = (new Date()).getTime();
+ startX = theTouch.clientX;
+ startY = theTouch.clientY;
+ mouseDown = true;
+ }
+
+ if (mouseEv == "mouseup") {
+ if ((new Date()).getTime() - eventTimer <= 500) {
+ mouseEv = "click";
+ } else if ((new Date()).getTime() - eventTimer > 1000) {
+ mouseEv = "longclick";
+ }
+ eventTimer = 0;
+ mouseDown = false;
+ }
+
+ if (mouseEv == "mousemove") {
+ if (mouseDown) {
+ deltaX = theTouch.clientX - startX;
+ deltaY = theTouch.clientY - startY;
+ moveDirection = deltaX > deltaY ? 'horizontal' : 'vertical';
+ }
+ }
+
+ var mouseEvent = document.createEvent("MouseEvent");
+ mouseEvent.initMouseEvent(mouseEv, true, true, window, 1, theTouch.screenX, theTouch.screenY, theTouch.clientX, theTouch.clientY, false, false, false, false, 0, null);
+ theTouch.target.dispatchEvent(mouseEvent);
+
+ e.preventDefault();
+}
+
+// Source: js/widgets/accordion.js
+$.widget("metro.accordion", {
+
+ version: "3.0.0",
+
+ options: {
+ closeAny: false,
+ speed: 'fast',
+ onFrameOpen: function(frame){return true;},
+ onFrameOpened: function(frame){},
+ onFrameClose: function(frame){return true;},
+ onFrameClosed: function(frame){}
+ },
+
+ init: function(){
+ var that = this, element = this.element;
+
+ element.on('click', '.heading', function(e){
+ var frame = $(this).parent();
+
+ if (frame.hasClass('disabled')) {return false;}
+
+ if (!frame.hasClass('active')) {
+ that._openFrame(frame);
+ } else {
+ that._closeFrame(frame);
+ }
+
+ e.preventDefault();
+ e.stopPropagation();
+ });
+ },
+
+ _closeAllFrames: function(){
+ var that = this;
+ var frames = this.element.children('.frame.active');
+ $.each(frames, function(){
+ that._closeFrame($(this));
+ });
+ },
+
+ _openFrame: function(frame){
+ var o = this.options;
+ var content = frame.children('.content');
+ var result;
+
+ if (typeof o.onFrameOpen === 'function') {
+ if (!o.onFrameOpen(frame)) {return false;}
+ } else {
+ if (typeof window[o.onFrameOpen] === 'function') {
+ if (!window[o.onFrameOpen](frame)) {return false;}
+ } else {
+ result = eval("(function(){"+o.onFrameOpen+"})");
+ if (!result.call(frame)) {return false;}
+ }
+ }
+
+ if (o.closeAny) {this._closeAllFrames();}
+
+ content.slideDown(o.speed);
+ frame.addClass('active');
+
+ if (typeof o.onFrameOpened === 'function') {
+ o.onFrameOpened(frame);
+ } else {
+ if (typeof window[o.onFrameOpened] === 'function') {
+ window[o.onFrameOpened](frame);
+ } else {
+ result = eval("(function(){"+o.onFrameOpened+"})");
+ result.call(frame);
+ }
+ }
+ },
+
+ _closeFrame: function(frame){
+ var o = this.options;
+ var content = frame.children('.content');
+ var result;
+
+ if (typeof o.onFrameClose === 'function') {
+ if (!o.onFrameClose(frame)) {return false;}
+ } else {
+ if (typeof window[o.onFrameClose] === 'function') {
+ if (!window[o.onFrameClose](frame)) {return false;}
+ } else {
+ result = eval("(function(){"+o.onFrameClose+"})");
+ if (!result.call(frame)) {return false;}
+ }
+ }
+
+ content.slideUp(o.speed,function(){
+ frame.removeClass("active");
+ });
+
+ if (typeof o.onFrameClosed === 'function') {
+ o.onFrameClosed(frame);
+ } else {
+ if (typeof window[o.onFrameClosed] === 'function') {
+ window[o.onFrameClosed](frame);
+ } else {
+ result = eval("(function(){"+o.onFrameClosed+"})");
+ result.call(frame);
+ }
+ }
+ },
+
+ _create: function(){
+ var that = this, o = this.options, element = this.element;
+
+ $.each(this.element.data(), function(key, value){
+ if (key in o) {
+ try {
+ o[key] = $.parseJSON(value);
+ } catch (e) {
+ o[key] = value;
+ }
+ }
+ });
+
+ that.init();
+ element.data('accordion', this);
+
+ },
+
+ _destroy: function(){
+ },
+
+ _setOption: function(key, value){
+ this._super('_setOption', key, value);
+ }
+});
+
+// Source: js/widgets/appbar.js
+ $.widget("metro.appbar", {
+ version: "3.0.0",
+ options: {
+ flexstyle: "app-bar-menu", //app-bar-menu | YOUR_OWN class for the pull flexmenu, basic support for "sidebar2" are integrated in the appbar.less file
+ flexclean: false, //true | false. if set all entries except the no-flexible ones will removed
+ flextolerance: 3 //in px. if set the freespace is runnig out a little bit earlier, so floats
+ //and not no-wrap elements have no chance to wrap. help for rounding errors also
+ },
+ _create: function () {
+ var that = this, element = this.element, o = this.options;
+
+ $.each(element.data(), function (key, value) {
+ if (key in o) {
+ try {
+ o[key] = $.parseJSON(value);
+ } catch (e) {
+ o[key] = value;
+ }
+ }
+ });
+
+ this._initBar();
+
+ element.data('appbar', this);
+
+ },
+ _calculateFreeSpace: function () {
+ var that = this, element = this.element, o = this.options;
+ var menusParentWidth = 0, childrenWidth = 0, children;
+ var freeSpace;
+
+ //get the overall free space from the wrapping parent of the menus
+ menusParentWidth = $(that.menusParent).width();
+
+ //get the width of all visible children
+ children = $(that.menusParent).children(":visible").not(".app-bar-pullmenu");
+
+
+ //margin support: because there could be margins between elements, we do not summarize the width up with a one liner
+ //but calculate width of all children in an intelligent way, we takte the left offsett of the first element and right offset of the right element
+ //for that we have to support float left and right too:
+ //float left and right support: we can not be sure that the first element in dom is on the left and the last is on the right
+ //right floated
+ // - sort the children as the user see them
+
+ //sort the children as the user see them according to the css float
+ var childrenLeftFloated = [];
+ var childrenRightFloated = [];
+ var childrenAsUsual = [];
+ var floatState;
+
+ for (var i = 0, len = children.length; i < len; i++) {
+ floatState = $(children[i]).css("float");
+ switch (floatState) {
+ case "left":
+ childrenLeftFloated.push(children[i]);
+ break;
+ case "right":
+ childrenRightFloated.push(children[i]);
+ break;
+ default:
+ childrenAsUsual.push(children[i]);
+ }
+ }
+ //right floats are from right to left
+ childrenRightFloated.reverse();
+
+ //=== build up the new children jquery object ===
+ //join the left, right and normal children
+ children = new Array();
+ children = childrenLeftFloated.concat(childrenAsUsual, childrenRightFloated);
+
+ //convert the array to jquery object again
+ children = $(children);
+
+ //=== calculate the width of the elements with margin support ===
+
+ //adds the left margin dedicated to the first child
+ childrenWidth += parseInt($(children).first().css("margin-left"));
+
+ //walk trough the children and add the size,
+ for (var i = 0, len = children.length - 1; i <= len; i++) {
+ childrenWidth += $(children[i]).outerWidth();
+ if (i !== len) {
+ //the highest margin between two elements counts
+ childrenWidth += Math.max(
+ parseInt($(children[i]).css("margin-right")),
+ parseInt($(children[i + 1]).css("margin-left"))
+
+ );
+ }
+ }
+ //the right margin for the right child
+ childrenWidth += parseInt($(children[len]).css("margin-right"));
+
+ //now we have all data for calculation. Yippie-Ya-Yeah, Schweinebacke!! (much cooler German translation of B. W. Yippie-Ya-Yeah, Motherf***er)
+ freeSpace = menusParentWidth - childrenWidth;
+
+ //writing the data we found out to the element's data
+ that.freeSpace = freeSpace; //not used space within the parent(mostly the appbar itself)
+ that.childrenWidth = childrenWidth; //the total width of the children
+ that.menusParentWidth = menusParentWidth; //the width without padding or something
+
+ return freeSpace;
+ },
+ _originIndexMove: function(menu, child) {
+ //find all children which are lower than we
+ var flexChildren = $(menu).children().filter(function () {
+ return parseInt($(this).attr("data-flexorderorigin")) < parseInt($(child).attr("data-flexorderorigin"));
+ });
+
+ if (flexChildren.length > 0) {
+ //because we are greater, we set it after the childern which are lower
+ $(flexChildren).last().after(child);
+ } else {
+ //find all children which are greater than we are
+ flexChildren = $(menu).children().filter(function () {
+ return parseInt($(this).attr("data-flexorderorigin")) > parseInt($(child).attr("data-flexorderorigin"));
+ });
+ if (flexChildren.length > 0) {
+ //because we are lower, we set us before the childern which are greater
+ $(flexChildren).first().before(child);
+ } else {
+ //we have no children, just append it
+ $(menu).append(child);
+ }
+ }
+ },
+ _moveMenuEntry: function (direction) {
+ var that = this, element = this.element, o = this.options;
+
+ direction = direction || "toPullMenu"; // "fromPullMenu" is also an option
+
+ if (direction === "toPullMenu") {
+ //get next candidate which could be moved to the pullmenu, in fact the last which not have a mark as pullmenu-entry
+
+ var nextToHide = $(that.allMenuEntries).not(".app-bar-pullmenu-entry").last();
+
+ if (nextToHide.length === 0) {
+ //nothing left, we have nothing to do
+ return false;
+ }
+
+
+ //find out in which menubar we are located in
+ var topMenu = $(nextToHide).parent(); //this is only a appbar-menu not the appbar itself
+ //find out where we have to go
+ var topMenuIndex = $(that.flexVisibles).index($(nextToHide).parent());
+ var pullMenuBar = $(that.pullMenu).find(".app-bar-pullmenubar").eq(topMenuIndex); //TODO: Make the class app-bar-menu configurable - perhaps sidebar
+
+ that._originIndexMove(pullMenuBar, nextToHide);
+ //move it to the pullmenu
+// if ($(topMenu).is("[data-flexdirection='reverse']")) {//data-flexdirection="reverse" support
+// $(nextToHide).appendTo(pullMenuBar);
+// } else { //normal way
+// $(nextToHide).prependTo(pullMenuBar);
+// }
+
+ //mark the entry as a entry of the pullmenu
+ $(nextToHide).addClass("app-bar-pullmenu-entry");
+
+ //the menubar is initiated with the hidden class, so we do not see empty pullmenubars, we must unhide them
+ //it does not matter, if we see it already, we do it always:
+ $(pullMenuBar).removeClass("hidden")
+ .show();
+
+ //in case there are no more entries in the top menu bar we can hide it
+ if ($(topMenu).children().length === 0) {
+ $(topMenu).addClass("hidden");
+ }
+
+ //we show the pullbutton now
+ $(that.pullButton).show();
+
+ return nextToHide;
+
+ } else if (direction === "fromPullMenu") {
+ //get next candidate which could be moved to the topbar menu, in fact the first which is still marked as pullmenu-entry
+ var nextToShow = $(that.allMenuEntries).filter(".app-bar-pullmenu-entry").first();
+
+
+ //find out in which pullmenu we are located in
+ var pullMenuBar = $(nextToShow).parent(); //only one single menu, not the whole thing
+
+ //find out where we have to go
+ var topMenuIndex = $(pullMenuBar).index(); //it is the same structur as that.flexVisibles, so we can use the simple index
+ var topMenu = $(that.flexVisibles).eq(topMenuIndex);
+
+ $(topMenu).removeClass("hidden");
+ //remove the mark as a entry of the pullmenu and move it to the normal top menu
+ $(nextToShow).removeClass("app-bar-pullmenu-entry");
+
+ //cosider the flexorder
+
+ //walk trough the children in topMenu and find out what we must do
+
+ //find all children which are lower than we
+ that._originIndexMove(topMenu, nextToShow);
+
+ //in case there are no more entries left, we can hide the pullbar menu from this entry
+ if ($(pullMenuBar).children().length === 0) {
+ $(pullMenuBar).addClass("hidden")
+ .hide();
+ }
+
+ //in case we have no more menus in the pullbar area, we hide the pullbar thing
+ if ($(that.pullMenu).children(".app-bar-pullmenubar").not(".hidden").length === 0) {
+ $(that.pullMenu).hide().addClass("hidden");
+ $(that.pullButton).hide();
+ }
+
+ if (nextToShow.length === 0) {
+ //nothing left, we have nothing to do
+ return false;
+ }
+ return nextToShow;
+ }
+ },
+ _checkMenuEntries: function () {
+ var that = this, element = this.element, o = this.options;
+
+ var forceEndLoop = false;
+
+ for (var maxLoop = 0, maxLoopLen = that.allMenuEntries.length; maxLoop < maxLoopLen; maxLoop++) { //we do nothing with this, we could use while(true) but there is a danger of infinite loops
+
+ //calculate the empty space within the appbar we can use for hidden children
+ that._calculateFreeSpace();
+ var freeSpace = that.freeSpace;
+
+ if (freeSpace < o.flextolerance || o.flexclean) { //3px is tolerance and to be faster than the wrapping. TODO: make this configurable
+ //no space left, we hide a menu entry now
+
+ //move the menu entry to the pullbar and check if there are more menuentries left
+ if (!(that._moveMenuEntry("toPullMenu"))) {
+ //nothing left to hide
+ break;
+ } else {
+ //we moved successfully, perhaps we can hide more entries, we recheck the appbar,
+ //remember, we are in a endless loop, which checks this for us
+
+ if (!forceEndLoop) {
+ continue;
+ }
+ }
+
+ } else {
+ //we have space here, we try to get more entries there
+
+ //check if there is something to do
+ if (!(that._moveMenuEntry("fromPullMenu"))) {
+ //nothing left to show
+ break;
+ } else {
+ forceEndLoop = true;
+ continue;
+ }
+
+ }
+
+ //we continue manually. if we reach the end of the loop we end this better so we do not produce infinite loop accidentally
+ break;
+ }
+ },
+ resize: function () {
+ var that = this, element = this.element, o = this.options;
+
+ if (that.initiatedAsFlex) {
+ this._checkMenuEntries();
+ }
+ },
+ _initBar: function () {
+ var that = this, element = this.element, o = this.options;
+
+ that.lastFlexAction = undefined;
+
+ that.pullButton = $(element).find('.app-bar-pullbutton');
+ var menus = $(element).find('.app-bar-menu');
+
+ that.initiatedAsFlex = false; //we change it later in the code - conditionally
+ o.flexclean = $(element).is("[data-flexclean='true']") || o.flexclean;
+ o.flexstyle = $(element).attr("data-flexstyle") || o.flexstyle;
+
+ var flexVisible, menuEntries; //temporarly used vars
+
+ that.flexVisibles = $(); //the menus which are directly in the appbar
+ that.allMenuEntries = $(); //all menu entries in a sorted order
+ that.menusParent = $(); //common parent from the menus, which can but do not need to be this.element. We get the max width from it
+ that.pullMenu = $();
+
+ if (menus.length > 0 && $(element).is(":not('.no-flexible')")) {
+ //strip off all .no-flexible menus
+ that.flexVisibles = $(menus).not(".no-flexible");
+
+ if (that.flexVisibles.length > 0) {
+
+ that.initiatedAsFlex = true;
+
+ //sort the menus according to the data-flexorder attribute
+ that.flexVisibles.sort(function (a, b) {
+ var aValue = (parseInt($(a).data("flexorder")) || $(a).index() + 1);
+ var bValue = (parseInt($(b).data("flexorder")) || $(b).index() + 1);
+ return aValue - bValue;
+ });
+
+ //get all children in a sorted order according to the data-flexorder attribute
+ $(that.flexVisibles).each(function () {
+ flexVisible = this;
+
+ menuEntries = $(flexVisible).children();
+
+ //give all menuEntries a flexorder which have not one and save the original order
+ $(menuEntries).each(function () {
+ $(this).attr("data-flexorderorigin", $(this).index());
+
+ if(!($(this).is("[data-flexorder]"))) {
+ $(this).attr("data-flexorder", $(this).index() + 1);
+ }
+ });
+
+ menuEntries.sort(function (a, b) {
+ var aValue = parseInt($(a).data("flexorder"));
+ var bValue = parseInt($(b).data("flexorder"));
+ return aValue - bValue;
+ });
+
+ //data-flexdirection="reverse" support
+ if ($(flexVisible).is("[data-flexdirection='reverse']")) {
+ menuEntries.reverse();
+ }
+
+ $.merge(that.allMenuEntries, $(menuEntries).not(".no-flexible")); //strip off all .no-flexible elements
+ });
+
+ //find the parent, which contains all menus
+ that.menusParent = $(element).find(".app-bar-menu").first().parent();
+
+ // === create a pull down button + pull menu ===
+ //check if a pulldown button already exists, if not we create one
+ if (!(that.pullButton.length > 0)) {
+ //DOC: We can create a display:none button, if we want to force to not show a pull button
+ that.pullButton = $('');
+ $(that.menusParent).append(that.pullButton);
+ }
+
+ //create a pullmenu
+ that.pullMenu = $('');
+
+ //create menubars within the pullmenu
+ that.flexVisibles.each(function () {
+ $(that.pullMenu).append($('
'));
+ });
+
+
+
+ // WORKAROUND: this is because a :after:before clearfix for the pullmenu do not work for some reason
+ //position: absolute does not work if we do not break the float. another pure css solution should be written in the appbar.less
+ //after that remove this line
+ $(that.menusParent).append($('
'));
+ //-----------
+
+
+ $(that.pullMenu).addClass("flexstyle-" + o.flexstyle);
+
+ $(that.menusParent).append(that.pullMenu);
+
+ //check for the first time the menu entries /hide them if needed, etc.
+ that._checkMenuEntries();
+
+
+
+ //=== EVENTS =================================================
+
+ //activate the click event for the pull button
+ $(that.pullButton).on("click", function () {
+
+ //who am i?
+ that = $(this).closest("[data-role=appbar]").data("appbar");
+
+ //we show /hide the pullmenu
+ if ($(that.pullMenu).is(":hidden")) {
+ $(that.pullMenu).show();
+ $(that.pullMenu).find(".app-bar-pullmenubar")
+ .hide().not(".hidden").slideDown("fast");
+ } else {
+ $(that.pullMenu).find(".app-bar-pullmenubar")
+ .not(".hidden").show().slideUp("fast", function () {
+ $(that.pullMenu).hide();
+ });
+ }
+
+ });
+
+
+ //we have to calculate everything new, if the user resizes or zooms the window
+ $(window).resize(function () {
+ $("[data-role=appbar]:not(.no-flexible)").each(function () {
+ $(this).data("appbar").resize();
+ });
+ });
+
+
+ //because fonts(also icon-fonts) are often loaded async after the page has loaded and this script walked through already,
+ //we have to check again after these elements loaded. Because there is no way to observe only specific elements, we do it for the window
+ $(window).load(function () {
+ $("[data-role=appbar]:not(.no-flexible)").each(function () {
+ $(this).data("appbar").resize();
+ });
+ });
+
+ //pictures (or other outside stuff was loaded - pictures are also often loaded async or have a lazy load or are injected after a while.
+ //a picture can change a size of the element from the appbar, so we must recheck it again.
+ $("[data-role=appbar]:not(.no-flexible) [src]").on("load", function () {
+ //who am i?
+ var appbar = $(this).closest("[data-role=appbar]").data("appbar");
+ appbar.resize();
+ });
+ }
+ }
+
+ },
+ _destroy: function () {
+ },
+ _setOption: function (key, value) {
+ this._super('_setOption', key, value);
+ }
+ });
+
+// Source: js/widgets/audio-player.js
+$.widget( "metro.audio" , {
+
+ version: "3.0.14",
+
+ options: {
+ src: false,
+ volume: .5,
+ muted: false,
+ loop: false,
+ preload: false,
+ autoplay: false,
+ playList: false,
+ mode: "full",
+
+ loopButton: "",
+ stopButton: "",
+ playButton: "",
+ pauseButton: "",
+ muteButton: "",
+ shuffleButton: "",
+ nextButton: "",
+ prevButton: "",
+ randomButton: "",
+ playListButton: "",
+
+ volumeLowButton: "",
+ volumeMediumButton: "",
+ volumeHighButton: ""
+
+ },
+
+ _create: function () {
+ var that = this, element = this.element, o = this.options;
+
+ this._setOptionsFromDOM();
+
+ this._createPlayer();
+ this._addControls();
+ this._addEvents();
+ this._addPlayList();
+ this._setControlsVisibility();
+
+ element.data('audio', this);
+ },
+
+ _setControlsVisibility: function(){
+ var that = this, element = this.element, o = this.options;
+ if (element.find(".play-list").length == 0) {
+ element.find(".controls .plist").hide();
+ element.find(".controls .next").hide();
+ element.find(".controls .prev").hide();
+ element.find(".controls .random").hide();
+ }
+ },
+
+ _addPlayList: function(){
+ var that = this, element = this.element, o = this.options;
+ var audio = element.find("audio");
+ var pl, pli, plw, poster, title;
+ var play_list;
+
+ if (o.playList) {
+ if (window[o.playList] != undefined && typeof window[o.playList] == 'function') {
+
+ pl = window[o.playList]();
+ pli = pl.items;
+ plw = $("
").addClass("play-list-wrapper").insertBefore(element.find("audio"));
+
+ if (pl.title != undefined) {
+ title = $("