/*! * Metro UI CSS v3.0.10 (http://metroui.org.ua) * Copyright 2012-2015 Sergey Pimenov * Licensed under MIT (http://metroui.org.ua/license.html) */ (function( factory ) { if ( typeof define === 'function' && define.amd ) { define([ 'jquery' ], factory ); } else { factory( jQuery ); } }(function( jQuery ) { 'use strict'; var $ = jQuery; // Source: js/requirements.js if (typeof jQuery === 'undefined') { throw new Error('Metro\'s JavaScript requires jQuery'); } // Source: js/global.js window.METRO_VERSION = '3.0.10'; if (window.METRO_AUTO_REINIT === undefined) window.METRO_AUTO_REINIT = true; if (window.METRO_LANGUAGE === undefined) window.METRO_LANGUAGE = 'en'; if (window.METRO_LOCALE === undefined) window.METRO_LOCALE = 'EN_en'; if (window.METRO_CURRENT_LOCALE === undefined) window.METRO_CURRENT_LOCALE = 'en'; if (window.METRO_SHOW_TYPE === undefined) window.METRO_SHOW_TYPE = 'slide'; if (window.METRO_DEBUG === undefined) window.METRO_DEBUG = true; if (window.METRO_CALENDAR_WEEK_START === undefined) window.METRO_CALENDAR_WEEK_START = 0; window.canObserveMutation = 'MutationObserver' in window; String.prototype.isUrl = function () { var regexp = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/; return regexp.test(this); }; String.prototype.isColor = function () { return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(this); }; Array.prototype.shuffle = function () { var currentIndex = this.length, temporaryValue, randomIndex; while (0 !== currentIndex) { randomIndex = Math.floor(Math.random() * currentIndex); currentIndex -= 1; temporaryValue = this[currentIndex]; this[currentIndex] = this[randomIndex]; this[randomIndex] = temporaryValue; } return this; }; Array.prototype.clone = function () { return this.slice(0); }; Array.prototype.unique = function () { var a = this.concat(); for (var i = 0; i < a.length; ++i) { for (var j = i + 1; j < a.length; ++j) { if (a[i] === a[j]) a.splice(j--, 1); } } return a; }; window.uniqueId = function (prefix) { var d = new Date().getTime(); var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = (d + Math.random() * 16) % 16 | 0; d = Math.floor(d / 16); return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16); }); return uuid; }; window.isTouchDevice = function() { return (('ontouchstart' in window) || (navigator.MaxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0)); }; window.METRO_LOCALES = { 'en': { months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ], buttons: [ "Today", "Clear", "Cancel", "Help", "Prior", "Next", "Finish" ] }, 'fr': { months: [ "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre", "Jan", "Fév", "Mars", "Avr", "Mai", "Juin", "Juil", "Août", "Sept", "Oct", "Nov", "Déc" ], days: [ "Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Di", "Lu", "Ma", "Me", "Je", "Ve", "Sa" ], buttons: [ "Aujourd'hui", "Effacer", "Annuler", "Aide", "Précedent", "Suivant", "Fin" ] }, 'nl': { months: [ "Januari", "Februari", "Maart", "April", "Mei", "Juni", "Juli", "Augustus", "September", "Oktober", "November", "December", "Jan", "Feb", "Mrt", "Apr", "Mei", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" ], days: [ "Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag", "Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za" ], buttons: [ "Vandaag", "Verwijderen", "Annuleren", "Hulp", "Vorige", "Volgende", "Einde" ] }, 'ua': { months: [ "Січень", "Лютий", "Березень", "Квітень", "Травень", "Червень", "Липень", "Серпень", "Вересень", "Жовтень", "Листопад", "Грудень", "Січ", "Лют", "Бер", "Кві", "Тра", "Чер", "Лип", "Сер", "Вер", "Жов", "Лис", "Гру" ], days: [ "Неділя", "Понеділок", "Вівторок", "Середа", "Четвер", "П’ятниця", "Субота", "Нд", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб" ], buttons: [ "Сьогодні", "Очистити", "Скасувати", "Допомога", "Назад", "Вперед", "Готово" ] }, 'ru': { months: [ "Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь", "Янв", "Фев", "Мар", "Апр", "Май", "Июн", "Июл", "Авг", "Сен", "Окт", "Ноя", "Дек" ], days: [ "Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Вс", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб" ], buttons: [ "Сегодня", "Очистить", "Отменить", "Помощь", "Назад", "Вперед", "Готово" ] }, /** By NoGrief (nogrief@gmail.com) */ 'zhCN': { months: [ "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月", "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月" ], days: [ "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "日", "一", "二", "三", "四", "五", "六" ], buttons: [ "今日", "清除", "Cancel", "Help", "Prior", "Next", "Finish" ] }, 'it': { months: [ 'Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre', 'Gen', ' Feb', 'Mar', 'Apr', 'Mag', 'Giu', 'Lug', 'Ago', 'Set', 'Ott', 'Nov', 'Dic' ], days: [ 'Lunedì', 'Martedì', 'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato', 'Domenica', 'Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab', 'Dom' ], buttons: [ "Oggi", "Cancella", "Cancel", "Help", "Prior", "Next", "Finish" ] }, 'de': { months: [ "Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember", "Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez" ], days: [ "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa" ], buttons: [ "Heute", "Zurücksetzen", "Abbrechen", "Hilfe", "Früher", "Später", "Fertig" ] }, /** By Javier Rodríguez (javier.rodriguez at fjrodriguez.com) */ 'es': { months: [ "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre", "Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sept", "Oct", "Nov", "Dic" ], days: [ "Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Do", "Lu", "Mar", "Mié", "Jue", "Vi", "Sáb" ], buttons: [ "Hoy", "Limpiar", "Cancel", "Help", "Prior", "Next", "Finish" ] }, 'pt': { months: [ 'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro', 'Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez' ], days: [ 'Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sabado', 'Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sab' ], buttons: [ "Hoje", "Limpar", "Cancelar", "Ajuda", "Anterior", "Seguinte", "Terminar" ] }, 'pl': { months: [ "Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień", "Sty", "Lut", "Mar", "Kwi", "Maj", "Cze", "Lip", "Sie", "Wrz", "Paź", "Lis", "Gru" ], days: [ "Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota", "Nd", "Pon", "Wt", "Śr", "Czw", "Pt", "Sob" ], buttons: [ "Dzisiaj", "Wyczyść", "Anuluj", "Pomoc", "Poprzedni", "Następny", "Koniec" ] }, 'cs': { months: [ "Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad", "Prosinec", "Led", "Ún", "Bř", "Dub", "Kvě", "Če", "Čer", "Srp", "Zá", "Ří", "Li", "Pro" ], days: [ "Neděle", "Pondělí", "Úterý", "Středa", "Čtvrtek", "Pátek", "Sobota", "Ne", "Po", "Út", "St", "Čt", "Pá", "So" ], buttons: [ "Dnes", "Vyčistit", "Zrušit", "Pomoc", "Předešlý", "Další", "Dokončit" ] }, /* By Satit Rianpit */ 'th': { months: [ "มกราคม", "กุมภาพันธ์", "มีนาคม", "เมษายน", "พฤษภาคม", "มิถุนายน", "กรกฎาคม", "สิงหาคม", "กันยายน", "ตุลาคม", "พฤศจิกายน", "ธันวาคม", "ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค.", "พ.ย.", "ธ.ค." ], days: [ "อาทิตย์", "จันทร์", "อังคาร", "พุธ", "พฤหัสบดี", "ศุกร์", "เสาร์", "อา.", "จ.", "อ.", "พ.", "พฤ.", "ศ.", "ส." ], buttons: [ "วันนี้", "ล้าง", "ยกเลิก", "ช่วยเหลือ", "กลับ", "ต่อไป", "เสร็จ" ] } }; /* * Date Format 1.2.3 * (c) 2007-2009 Steven Levithan * MIT license * * Includes enhancements by Scott Trenda * and Kris Kowal * * Accepts a date, a mask, or a date and a mask. * Returns a formatted version of the given date. * The date defaults to the current date/time. * The mask defaults to dateFormat.masks.default. */ // this is a temporary solution var dateFormat = function () { var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, timezoneClip = /[^-+\dA-Z]/g, pad = function (val, len) { val = String(val); len = len || 2; while (val.length < len) { val = "0" + val; } return val; }; // Regexes and supporting functions are cached through closure return function (date, mask, utc) { var dF = dateFormat; // You can't provide utc if you skip other args (use the "UTC:" mask prefix) if (arguments.length === 1 && Object.prototype.toString.call(date) === "[object String]" && !/\d/.test(date)) { mask = date; date = undefined; } //console.log(arguments); // Passing date through Date applies Date.parse, if necessary date = date ? new Date(date) : new Date(); //if (isNaN(date)) throw SyntaxError("invalid date"); mask = String(dF.masks[mask] || mask || dF.masks["default"]); // Allow setting the utc argument via the mask if (mask.slice(0, 4) === "UTC:") { mask = mask.slice(4); utc = true; } //console.log(locale); var locale = window.METRO_CURRENT_LOCALE || 'en'; var _ = utc ? "getUTC" : "get", d = date[_ + "Date"](), D = date[_ + "Day"](), m = date[_ + "Month"](), y = date[_ + "FullYear"](), H = date[_ + "Hours"](), M = date[_ + "Minutes"](), s = date[_ + "Seconds"](), L = date[_ + "Milliseconds"](), o = utc ? 0 : date.getTimezoneOffset(), flags = { d: d, dd: pad(d), ddd: window.METRO_LOCALES[locale].days[D], dddd: window.METRO_LOCALES[locale].days[D + 7], m: m + 1, mm: pad(m + 1), mmm: window.METRO_LOCALES[locale].months[m], mmmm: window.METRO_LOCALES[locale].months[m + 12], yy: String(y).slice(2), yyyy: y, h: H % 12 || 12, hh: pad(H % 12 || 12), H: H, HH: pad(H), M: M, MM: pad(M), s: s, ss: pad(s), l: pad(L, 3), L: pad(L > 99 ? Math.round(L / 10) : L), t: H < 12 ? "a" : "p", tt: H < 12 ? "am" : "pm", T: H < 12 ? "A" : "P", TT: H < 12 ? "AM" : "PM", Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""), o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 !== 10) * d % 10] }; return mask.replace(token, function ($0) { return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1); }); }; }(); // Some common format strings dateFormat.masks = { "default": "ddd mmm dd yyyy HH:MM:ss", shortDate: "m/d/yy", mediumDate: "mmm d, yyyy", longDate: "mmmm d, yyyy", fullDate: "dddd, mmmm d, yyyy", shortTime: "h:MM TT", mediumTime: "h:MM:ss TT", longTime: "h:MM:ss TT Z", isoDate: "yyyy-mm-dd", isoTime: "HH:MM:ss", isoDateTime: "yyyy-mm-dd'T'HH:MM:ss", isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'" }; // For convenience... Date.prototype.format = function (mask, utc) { return dateFormat(this, mask, utc); }; // Source: js/widget.js var widget_uuid = 0, widget_slice = Array.prototype.slice; $.cleanData = (function (orig) { return function (elems) { var events, elem, i; for (i = 0; (elem = elems[i]) != null; i++) { try { // Only trigger remove when necessary to save time events = $._data(elem, "events"); if (events && events.remove) { $(elem).triggerHandler("remove"); } // http://bugs.$.com/ticket/8235 } catch (e) { } } orig(elems); }; })($.cleanData); $.widget = function (name, base, prototype) { var fullName, existingConstructor, constructor, basePrototype, // proxiedPrototype allows the provided prototype to remain unmodified // so that it can be used as a mixin for multiple widgets (#8876) proxiedPrototype = {}, namespace = name.split(".")[0]; name = name.split(".")[1]; fullName = namespace + "-" + name; if (!prototype) { prototype = base; base = $.Widget; } // create selector for plugin $.expr[":"][fullName.toLowerCase()] = function (elem) { return !!$.data(elem, fullName); }; $[namespace] = $[namespace] || {}; existingConstructor = $[namespace][name]; constructor = $[namespace][name] = function (options, element) { // allow instantiation without "new" keyword if (!this._createWidget) { return new constructor(options, element); } // allow instantiation without initializing for simple inheritance // must use "new" keyword (the code above always passes args) if (arguments.length) { this._createWidget(options, element); } }; // extend with the existing constructor to carry over any static properties $.extend(constructor, existingConstructor, { version: prototype.version, // copy the object used to create the prototype in case we need to // redefine the widget later _proto: $.extend({}, prototype), // track widgets that inherit from this widget in case this widget is // redefined after a widget inherits from it _childConstructors: [] }); basePrototype = new base(); // we need to make the options hash a property directly on the new instance // otherwise we'll modify the options hash on the prototype that we're // inheriting from basePrototype.options = $.widget.extend({}, basePrototype.options); $.each(prototype, function (prop, value) { if (!$.isFunction(value)) { proxiedPrototype[prop] = value; return; } proxiedPrototype[prop] = (function () { var _super = function () { return base.prototype[prop].apply(this, arguments); }, _superApply = function (args) { return base.prototype[prop].apply(this, args); }; return function () { var __super = this._super, __superApply = this._superApply, returnValue; this._super = _super; this._superApply = _superApply; returnValue = value.apply(this, arguments); this._super = __super; this._superApply = __superApply; return returnValue; }; })(); }); constructor.prototype = $.widget.extend(basePrototype, { // TODO: remove support for widgetEventPrefix // always use the name + a colon as the prefix, e.g., draggable:start // don't prefix for widgets that aren't DOM-based widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name }, proxiedPrototype, { constructor: constructor, namespace: namespace, widgetName: name, widgetFullName: fullName }); // If this widget is being redefined then we need to find all widgets that // are inheriting from it and redefine all of them so that they inherit from // the new version of this widget. We're essentially trying to replace one // level in the prototype chain. if (existingConstructor) { $.each(existingConstructor._childConstructors, function (i, child) { var childPrototype = child.prototype; // redefine the child widget using the same prototype that was // originally used, but inherit from the new version of the base $.widget(childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto); }); // remove the list of existing child constructors from the old constructor // so the old child constructors can be garbage collected delete existingConstructor._childConstructors; } else { base._childConstructors.push(constructor); } $.widget.bridge(name, constructor); return constructor; }; $.widget.extend = function (target) { var input = widget_slice.call(arguments, 1), inputIndex = 0, inputLength = input.length, key, value; for (; inputIndex < inputLength; inputIndex++) { for (key in input[inputIndex]) { value = input[inputIndex][key]; if (input[inputIndex].hasOwnProperty(key) && value !== undefined) { // Clone objects if ($.isPlainObject(value)) { target[key] = $.isPlainObject(target[key]) ? $.widget.extend({}, target[key], value) : // Don't extend strings, arrays, etc. with objects $.widget.extend({}, value); // Copy everything else by reference } else { target[key] = value; } } } } return target; }; $.widget.bridge = function (name, object) { var fullName = object.prototype.widgetFullName || name; $.fn[name] = function (options) { var isMethodCall = typeof options === "string", args = widget_slice.call(arguments, 1), returnValue = this; if (isMethodCall) { this.each(function () { var methodValue, instance = $.data(this, fullName); if (options === "instance") { returnValue = instance; return false; } if (!instance) { return $.error("cannot call methods on " + name + " prior to initialization; " + "attempted to call method '" + options + "'"); } if (!$.isFunction(instance[options]) || options.charAt(0) === "_") { return $.error("no such method '" + options + "' for " + name + " widget instance"); } methodValue = instance[options].apply(instance, args); if (methodValue !== instance && methodValue !== undefined) { returnValue = methodValue && methodValue.jquery ? returnValue.pushStack(methodValue.get()) : methodValue; return false; } }); } else { // Allow multiple hashes to be passed on init if (args.length) { options = $.widget.extend.apply(null, [options].concat(args)); } this.each(function () { var instance = $.data(this, fullName); if (instance) { instance.option(options || {}); if (instance._init) { instance._init(); } } else { $.data(this, fullName, new object(options, this)); } }); } return returnValue; }; }; $.Widget = function (/* options, element */) { }; $.Widget._childConstructors = []; $.Widget.prototype = { widgetName: "widget", widgetEventPrefix: "", defaultElement: "
", 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) { $.fn[func].call($this); } } 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('initiated') !== true) { $.fn[func].call(_this); _this.data('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 = $('