",
- options: {
- disabled: false,
-
- // callbacks
- create: null
- },
- _createWidget: function (options, element) {
- element = $(element || this.defaultElement || this)[0];
- this.element = $(element);
- this.uuid = uuid++;
- this.eventNamespace = "." + this.widgetName + this.uuid;
- this.options = $.widget.extend({},
- this.options,
- this._getCreateOptions(),
- options);
-
- 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._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 (value === undefined) {
- return curOption[key] === undefined ? null : curOption[key];
- }
- curOption[key] = value;
- } else {
- if (value === undefined) {
- 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);
- 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 {
- // accept selectors, DOM elements
- 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);
- },
-
- _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[0].dispatchEvent(new CustomEvent(event.type, {
- bubbles: true,
- detail: {
- data: data,
- originalEvent: event
- }
- }));
-
- //this.element.trigger(event, data);
- return !($.isFunction(callback) &&
- callback.apply(this.element[0], [event].concat(data)) === false ||
- event.isDefaultPrevented());
- }
- };
-
- })(jQuery);
-
- (function ($, undefined) {
-
- $.extend($.Widget.prototype, {
- _getCreateOptions: function () {
-
- var option, value,
- elem = this.element[0],
- options = {};
-
- //
- if (!this.element.data("defaults")) {
- for (option in this.options) {
-
- value = this.element.data(option);
-
- if (value != null) {
- options[option] = value;
- }
- }
- }
-
- return options;
- }
});
+ })(jQuery, this);
+
+ (function ($, undefined) {
+
+ var uiScreenHiddenRegex = /\bui-screen-hidden\b/;
+ function noHiddenClass(elements) {
+ var index,
+ length = elements.length,
+ result = [];
+
+ for (index = 0; index < length; index++) {
+ if (!elements[index].className.match(uiScreenHiddenRegex)) {
+ result.push(elements[index]);
+ }
+ }
+
+ return $(result);
+ }
+
+ $.mobile.behaviors.addFirstLastClasses = {
+ _getVisibles: function ($els, create) {
+ var visibles;
+
+ if (create) {
+ visibles = noHiddenClass($els);
+ } else {
+ visibles = $els.filter(":visible");
+ if (visibles.length === 0) {
+ visibles = noHiddenClass($els);
+ }
+ }
+
+ return visibles;
+ },
+
+ _addFirstLastClasses: function ($els, $visibles, create) {
+ $els.removeClass("ui-first-child ui-last-child");
+ $visibles.eq(0).addClass("ui-first-child").end().last().addClass("ui-last-child");
+ if (!create) {
+ this.element.trigger("updatelayout");
+ }
+ },
+
+ _removeFirstLastClasses: function ($els) {
+ $els.removeClass("ui-first-child ui-last-child");
+ }
+ };
+
})(jQuery);
(function ($, undefined) {
+ var getAttr = $.mobile.getAttribute;
- var originalWidget = $.widget
+ $.widget("mobile.listview", $.extend({
- $.widget = (function (orig) {
- return function () {
- var constructor = orig.apply(this, arguments),
- name = constructor.prototype.widgetName;
+ options: {
+ theme: null,
+ countTheme: null, /* Deprecated in 1.4 */
+ dividerTheme: null,
+ icon: "carat-r",
+ splitIcon: "carat-r",
+ splitTheme: null,
+ corners: true,
+ shadow: true,
+ inset: false
+ },
- constructor.initSelector = ((constructor.prototype.initSelector !== undefined) ?
- constructor.prototype.initSelector : "*[data-role='" + name + "']:not([data-role='none'])");
+ _create: function () {
+ var t = this,
+ listviewClasses = "";
- $.mobile.widgets[name] = constructor;
+ listviewClasses += t.options.inset ? " ui-listview-inset" : "";
- return constructor;
- };
- })($.widget);
+ if (!!t.options.inset) {
+ listviewClasses += t.options.corners ? " ui-corner-all" : "";
+ listviewClasses += t.options.shadow ? " ui-shadow" : "";
+ }
- // Make sure $.widget still has bridge and extend methods
- $.extend($.widget, originalWidget);
+ // create listview markup
+ t.element.addClass(" ui-listview" + listviewClasses);
+
+ t.refresh(true);
+ },
+
+ // TODO: Remove in 1.5
+ _findFirstElementByTagName: function (ele, nextProp, lcName, ucName) {
+ var dict = {};
+ dict[lcName] = dict[ucName] = true;
+ while (ele) {
+ if (dict[ele.nodeName]) {
+ return ele;
+ }
+ ele = ele[nextProp];
+ }
+ return null;
+ },
+ // TODO: Remove in 1.5
+ _addThumbClasses: function (containers) {
+ var i, img, len = containers.length;
+ for (i = 0; i < len; i++) {
+ img = $(this._findFirstElementByTagName(containers[i].firstChild, "nextSibling", "img", "IMG"));
+ if (img.length) {
+ $(this._findFirstElementByTagName(img[0].parentNode, "parentNode", "li", "LI")).addClass(img.hasClass("ui-li-icon") ? "ui-li-has-icon" : "ui-li-has-thumb");
+ }
+ }
+ },
+
+ _getChildrenByTagName: function (ele, lcName, ucName) {
+ var results = [],
+ dict = {};
+ dict[lcName] = dict[ucName] = true;
+ ele = ele.firstChild;
+ while (ele) {
+ if (dict[ele.nodeName]) {
+ results.push(ele);
+ }
+ ele = ele.nextSibling;
+ }
+ return $(results);
+ },
+
+ _beforeListviewRefresh: $.noop,
+ _afterListviewRefresh: $.noop,
+
+ refresh: function (create) {
+ var buttonClass, pos, numli, item, itemClass, itemTheme, itemIcon, icon, a,
+ isDivider, startCount, newStartCount, value, last, splittheme, splitThemeClass, spliticon,
+ altButtonClass, dividerTheme, li,
+ o = this.options,
+ $list = this.element,
+ ol = !!$.nodeName($list[0], "ol"),
+ start = $list.attr("start"),
+ itemClassDict = {},
+ countBubbles = $list.find(".ui-li-count"),
+ countTheme = getAttr($list[0], "counttheme") || this.options.countTheme,
+ countThemeClass = countTheme ? "ui-body-" + countTheme : "ui-body-inherit";
+
+ if (o.theme) {
+ $list.addClass("ui-group-theme-" + o.theme);
+ }
+
+ // Check if a start attribute has been set while taking a value of 0 into account
+ if (ol && (start || start === 0)) {
+ startCount = parseInt(start, 10) - 1;
+ $list.css("counter-reset", "listnumbering " + startCount);
+ }
+
+ this._beforeListviewRefresh();
+
+ li = this._getChildrenByTagName($list[0], "li", "LI");
+
+ for (pos = 0, numli = li.length; pos < numli; pos++) {
+ item = li.eq(pos);
+ itemClass = "";
+
+ if (create || item[0].className.search(/\bui-li-static\b|\bui-li-divider\b/) < 0) {
+ a = this._getChildrenByTagName(item[0], "a", "A");
+ isDivider = (getAttr(item[0], "role") === "list-divider");
+ value = item.attr("value");
+ itemTheme = getAttr(item[0], "theme");
+
+ if (a.length && a[0].className.search(/\bui-btn\b/) < 0 && !isDivider) {
+ itemIcon = getAttr(item[0], "icon");
+ icon = (itemIcon === false) ? false : (itemIcon || o.icon);
+
+ // TODO: Remove in 1.5 together with links.js (links.js / .ui-link deprecated in 1.4)
+ a.removeClass("ui-link");
+
+ buttonClass = "ui-btn";
+
+ if (itemTheme) {
+ buttonClass += " ui-btn-" + itemTheme;
+ }
+
+ if (a.length > 1) {
+ itemClass = "ui-li-has-alt";
+
+ last = a.last();
+ splittheme = getAttr(last[0], "theme") || o.splitTheme || getAttr(item[0], "theme", true);
+ splitThemeClass = splittheme ? " ui-btn-" + splittheme : "";
+ spliticon = getAttr(last[0], "icon") || getAttr(item[0], "icon") || o.splitIcon;
+ altButtonClass = "ui-btn ui-btn-icon-notext ui-icon-" + spliticon + splitThemeClass;
+
+ last
+ .attr("title", $.trim(last.text()))
+ .addClass(altButtonClass)
+ .empty();
+
+ // Reduce to the first anchor, because only the first gets the buttonClass
+ a = a.first();
+ } else if (icon) {
+ buttonClass += " ui-btn-icon-right ui-icon-" + icon;
+ }
+
+ // Apply buttonClass to the (first) anchor
+ a.addClass(buttonClass);
+ } else if (isDivider) {
+ dividerTheme = (getAttr(item[0], "theme") || o.dividerTheme || o.theme);
+
+ itemClass = "ui-li-divider ui-bar-" + (dividerTheme ? dividerTheme : "inherit");
+
+ item.attr("role", "heading");
+ } else if (a.length <= 0) {
+ itemClass = "ui-li-static ui-body-" + (itemTheme ? itemTheme : "inherit");
+ }
+ if (ol && value) {
+ newStartCount = parseInt(value, 10) - 1;
+
+ item.css("counter-reset", "listnumbering " + newStartCount);
+ }
+ }
+
+ // Instead of setting item class directly on the list item
+ // at this point in time, push the item into a dictionary
+ // that tells us what class to set on it so we can do this after this
+ // processing loop is finished.
+
+ if (!itemClassDict[itemClass]) {
+ itemClassDict[itemClass] = [];
+ }
+
+ itemClassDict[itemClass].push(item[0]);
+ }
+
+ // Set the appropriate listview item classes on each list item.
+ // The main reason we didn't do this
+ // in the for-loop above is because we can eliminate per-item function overhead
+ // by calling addClass() and children() once or twice afterwards. This
+ // can give us a significant boost on platforms like WP7.5.
+
+ for (itemClass in itemClassDict) {
+ $(itemClassDict[itemClass]).addClass(itemClass);
+ }
+
+ countBubbles.each(function () {
+ $(this).closest("li").addClass("ui-li-has-count");
+ });
+ if (countThemeClass) {
+ countBubbles.not("[class*='ui-body-']").addClass(countThemeClass);
+ }
+
+ // Deprecated in 1.4. From 1.5 you have to add class ui-li-has-thumb or ui-li-has-icon to the LI.
+ this._addThumbClasses(li);
+ this._addThumbClasses(li.find(".ui-btn"));
+
+ this._afterListviewRefresh();
+
+ this._addFirstLastClasses(li, this._getVisibles(li, create), create);
+ }
+ }, $.mobile.behaviors.addFirstLastClasses));
})(jQuery);
-
-})();
-
-(function ($, window, undefined) {
- var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/;
-
- $.extend($.mobile, {
-
- // Namespace used framework-wide for data-attrs. Default is no namespace
-
- // Retrieve an attribute from an element and perform some massaging of the value
-
- getAttribute: function (element, key) {
- var data;
-
- element = element.jquery ? element[0] : element;
-
- if (element && element.getAttribute) {
- data = element.getAttribute("data-" + key);
- }
-
- // Copied from core's src/data.js:dataAttr()
- // Convert from a string to a proper data type
- try {
- data = data === "true" ? true :
- data === "false" ? false :
- data === "null" ? null :
- // Only convert to a number if it doesn't change the string
- +data + "" === data ? +data :
- rbrace.test(data) ? JSON.parse(data) :
- data;
- } catch (err) { }
-
- return data;
- }
-
- });
-
-})(jQuery, this);
-
-(function ($, undefined) {
-
- var uiScreenHiddenRegex = /\bui-screen-hidden\b/;
- function noHiddenClass(elements) {
- var index,
- length = elements.length,
- result = [];
-
- for (index = 0; index < length; index++) {
- if (!elements[index].className.match(uiScreenHiddenRegex)) {
- result.push(elements[index]);
- }
- }
-
- return $(result);
- }
-
- $.mobile.behaviors.addFirstLastClasses = {
- _getVisibles: function ($els, create) {
- var visibles;
-
- if (create) {
- visibles = noHiddenClass($els);
- } else {
- visibles = $els.filter(":visible");
- if (visibles.length === 0) {
- visibles = noHiddenClass($els);
- }
- }
-
- return visibles;
- },
-
- _addFirstLastClasses: function ($els, $visibles, create) {
- $els.removeClass("ui-first-child ui-last-child");
- $visibles.eq(0).addClass("ui-first-child").end().last().addClass("ui-last-child");
- if (!create) {
- this.element.trigger("updatelayout");
- }
- },
-
- _removeFirstLastClasses: function ($els) {
- $els.removeClass("ui-first-child ui-last-child");
- }
- };
-
-})(jQuery);
-
-(function ($, undefined) {
-
- var getAttr = $.mobile.getAttribute;
-
- $.widget("mobile.listview", $.extend({
-
- options: {
- theme: null,
- countTheme: null, /* Deprecated in 1.4 */
- dividerTheme: null,
- icon: "carat-r",
- splitIcon: "carat-r",
- splitTheme: null,
- corners: true,
- shadow: true,
- inset: false
- },
-
- _create: function () {
- var t = this,
- listviewClasses = "";
-
- listviewClasses += t.options.inset ? " ui-listview-inset" : "";
-
- if (!!t.options.inset) {
- listviewClasses += t.options.corners ? " ui-corner-all" : "";
- listviewClasses += t.options.shadow ? " ui-shadow" : "";
- }
-
- // create listview markup
- t.element.addClass(" ui-listview" + listviewClasses);
-
- t.refresh(true);
- },
-
- // TODO: Remove in 1.5
- _findFirstElementByTagName: function (ele, nextProp, lcName, ucName) {
- var dict = {};
- dict[lcName] = dict[ucName] = true;
- while (ele) {
- if (dict[ele.nodeName]) {
- return ele;
- }
- ele = ele[nextProp];
- }
- return null;
- },
- // TODO: Remove in 1.5
- _addThumbClasses: function (containers) {
- var i, img, len = containers.length;
- for (i = 0; i < len; i++) {
- img = $(this._findFirstElementByTagName(containers[i].firstChild, "nextSibling", "img", "IMG"));
- if (img.length) {
- $(this._findFirstElementByTagName(img[0].parentNode, "parentNode", "li", "LI")).addClass(img.hasClass("ui-li-icon") ? "ui-li-has-icon" : "ui-li-has-thumb");
- }
- }
- },
-
- _getChildrenByTagName: function (ele, lcName, ucName) {
- var results = [],
- dict = {};
- dict[lcName] = dict[ucName] = true;
- ele = ele.firstChild;
- while (ele) {
- if (dict[ele.nodeName]) {
- results.push(ele);
- }
- ele = ele.nextSibling;
- }
- return $(results);
- },
-
- _beforeListviewRefresh: $.noop,
- _afterListviewRefresh: $.noop,
-
- refresh: function (create) {
- var buttonClass, pos, numli, item, itemClass, itemTheme, itemIcon, icon, a,
- isDivider, startCount, newStartCount, value, last, splittheme, splitThemeClass, spliticon,
- altButtonClass, dividerTheme, li,
- o = this.options,
- $list = this.element,
- ol = !!$.nodeName($list[0], "ol"),
- start = $list.attr("start"),
- itemClassDict = {},
- countBubbles = $list.find(".ui-li-count"),
- countTheme = getAttr($list[0], "counttheme") || this.options.countTheme,
- countThemeClass = countTheme ? "ui-body-" + countTheme : "ui-body-inherit";
-
- if (o.theme) {
- $list.addClass("ui-group-theme-" + o.theme);
- }
-
- // Check if a start attribute has been set while taking a value of 0 into account
- if (ol && (start || start === 0)) {
- startCount = parseInt(start, 10) - 1;
- $list.css("counter-reset", "listnumbering " + startCount);
- }
-
- this._beforeListviewRefresh();
-
- li = this._getChildrenByTagName($list[0], "li", "LI");
-
- for (pos = 0, numli = li.length; pos < numli; pos++) {
- item = li.eq(pos);
- itemClass = "";
-
- if (create || item[0].className.search(/\bui-li-static\b|\bui-li-divider\b/) < 0) {
- a = this._getChildrenByTagName(item[0], "a", "A");
- isDivider = (getAttr(item[0], "role") === "list-divider");
- value = item.attr("value");
- itemTheme = getAttr(item[0], "theme");
-
- if (a.length && a[0].className.search(/\bui-btn\b/) < 0 && !isDivider) {
- itemIcon = getAttr(item[0], "icon");
- icon = (itemIcon === false) ? false : (itemIcon || o.icon);
-
- // TODO: Remove in 1.5 together with links.js (links.js / .ui-link deprecated in 1.4)
- a.removeClass("ui-link");
-
- buttonClass = "ui-btn";
-
- if (itemTheme) {
- buttonClass += " ui-btn-" + itemTheme;
- }
-
- if (a.length > 1) {
- itemClass = "ui-li-has-alt";
-
- last = a.last();
- splittheme = getAttr(last[0], "theme") || o.splitTheme || getAttr(item[0], "theme", true);
- splitThemeClass = splittheme ? " ui-btn-" + splittheme : "";
- spliticon = getAttr(last[0], "icon") || getAttr(item[0], "icon") || o.splitIcon;
- altButtonClass = "ui-btn ui-btn-icon-notext ui-icon-" + spliticon + splitThemeClass;
-
- last
- .attr("title", $.trim(last.text()))
- .addClass(altButtonClass)
- .empty();
-
- // Reduce to the first anchor, because only the first gets the buttonClass
- a = a.first();
- } else if (icon) {
- buttonClass += " ui-btn-icon-right ui-icon-" + icon;
- }
-
- // Apply buttonClass to the (first) anchor
- a.addClass(buttonClass);
- } else if (isDivider) {
- dividerTheme = (getAttr(item[0], "theme") || o.dividerTheme || o.theme);
-
- itemClass = "ui-li-divider ui-bar-" + (dividerTheme ? dividerTheme : "inherit");
-
- item.attr("role", "heading");
- } else if (a.length <= 0) {
- itemClass = "ui-li-static ui-body-" + (itemTheme ? itemTheme : "inherit");
- }
- if (ol && value) {
- newStartCount = parseInt(value, 10) - 1;
-
- item.css("counter-reset", "listnumbering " + newStartCount);
- }
- }
-
- // Instead of setting item class directly on the list item
- // at this point in time, push the item into a dictionary
- // that tells us what class to set on it so we can do this after this
- // processing loop is finished.
-
- if (!itemClassDict[itemClass]) {
- itemClassDict[itemClass] = [];
- }
-
- itemClassDict[itemClass].push(item[0]);
- }
-
- // Set the appropriate listview item classes on each list item.
- // The main reason we didn't do this
- // in the for-loop above is because we can eliminate per-item function overhead
- // by calling addClass() and children() once or twice afterwards. This
- // can give us a significant boost on platforms like WP7.5.
-
- for (itemClass in itemClassDict) {
- $(itemClassDict[itemClass]).addClass(itemClass);
- }
-
- countBubbles.each(function () {
- $(this).closest("li").addClass("ui-li-has-count");
- });
- if (countThemeClass) {
- countBubbles.not("[class*='ui-body-']").addClass(countThemeClass);
- }
-
- // Deprecated in 1.4. From 1.5 you have to add class ui-li-has-thumb or ui-li-has-icon to the LI.
- this._addThumbClasses(li);
- this._addThumbClasses(li.find(".ui-btn"));
-
- this._afterListviewRefresh();
-
- this._addFirstLastClasses(li, this._getVisibles(li, create), create);
- }
- }, $.mobile.behaviors.addFirstLastClasses));
-
-})(jQuery);
\ No newline at end of file
+});
\ No newline at end of file
diff --git a/dashboard-ui/thirdparty/jquerymobile-1.4.5/jqm.panel.js b/dashboard-ui/thirdparty/jquerymobile-1.4.5/jqm.panel.js
index 6c54050ebe..0a7cb9b3b6 100644
--- a/dashboard-ui/thirdparty/jquerymobile-1.4.5/jqm.panel.js
+++ b/dashboard-ui/thirdparty/jquerymobile-1.4.5/jqm.panel.js
@@ -1,1051 +1,531 @@
-(function () {
+define(['jqmwidget'], function () {
- if (jQuery.widget) {
- return;
- }
+ (function ($, undefined) {
+ var props = {
+ "animation": {},
+ "transition": {}
+ },
+ testElement = document.createElement("a"),
+ vendorPrefixes = ["", "webkit-", "moz-", "o-"];
+
+ $.each(["animation", "transition"], function (i, test) {
+
+ // Get correct name for test
+ var testName = (i === 0) ? test + "-" + "name" : test;
+
+ $.each(vendorPrefixes, function (j, prefix) {
+ if (testElement.style[$.camelCase(prefix + testName)] !== undefined) {
+ props[test]["prefix"] = prefix;
+ return false;
+ }
+ });
+
+ // Set event and duration names for later use
+ props[test]["duration"] =
+ $.camelCase(props[test]["prefix"] + test + "-" + "duration");
+ props[test]["event"] =
+ $.camelCase(props[test]["prefix"] + test + "-" + "end");
+
+ // All lower case if not a vendor prop
+ if (props[test]["prefix"] === "") {
+ props[test]["event"] = props[test]["event"].toLowerCase();
+ }
+ });
+
+ // Remove the testElement
+ $(testElement).remove();
+
+ // Animation complete callback
+ $.fn.animationComplete = function (callback, type, fallbackTime) {
+ var timer, duration,
+ that = this,
+ eventBinding = function () {
+
+ // Clear the timer so we don't call callback twice
+ clearTimeout(timer);
+ callback.apply(this, arguments);
+ },
+ animationType = (!type || type === "animation") ? "animation" : "transition";
+
+ // If a fallback time was not passed set one
+ if (fallbackTime === undefined) {
+
+ // Make sure the was not bound to document before checking .css
+ if ($(this).context !== document) {
+
+ // Parse the durration since its in second multiple by 1000 for milliseconds
+ // Multiply by 3 to make sure we give the animation plenty of time.
+ duration = parseFloat(
+ $(this).css(props[animationType].duration)
+ ) * 3000;
+ }
+
+ // If we could not read a duration use the default
+ if (duration === 0 || duration === undefined || isNaN(duration)) {
+ duration = $.fn.animationComplete.defaultDuration;
+ }
+ }
+
+ // Sets up the fallback if event never comes
+ timer = setTimeout(function () {
+ $(that).off(props[animationType].event, eventBinding);
+ callback.apply(that);
+ }, duration);
+
+ // Bind the event
+ return $(this).one(props[animationType].event, eventBinding);
+ };
+
+ // Allow default callback to be configured on mobileInit
+ $.fn.animationComplete.defaultDuration = 1000;
+ })(jQuery);
- /*!
- * jQuery UI Widget c0ab71056b936627e8a7821f03c044aec6280a40
- * http://jqueryui.com
- *
- * Copyright 2013 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * http://api.jqueryui.com/jQuery.widget/
- */
(function ($, undefined) {
- var uuid = 0,
- slice = Array.prototype.slice,
- _cleanData = $.cleanData;
- $.cleanData = function (elems) {
- for (var i = 0, elem; (elem = elems[i]) != null; i++) {
- try {
- $(elem).triggerHandler("remove");
- // http://bugs.jquery.com/ticket/8235
- } catch (e) { }
- }
- _cleanData(elems);
- };
-
- $.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 = 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 = slice.call(arguments, 1),
- returnValue = this;
-
- // allow multiple hashes to be passed on init
- options = !isMethodCall && args.length ?
- $.widget.extend.apply(null, [options].concat(args)) :
- options;
-
- 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 {
- this.each(function () {
- var instance = $.data(this, fullName);
- if (instance) {
- instance.option(options || {})._init();
- } else {
- $.data(this, fullName, new object(options, this));
- }
- });
- }
-
- return returnValue;
- };
- };
-
- $.Widget = function ( /* options, element */) { };
- $.Widget._childConstructors = [];
-
- $.Widget.prototype = {
- widgetName: "widget",
- widgetEventPrefix: "",
- defaultElement: "
",
+ $.widget("mobile.panel", {
options: {
- disabled: false,
-
- // callbacks
- create: null
+ animate: true,
+ theme: null,
+ position: "left",
+ dismissible: true,
+ display: "overlay", //accepts reveal, push, overlay
+ swipeClose: true,
+ positionFixed: true
},
- _createWidget: function (options, element) {
- element = $(element || this.defaultElement || this)[0];
- this.element = $(element);
- this.uuid = uuid++;
- this.eventNamespace = "." + this.widgetName + this.uuid;
- this.options = $.widget.extend({},
- this.options,
- this._getCreateOptions(),
- options);
- this.bindings = $();
- this.hoverable = $();
- this.focusable = $();
+ _parentPage: null,
+ _page: null,
+ _modal: null,
+ _panelInner: null,
+ _wrapper: null,
- if (element !== this) {
- $.data(element, this.widgetFullName, this);
- this._on(true, this.element, {
- remove: function (event) {
- if (event.target === element) {
- this.destroy();
+ _create: function () {
+ var el = this.element,
+ parentPage = el.closest(".ui-page, [data-role='page']");
+
+ // expose some private props to other methods
+ $.extend(this, {
+ _parentPage: (parentPage.length > 0) ? parentPage : false,
+ _openedPage: null,
+ _page: this._getPage,
+ _panelInner: this._getPanelInner()
+ });
+ if (this.options.display !== "overlay") {
+ this._getWrapper();
+ }
+ this._addPanelClasses();
+
+ // if animating, add the class to do so
+ if (!!this.options.animate) {
+ this.element.addClass("ui-panel-animate");
+ }
+
+ this._bindUpdateLayout();
+ this._bindCloseEvents();
+ this._bindLinkListeners();
+ this._bindPageEvents();
+
+ if (!!this.options.dismissible) {
+ this._createModal();
+ }
+
+ this._bindSwipeEvents();
+ },
+
+ _getPanelInner: function () {
+ var panelInner = this.element[0].querySelector("." + "ui-panel-inner");
+ if (!panelInner) {
+ panelInner = this.element.children().wrapAll("
").parent();
+ } else {
+ panelInner = $(panelInner);
+ }
+
+ return panelInner;
+ },
+
+ _createModal: function () {
+ var self = this,
+ target = self._parentPage ? self._parentPage.parent() : self.element.parent();
+
+ self._modal = $("
")
+ .on("mousedown", function () {
+ self.close();
+ })
+ .appendTo(target);
+ },
+
+ _getPage: function () {
+ var page = this._openedPage || this._parentPage || $(".ui-page-active");
+
+ return page;
+ },
+
+ _getWrapper: function () {
+ var wrapper = this._page().find("." + "ui-panel-wrapper");
+ if (wrapper.length === 0) {
+ wrapper = this._page().children(".ui-header:not(.ui-header-fixed), .ui-content:not(.ui-popup), .ui-footer:not(.ui-footer-fixed)")
+ .wrapAll("
")
+ .parent();
+ }
+
+ this._wrapper = wrapper;
+ },
+
+ _getPosDisplayClasses: function (prefix) {
+ return prefix + "-position-right " + prefix + "-display-" + this.options.display;
+ },
+
+ _getPanelClasses: function () {
+ var panelClasses = "ui-panel" +
+ " " + this._getPosDisplayClasses("ui-panel") +
+ " " + "ui-panel-closed" +
+ " " + "ui-body-" + (this.options.theme ? this.options.theme : "inherit");
+
+ if (!!this.options.positionFixed) {
+ panelClasses += " " + "ui-panel-fixed";
+ }
+
+ return panelClasses;
+ },
+
+ _addPanelClasses: function () {
+ this.element.addClass(this._getPanelClasses());
+ },
+
+ _handleCloseClick: function (event) {
+ if (!event.isDefaultPrevented()) {
+ this.close();
+ }
+ },
+
+ _bindCloseEvents: function () {
+ },
+
+ _positionPanel: function (scrollToTop) {
+ var self = this,
+ panelInnerHeight = self._panelInner.outerHeight(),
+ expand = panelInnerHeight > (window.innerHeight || $(window).height());
+
+ if (expand || !self.options.positionFixed) {
+ if (expand) {
+ self._unfixPanel();
+ }
+ if (scrollToTop) {
+ this.window[0].scrollTo(0, $.mobile.defaultHomeScroll);
+ }
+ } else {
+ self._fixPanel();
+ }
+ },
+
+ _bindFixListener: function () {
+ this._on($(window), { "resize": "_positionPanel" });
+ },
+
+ _unbindFixListener: function () {
+ this._off($(window), "resize");
+ },
+
+ _unfixPanel: function () {
+ if (!!this.options.positionFixed) {
+ this.element.removeClass("ui-panel-fixed");
+ }
+ },
+
+ _fixPanel: function () {
+ if (!!this.options.positionFixed) {
+ this.element.addClass("ui-panel-fixed");
+ }
+ },
+
+ _bindUpdateLayout: function () {
+ var self = this;
+
+ self.element.on("updatelayout", function (/* e */) {
+ if (self._open) {
+ self._positionPanel();
+ }
+ });
+ },
+
+ _bindLinkListeners: function () {
+ this._on("body", {
+ "click a": "_handleClick"
+ });
+
+ },
+
+ _handleClick: function (e) {
+ var link,
+ panelId = this.element.attr("id");
+
+ if (e.currentTarget.href.split("#")[1] === panelId && panelId !== undefined) {
+
+ e.preventDefault();
+ link = $(e.target);
+ if (link.hasClass("ui-btn")) {
+ link.addClass($.mobile.activeBtnClass);
+ this.element.one("panelopen panelclose", function () {
+ link.removeClass($.mobile.activeBtnClass);
+ });
+ }
+ this.toggle();
+ }
+ },
+
+ _bindSwipeEvents: function () {
+ var self = this,
+ area = self._modal ? self.element.add(self._modal) : self.element;
+
+ // on swipe, close the panel
+ if (!!self.options.swipeClose) {
+ if (self.options.position === "left") {
+ area.on("swipeleft.panel", function (/* e */) {
+ self.close();
+ });
+ } else {
+ area.on("swiperight.panel", function (/* e */) {
+ self.close();
+ });
+ }
+ }
+ },
+
+ _bindPageEvents: function () {
+ var self = this;
+
+ this.document
+ // Close the panel if another panel on the page opens
+ .on("panelbeforeopen", function (e) {
+ if (self._open && e.target !== self.element[0]) {
+ self.close();
+ }
+ })
+ // On escape, close? might need to have a target check too...
+ .on("keyup.panel", function (e) {
+ if (e.keyCode === 27 && self._open) {
+ self.close();
+ }
+ });
+ if (!this._parentPage && this.options.display !== "overlay") {
+ this._on(this.document, {
+ "pageshow": function () {
+ this._openedPage = null;
+ this._getWrapper();
+ }
+ });
+ }
+ // Clean up open panels after page hide
+ if (self._parentPage) {
+ this.document.on("pagehide", "[data-role='page']", function () {
+ if (self._open) {
+ self.close(true);
+ }
+ });
+ } else {
+ this.document.on("pagebeforehide", function () {
+ if (self._open) {
+ self.close(true);
+ }
+ });
+ }
+ },
+
+ // state storage of open or closed
+ _open: false,
+ _pageContentOpenClasses: null,
+ _modalOpenClasses: null,
+
+ open: function (immediate) {
+ if (!this._open) {
+ var self = this,
+ o = self.options,
+
+ _openPanel = function () {
+ self._off(self.document, "panelclose");
+ self._page().data("panel", "open");
+
+ if (!!o.animate && o.display !== "overlay") {
+ self._wrapper.addClass("ui-panel-animate");
}
- }
- });
- 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._create();
- this._trigger("create", null, this._getCreateEventData());
- this._init();
- },
- _getCreateOptions: $.noop,
- _getCreateEventData: $.noop,
- _create: $.noop,
- _init: $.noop,
+ if (!immediate && !!o.animate) {
+ (self._wrapper || self.element)
+ .animationComplete(complete, "transition");
+ } else {
+ setTimeout(complete, 0);
+ }
- 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");
+ if (o.theme && o.display !== "overlay") {
+ self._page().parent()
+ .addClass("ui-panel-page-container" + "-themed " + "ui-panel-page-container" + "-" + o.theme);
+ }
- // clean up events and states
- this.bindings.unbind(this.eventNamespace);
- this.hoverable.removeClass("ui-state-hover");
- this.focusable.removeClass("ui-state-focus");
- },
- _destroy: $.noop,
+ self.element
+ .removeClass("ui-panel-closed")
+ .addClass("ui-panel-open");
- widget: function () {
- return this.element;
- },
+ self._positionPanel(true);
- option: function (key, value) {
- var options = key,
- parts,
- curOption,
- i;
+ self._pageContentOpenClasses = self._getPosDisplayClasses("ui-panel-page-content");
- if (arguments.length === 0) {
- // don't return a reference to the internal hash
- return $.widget.extend({}, this.options);
- }
+ if (o.display !== "overlay") {
+ self._page().parent().addClass("ui-panel-page-container");
+ self._wrapper.addClass(self._pageContentOpenClasses);
+ }
- 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 (value === undefined) {
- return curOption[key] === undefined ? null : curOption[key];
- }
- curOption[key] = value;
+ self._modalOpenClasses = self._getPosDisplayClasses("ui-panel-dismiss") + " " + "ui-panel-dismiss-open";
+ if (self._modal) {
+ self._modal
+ .addClass(self._modalOpenClasses)
+ .height(Math.max(self._modal.height(), self.document.height()));
+ }
+ },
+ complete = function () {
+
+ // Bail if the panel was closed before the opening animation has completed
+ if (!self._open) {
+ return;
+ }
+
+ if (o.display !== "overlay") {
+ self._wrapper.addClass("ui-panel-page-content" + "-open");
+ }
+
+ self._bindFixListener();
+
+ self._trigger("open");
+
+ self._openedPage = self._page();
+ };
+
+ self._trigger("beforeopen");
+
+ if (self._page().data("panel") === "open") {
+ self._on(self.document, {
+ "panelclose": _openPanel
+ });
} else {
- if (value === undefined) {
- return this.options[key] === undefined ? null : this.options[key];
- }
- options[key] = value;
+ _openPanel();
}
+
+ self._open = true;
}
-
- 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);
- 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 });
+ close: function (immediate) {
+ if (this._open) {
+ var self = this,
+ o = this.options,
+
+ _closePanel = function () {
+
+ self.element.removeClass("ui-panel-open");
+
+ if (o.display !== "overlay") {
+ self._wrapper.removeClass(self._pageContentOpenClasses);
+ }
+
+ if (!immediate && !!o.animate) {
+ (self._wrapper || self.element)
+ .animationComplete(complete, "transition");
+ } else {
+ setTimeout(complete, 0);
+ }
+
+ if (self._modal) {
+ self._modal
+ .removeClass(self._modalOpenClasses)
+ .height("");
+ }
+ },
+ complete = function () {
+ if (o.theme && o.display !== "overlay") {
+ self._page().parent().removeClass("ui-panel-page-container" + "-themed " + "ui-panel-page-container" + "-" + o.theme);
+ }
+
+ self.element.addClass("ui-panel-closed");
+
+ if (o.display !== "overlay") {
+ self._page().parent().removeClass("ui-panel-page-container");
+ self._wrapper.removeClass("ui-panel-page-content" + "-open");
+ }
+
+ if (!!o.animate && o.display !== "overlay") {
+ self._wrapper.removeClass("ui-panel-animate");
+ }
+
+ self._fixPanel();
+ self._unbindFixListener();
+
+ self._page().removeData("panel");
+
+ self._trigger("close");
+
+ self._openedPage = null;
+ };
+
+ self._trigger("beforeclose");
+
+ _closePanel();
+
+ self._open = false;
+ }
},
- _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 {
- // accept selectors, DOM elements
- 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);
- }
- });
+ toggle: function () {
+ this[this._open ? "close" : "open"]();
},
- _off: function (element, eventName) {
- eventName = (eventName || "").split(" ").join(this.eventNamespace + " ") + this.eventNamespace;
- element.unbind(eventName).undelegate(eventName);
- },
+ _destroy: function () {
+ var otherPanels,
+ o = this.options,
+ multiplePanels = ($("body > :mobile-panel").length + $.mobile.activePage.find(":mobile-panel").length) > 1;
- _trigger: function (type, event, data) {
- var prop, orig,
- callback = this.options[type];
+ if (o.display !== "overlay") {
- 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];
+ // remove the wrapper if not in use by another panel
+ otherPanels = $("body > :mobile-panel").add($.mobile.activePage.find(":mobile-panel"));
+ if (otherPanels.not(".ui-panel-display-overlay").not(this.element).length === 0) {
+ this._wrapper.children().unwrap();
+ }
- // 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];
+ if (this._open) {
+
+ this._page().parent().removeClass("ui-panel-page-container");
+
+ if (o.theme) {
+ this._page().parent().removeClass("ui-panel-page-container" + "-themed " + "ui-panel-page-container" + "-" + o.theme);
}
}
}
- this.element[0].dispatchEvent(new CustomEvent(event.type, {
- bubbles: true,
- detail: {
- data: data,
- originalEvent: event
- }
- }));
+ if (!multiplePanels) {
- //this.element.trigger(event, data);
- return !($.isFunction(callback) &&
- callback.apply(this.element[0], [event].concat(data)) === false ||
- event.isDefaultPrevented());
- }
- };
+ this.document.off("panelopen panelclose");
- })(jQuery);
-
- (function ($, undefined) {
-
- $.extend($.Widget.prototype, {
- _getCreateOptions: function () {
-
- var option, value,
- elem = this.element[0],
- options = {};
-
- //
- if (!this.element.data("defaults")) {
- for (option in this.options) {
-
- value = this.element.data(option);
-
- if (value != null) {
- options[option] = value;
- }
- }
- }
-
- return options;
- }
- });
-
- })(jQuery);
-
- (function ($, undefined) {
-
-
- var originalWidget = $.widget
-
- $.widget = (function (orig) {
- return function () {
- var constructor = orig.apply(this, arguments),
- name = constructor.prototype.widgetName;
-
- constructor.initSelector = ((constructor.prototype.initSelector !== undefined) ?
- constructor.prototype.initSelector : "*[data-role='" + name + "']:not([data-role='none'])");
-
- $.mobile.widgets[name] = constructor;
-
- return constructor;
- };
- })($.widget);
-
- // Make sure $.widget still has bridge and extend methods
- $.extend($.widget, originalWidget);
-
- })(jQuery);
-
-
-})();
-
-(function ($, undefined) {
- var props = {
- "animation": {},
- "transition": {}
- },
- testElement = document.createElement("a"),
- vendorPrefixes = ["", "webkit-", "moz-", "o-"];
-
- $.each(["animation", "transition"], function (i, test) {
-
- // Get correct name for test
- var testName = (i === 0) ? test + "-" + "name" : test;
-
- $.each(vendorPrefixes, function (j, prefix) {
- if (testElement.style[$.camelCase(prefix + testName)] !== undefined) {
- props[test]["prefix"] = prefix;
- return false;
- }
- });
-
- // Set event and duration names for later use
- props[test]["duration"] =
- $.camelCase(props[test]["prefix"] + test + "-" + "duration");
- props[test]["event"] =
- $.camelCase(props[test]["prefix"] + test + "-" + "end");
-
- // All lower case if not a vendor prop
- if (props[test]["prefix"] === "") {
- props[test]["event"] = props[test]["event"].toLowerCase();
- }
- });
-
- // Remove the testElement
- $(testElement).remove();
-
- // Animation complete callback
- $.fn.animationComplete = function (callback, type, fallbackTime) {
- var timer, duration,
- that = this,
- eventBinding = function () {
-
- // Clear the timer so we don't call callback twice
- clearTimeout(timer);
- callback.apply(this, arguments);
- },
- animationType = (!type || type === "animation") ? "animation" : "transition";
-
- // If a fallback time was not passed set one
- if (fallbackTime === undefined) {
-
- // Make sure the was not bound to document before checking .css
- if ($(this).context !== document) {
-
- // Parse the durration since its in second multiple by 1000 for milliseconds
- // Multiply by 3 to make sure we give the animation plenty of time.
- duration = parseFloat(
- $(this).css(props[animationType].duration)
- ) * 3000;
- }
-
- // If we could not read a duration use the default
- if (duration === 0 || duration === undefined || isNaN(duration)) {
- duration = $.fn.animationComplete.defaultDuration;
- }
- }
-
- // Sets up the fallback if event never comes
- timer = setTimeout(function () {
- $(that).off(props[animationType].event, eventBinding);
- callback.apply(that);
- }, duration);
-
- // Bind the event
- return $(this).one(props[animationType].event, eventBinding);
- };
-
- // Allow default callback to be configured on mobileInit
- $.fn.animationComplete.defaultDuration = 1000;
-})(jQuery);
-
-(function ($, undefined) {
-
- $.widget("mobile.panel", {
- options: {
- animate: true,
- theme: null,
- position: "left",
- dismissible: true,
- display: "overlay", //accepts reveal, push, overlay
- swipeClose: true,
- positionFixed: true
- },
-
- _parentPage: null,
- _page: null,
- _modal: null,
- _panelInner: null,
- _wrapper: null,
-
- _create: function () {
- var el = this.element,
- parentPage = el.closest(".ui-page, [data-role='page']");
-
- // expose some private props to other methods
- $.extend(this, {
- _parentPage: (parentPage.length > 0) ? parentPage : false,
- _openedPage: null,
- _page: this._getPage,
- _panelInner: this._getPanelInner()
- });
- if (this.options.display !== "overlay") {
- this._getWrapper();
- }
- this._addPanelClasses();
-
- // if animating, add the class to do so
- if (!!this.options.animate) {
- this.element.addClass("ui-panel-animate");
- }
-
- this._bindUpdateLayout();
- this._bindCloseEvents();
- this._bindLinkListeners();
- this._bindPageEvents();
-
- if (!!this.options.dismissible) {
- this._createModal();
- }
-
- this._bindSwipeEvents();
- },
-
- _getPanelInner: function () {
- var panelInner = this.element[0].querySelector("." + "ui-panel-inner");
- if (!panelInner) {
- panelInner = this.element.children().wrapAll("
").parent();
- } else {
- panelInner = $(panelInner);
- }
-
- return panelInner;
- },
-
- _createModal: function () {
- var self = this,
- target = self._parentPage ? self._parentPage.parent() : self.element.parent();
-
- self._modal = $("
")
- .on("mousedown", function () {
- self.close();
- })
- .appendTo(target);
- },
-
- _getPage: function () {
- var page = this._openedPage || this._parentPage || $(".ui-page-active");
-
- return page;
- },
-
- _getWrapper: function () {
- var wrapper = this._page().find("." + "ui-panel-wrapper");
- if (wrapper.length === 0) {
- wrapper = this._page().children(".ui-header:not(.ui-header-fixed), .ui-content:not(.ui-popup), .ui-footer:not(.ui-footer-fixed)")
- .wrapAll("
")
- .parent();
- }
-
- this._wrapper = wrapper;
- },
-
- _getPosDisplayClasses: function (prefix) {
- return prefix + "-position-right " + prefix + "-display-" + this.options.display;
- },
-
- _getPanelClasses: function () {
- var panelClasses = "ui-panel" +
- " " + this._getPosDisplayClasses("ui-panel") +
- " " + "ui-panel-closed" +
- " " + "ui-body-" + (this.options.theme ? this.options.theme : "inherit");
-
- if (!!this.options.positionFixed) {
- panelClasses += " " + "ui-panel-fixed";
- }
-
- return panelClasses;
- },
-
- _addPanelClasses: function () {
- this.element.addClass(this._getPanelClasses());
- },
-
- _handleCloseClick: function (event) {
- if (!event.isDefaultPrevented()) {
- this.close();
- }
- },
-
- _bindCloseEvents: function () {
- },
-
- _positionPanel: function (scrollToTop) {
- var self = this,
- panelInnerHeight = self._panelInner.outerHeight(),
- expand = panelInnerHeight > (window.innerHeight || $(window).height());
-
- if (expand || !self.options.positionFixed) {
- if (expand) {
- self._unfixPanel();
- }
- if (scrollToTop) {
- this.window[0].scrollTo(0, $.mobile.defaultHomeScroll);
- }
- } else {
- self._fixPanel();
- }
- },
-
- _bindFixListener: function () {
- this._on($(window), { "resize": "_positionPanel" });
- },
-
- _unbindFixListener: function () {
- this._off($(window), "resize");
- },
-
- _unfixPanel: function () {
- if (!!this.options.positionFixed) {
- this.element.removeClass("ui-panel-fixed");
- }
- },
-
- _fixPanel: function () {
- if (!!this.options.positionFixed) {
- this.element.addClass("ui-panel-fixed");
- }
- },
-
- _bindUpdateLayout: function () {
- var self = this;
-
- self.element.on("updatelayout", function (/* e */) {
- if (self._open) {
- self._positionPanel();
- }
- });
- },
-
- _bindLinkListeners: function () {
- this._on("body", {
- "click a": "_handleClick"
- });
-
- },
-
- _handleClick: function (e) {
- var link,
- panelId = this.element.attr("id");
-
- if (e.currentTarget.href.split("#")[1] === panelId && panelId !== undefined) {
-
- e.preventDefault();
- link = $(e.target);
- if (link.hasClass("ui-btn")) {
- link.addClass($.mobile.activeBtnClass);
- this.element.one("panelopen panelclose", function () {
- link.removeClass($.mobile.activeBtnClass);
- });
- }
- this.toggle();
- }
- },
-
- _bindSwipeEvents: function () {
- var self = this,
- area = self._modal ? self.element.add(self._modal) : self.element;
-
- // on swipe, close the panel
- if (!!self.options.swipeClose) {
- if (self.options.position === "left") {
- area.on("swipeleft.panel", function (/* e */) {
- self.close();
- });
- } else {
- area.on("swiperight.panel", function (/* e */) {
- self.close();
- });
- }
- }
- },
-
- _bindPageEvents: function () {
- var self = this;
-
- this.document
- // Close the panel if another panel on the page opens
- .on("panelbeforeopen", function (e) {
- if (self._open && e.target !== self.element[0]) {
- self.close();
- }
- })
- // On escape, close? might need to have a target check too...
- .on("keyup.panel", function (e) {
- if (e.keyCode === 27 && self._open) {
- self.close();
- }
- });
- if (!this._parentPage && this.options.display !== "overlay") {
- this._on(this.document, {
- "pageshow": function () {
- this._openedPage = null;
- this._getWrapper();
- }
- });
- }
- // Clean up open panels after page hide
- if (self._parentPage) {
- this.document.on("pagehide", "[data-role='page']", function () {
- if (self._open) {
- self.close(true);
- }
- });
- } else {
- this.document.on("pagebeforehide", function () {
- if (self._open) {
- self.close(true);
- }
- });
- }
- },
-
- // state storage of open or closed
- _open: false,
- _pageContentOpenClasses: null,
- _modalOpenClasses: null,
-
- open: function (immediate) {
- if (!this._open) {
- var self = this,
- o = self.options,
-
- _openPanel = function () {
- self._off(self.document, "panelclose");
- self._page().data("panel", "open");
-
- if (!!o.animate && o.display !== "overlay") {
- self._wrapper.addClass("ui-panel-animate");
- }
-
- if (!immediate && !!o.animate) {
- (self._wrapper || self.element)
- .animationComplete(complete, "transition");
- } else {
- setTimeout(complete, 0);
- }
-
- if (o.theme && o.display !== "overlay") {
- self._page().parent()
- .addClass("ui-panel-page-container" + "-themed " + "ui-panel-page-container" + "-" + o.theme);
- }
-
- self.element
- .removeClass("ui-panel-closed")
- .addClass("ui-panel-open");
-
- self._positionPanel(true);
-
- self._pageContentOpenClasses = self._getPosDisplayClasses("ui-panel-page-content");
-
- if (o.display !== "overlay") {
- self._page().parent().addClass("ui-panel-page-container");
- self._wrapper.addClass(self._pageContentOpenClasses);
- }
-
- self._modalOpenClasses = self._getPosDisplayClasses("ui-panel-dismiss") + " " + "ui-panel-dismiss-open";
- if (self._modal) {
- self._modal
- .addClass(self._modalOpenClasses)
- .height(Math.max(self._modal.height(), self.document.height()));
- }
- },
- complete = function () {
-
- // Bail if the panel was closed before the opening animation has completed
- if (!self._open) {
- return;
- }
-
- if (o.display !== "overlay") {
- self._wrapper.addClass("ui-panel-page-content" + "-open");
- }
-
- self._bindFixListener();
-
- self._trigger("open");
-
- self._openedPage = self._page();
- };
-
- self._trigger("beforeopen");
-
- if (self._page().data("panel") === "open") {
- self._on(self.document, {
- "panelclose": _openPanel
- });
- } else {
- _openPanel();
- }
-
- self._open = true;
- }
- },
-
- close: function (immediate) {
- if (this._open) {
- var self = this,
- o = this.options,
-
- _closePanel = function () {
-
- self.element.removeClass("ui-panel-open");
-
- if (o.display !== "overlay") {
- self._wrapper.removeClass(self._pageContentOpenClasses);
- }
-
- if (!immediate && !!o.animate) {
- (self._wrapper || self.element)
- .animationComplete(complete, "transition");
- } else {
- setTimeout(complete, 0);
- }
-
- if (self._modal) {
- self._modal
- .removeClass(self._modalOpenClasses)
- .height("");
- }
- },
- complete = function () {
- if (o.theme && o.display !== "overlay") {
- self._page().parent().removeClass("ui-panel-page-container" + "-themed " + "ui-panel-page-container" + "-" + o.theme);
- }
-
- self.element.addClass("ui-panel-closed");
-
- if (o.display !== "overlay") {
- self._page().parent().removeClass("ui-panel-page-container");
- self._wrapper.removeClass("ui-panel-page-content" + "-open");
- }
-
- if (!!o.animate && o.display !== "overlay") {
- self._wrapper.removeClass("ui-panel-animate");
- }
-
- self._fixPanel();
- self._unbindFixListener();
-
- self._page().removeData("panel");
-
- self._trigger("close");
-
- self._openedPage = null;
- };
-
- self._trigger("beforeclose");
-
- _closePanel();
-
- self._open = false;
- }
- },
-
- toggle: function () {
- this[this._open ? "close" : "open"]();
- },
-
- _destroy: function () {
- var otherPanels,
- o = this.options,
- multiplePanels = ($("body > :mobile-panel").length + $.mobile.activePage.find(":mobile-panel").length) > 1;
-
- if (o.display !== "overlay") {
-
- // remove the wrapper if not in use by another panel
- otherPanels = $("body > :mobile-panel").add($.mobile.activePage.find(":mobile-panel"));
- if (otherPanels.not(".ui-panel-display-overlay").not(this.element).length === 0) {
- this._wrapper.children().unwrap();
}
if (this._open) {
+ this._page().removeData("panel");
+ }
- this._page().parent().removeClass("ui-panel-page-container");
+ this._panelInner.children().unwrap();
- if (o.theme) {
- this._page().parent().removeClass("ui-panel-page-container" + "-themed " + "ui-panel-page-container" + "-" + o.theme);
- }
+ this.element
+ .removeClass([this._getPanelClasses(), "ui-panel-open", "ui-panel-animate"].join(" "))
+ .off("swipeleft.panel swiperight.panel")
+ .off("panelbeforeopen")
+ .off("panelhide")
+ .off("keyup.panel")
+ .off("updatelayout");
+
+ if (this._modal) {
+ this._modal.remove();
}
}
+ });
- if (!multiplePanels) {
+ })(jQuery);
- this.document.off("panelopen panelclose");
-
- }
-
- if (this._open) {
- this._page().removeData("panel");
- }
-
- this._panelInner.children().unwrap();
-
- this.element
- .removeClass([this._getPanelClasses(), "ui-panel-open", "ui-panel-animate"].join(" "))
- .off("swipeleft.panel swiperight.panel")
- .off("panelbeforeopen")
- .off("panelhide")
- .off("keyup.panel")
- .off("updatelayout");
-
- if (this._modal) {
- this._modal.remove();
- }
- }
- });
-
-})(jQuery);
\ No newline at end of file
+});
\ No newline at end of file
diff --git a/dashboard-ui/thirdparty/jquerymobile-1.4.5/jqm.popup.js b/dashboard-ui/thirdparty/jquerymobile-1.4.5/jqm.popup.js
index 41042ad83d..3ec34800c2 100644
--- a/dashboard-ui/thirdparty/jquerymobile-1.4.5/jqm.popup.js
+++ b/dashboard-ui/thirdparty/jquerymobile-1.4.5/jqm.popup.js
@@ -1,1805 +1,1284 @@
-(function () {
+define(['jqmwidget'], function () {
- if (jQuery.widget) {
- return;
- }
-
- /*!
- * jQuery UI Widget c0ab71056b936627e8a7821f03c044aec6280a40
- * http://jqueryui.com
- *
- * Copyright 2013 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * http://api.jqueryui.com/jQuery.widget/
- */
(function ($, undefined) {
+ var props = {
+ "animation": {},
+ "transition": {}
+ },
+ testElement = document.createElement("a"),
+ vendorPrefixes = ["", "webkit-", "moz-", "o-"];
- var uuid = 0,
- slice = Array.prototype.slice,
- _cleanData = $.cleanData;
- $.cleanData = function (elems) {
- for (var i = 0, elem; (elem = elems[i]) != null; i++) {
- try {
- $(elem).triggerHandler("remove");
- // http://bugs.jquery.com/ticket/8235
- } catch (e) { }
- }
- _cleanData(elems);
- };
+ $.each(["animation", "transition"], function (i, test) {
- $.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];
+ // Get correct name for test
+ var testName = (i === 0) ? test + "-" + "name" : test;
- 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);
+ $.each(vendorPrefixes, function (j, prefix) {
+ if (testElement.style[$.camelCase(prefix + testName)] !== undefined) {
+ props[test]["prefix"] = prefix;
+ return false;
}
-
- // 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;
+ // Set event and duration names for later use
+ props[test]["duration"] =
+ $.camelCase(props[test]["prefix"] + test + "-" + "duration");
+ props[test]["event"] =
+ $.camelCase(props[test]["prefix"] + test + "-" + "end");
+
+ // All lower case if not a vendor prop
+ if (props[test]["prefix"] === "") {
+ props[test]["event"] = props[test]["event"].toLowerCase();
+ }
+ });
+
+ // Remove the testElement
+ $(testElement).remove();
+
+ // Animation complete callback
+ $.fn.animationComplete = function (callback, type, fallbackTime) {
+ var timer, duration,
+ that = this,
+ eventBinding = function () {
+
+ // Clear the timer so we don't call callback twice
+ clearTimeout(timer);
+ callback.apply(this, arguments);
+ },
+ animationType = (!type || type === "animation") ? "animation" : "transition";
+
+ // If a fallback time was not passed set one
+ if (fallbackTime === undefined) {
+
+ // Make sure the was not bound to document before checking .css
+ if ($(this).context !== document) {
+
+ // Parse the durration since its in second multiple by 1000 for milliseconds
+ // Multiply by 3 to make sure we give the animation plenty of time.
+ duration = parseFloat(
+ $(this).css(props[animationType].duration)
+ ) * 3000;
+ }
+
+ // If we could not read a duration use the default
+ if (duration === 0 || duration === undefined || isNaN(duration)) {
+ duration = $.fn.animationComplete.defaultDuration;
+ }
+ }
+
+ // Sets up the fallback if event never comes
+ timer = setTimeout(function () {
+ $(that).off(props[animationType].event, eventBinding);
+ callback.apply(that);
+ }, duration);
+
+ // Bind the event
+ return $(this).one(props[animationType].event, eventBinding);
+ };
+
+ // Allow default callback to be configured on mobileInit
+ $.fn.animationComplete.defaultDuration = 1000;
+ })(jQuery);
+
+ (function ($, undefined) {
+
+ function fitSegmentInsideSegment(windowSize, segmentSize, offset, desired) {
+ var returnValue = desired;
+
+ if (windowSize < segmentSize) {
+ // Center segment if it's bigger than the window
+ returnValue = offset + (windowSize - segmentSize) / 2;
+ } else {
+ // Otherwise center it at the desired coordinate while keeping it completely inside the window
+ returnValue = Math.min(Math.max(offset, desired - segmentSize / 2), offset + windowSize - segmentSize);
+ }
+
+ return returnValue;
+ }
+
+ function getWindowCoordinates(theWindow) {
+ return {
+ x: theWindow.scrollLeft(),
+ y: theWindow.scrollTop(),
+ cx: (theWindow[0].innerWidth || theWindow.width()),
+ cy: (theWindow[0].innerHeight || theWindow.height())
+ };
+ }
+
+ // non-UA-based IE version check by James Padolsey, modified by jdalton - from http://gist.github.com/527683
+ // allows for inclusion of IE 6+, including Windows Mobile 7
+ $.extend($.mobile, { browser: {} });
+ $.mobile.browser.oldIE = (function () {
+ var v = 3,
+ div = document.createElement("div"),
+ a = div.all || [];
+
+ do {
+ div.innerHTML = "";
+ } while (a[0]);
+
+ return v > 4 ? v : !v;
+ })();
+
+ $.widget("mobile.popup", {
+ options: {
+ wrapperClass: null,
+ theme: null,
+ overlayTheme: null,
+ shadow: true,
+ corners: true,
+ transition: "none",
+ positionTo: "origin",
+ tolerance: null,
+ closeLinkSelector: "a[data-rel='back']",
+ closeLinkEvents: "click.popup",
+ navigateEvents: "navigate.popup",
+ closeEvents: "navigate.popup pagebeforechange.popup",
+ dismissible: true,
+ enhanced: false,
+
+ // NOTE Windows Phone 7 has a scroll position caching issue that
+ // requires us to disable popup history management by default
+ // https://github.com/jquery/jquery-mobile/issues/4784
+ //
+ // NOTE this option is modified in _create!
+ history: !$.mobile.browser.oldIE
+ },
+
+ // When the user depresses the mouse/finger on an element inside the popup while the popup is
+ // open, we ignore resize events for a short while. This prevents #6961.
+ _handleDocumentVmousedown: function (theEvent) {
+ if (this._isOpen && $.contains(this._ui.container[0], theEvent.target)) {
+ this._ignoreResizeEvents();
+ }
+ },
+
+ _create: function () {
+ var theElement = this.element,
+ myId = theElement.attr("id"),
+ currentOptions = this.options;
+
+ // We need to adjust the history option to be false if there's no AJAX nav.
+ // We can't do it in the option declarations because those are run before
+ // it is determined whether there shall be AJAX nav.
+ currentOptions.history = currentOptions.history && $.mobile.ajaxEnabled && $.mobile.hashListeningEnabled;
+
+ this._on(this.document, {
+ "mousedown": "_handleDocumentVmousedown"
+ });
+
+ // Define instance variables
+ $.extend(this, {
+ _scrollTop: 0,
+ _page: theElement.closest(".ui-page"),
+ _ui: null,
+ _fallbackTransition: "",
+ _currentTransition: false,
+ _prerequisites: null,
+ _isOpen: false,
+ _tolerance: null,
+ _resizeData: null,
+ _ignoreResizeTo: 0,
+ _orientationchangeInProgress: false
+ });
+
+ if (this._page.length === 0) {
+ this._page = $("body");
+ }
+
+ if (currentOptions.enhanced) {
+ this._ui = {
+ container: theElement.parent(),
+ screen: theElement.parent().prev(),
+ placeholder: $(this.document[0].getElementById(myId + "-placeholder"))
+ };
+ } else {
+ this._ui = this._enhance(theElement, myId);
+ this._applyTransition(currentOptions.transition);
+ }
+ this
+ ._setTolerance(currentOptions.tolerance)
+ ._ui.focusElement = this._ui.container;
+
+ // Event handlers
+ this._on(this._ui.screen, { "click": "_eatEventAndClose" });
+ this._on(this.window, {
+ orientationchange: $.proxy(this, "_handleWindowOrientationchange"),
+ resize: $.proxy(this, "_handleWindowResize")
+ });
+ this._on(this.document, { "focusin": "_handleDocumentFocusIn" });
+ },
+
+ _delay: function (handler, delay) {
+ function handlerProxy() {
+ return (typeof handler === "string" ? instance[handler] : handler)
+ .apply(instance, arguments);
+ }
+ var instance = this;
+ return setTimeout(handlerProxy, delay || 0);
+ },
+
+ _enhance: function (theElement, myId) {
+ var currentOptions = this.options,
+ wrapperClass = currentOptions.wrapperClass,
+ ui = {
+ screen: $(""),
+ placeholder: $("
"),
+ container: $("")
+ },
+ fragment = this.document[0].createDocumentFragment();
+
+ fragment.appendChild(ui.screen[0]);
+ fragment.appendChild(ui.container[0]);
+
+ if (myId) {
+ ui.screen.attr("id", myId + "-screen");
+ ui.container.attr("id", myId + "-popup");
+ ui.placeholder
+ .attr("id", myId + "-placeholder")
+ .html("");
+ }
+
+ // Apply the proto
+ this._page[0].appendChild(fragment);
+ // Leave a placeholder where the element used to be
+ ui.placeholder.insertAfter(theElement);
+ theElement
+ .detach()
+ .addClass("ui-popup " +
+ this._themeClassFromOption("ui-body-", currentOptions.theme) + " " +
+ (currentOptions.shadow ? "ui-overlay-shadow " : "") +
+ (currentOptions.corners ? "ui-corner-all " : ""))
+ .appendTo(ui.container);
+
+ return ui;
+ },
+
+ _eatEventAndClose: function (theEvent) {
+ theEvent.preventDefault();
+ theEvent.stopImmediatePropagation();
+ if (this.options.dismissible) {
+ this.close();
+ }
+ return false;
+ },
+
+ // Make sure the screen covers the entire document - CSS is sometimes not
+ // enough to accomplish this.
+ _resizeScreen: function () {
+ var screen = this._ui.screen,
+ popupHeight = this._ui.container.outerHeight(true),
+ screenHeight = screen.removeAttr("style").height(),
+
+ // Subtracting 1 here is necessary for an obscure Andrdoid 4.0 bug where
+ // the browser hangs if the screen covers the entire document :/
+ documentHeight = this.document.height() - 1;
+
+ if (screenHeight < documentHeight) {
+ screen.height(documentHeight);
+ } else if (popupHeight > screenHeight) {
+ screen.height(popupHeight);
+ }
+ },
+
+ _expectResizeEvent: function () {
+ var windowCoordinates = getWindowCoordinates(this.window);
+
+ if (this._resizeData) {
+ if (windowCoordinates.x === this._resizeData.windowCoordinates.x &&
+ windowCoordinates.y === this._resizeData.windowCoordinates.y &&
+ windowCoordinates.cx === this._resizeData.windowCoordinates.cx &&
+ windowCoordinates.cy === this._resizeData.windowCoordinates.cy) {
+ // timeout not refreshed
+ return false;
+ } else {
+ // clear existing timeout - it will be refreshed below
+ clearTimeout(this._resizeData.timeoutId);
+ }
+ }
+
+ this._resizeData = {
+ timeoutId: this._delay("_resizeTimeout", 200),
+ windowCoordinates: windowCoordinates
+ };
+
+ return true;
+ },
+
+ _resizeTimeout: function () {
+ if (this._isOpen) {
+ if (!this._expectResizeEvent()) {
+ if (this._ui.container.hasClass("ui-popup-hidden")) {
+ // effectively rapid-open the popup while leaving the screen intact
+ this._ui.container.removeClass("ui-popup-hidden ui-popup-truncate");
+ this.reposition({ positionTo: "window" });
+ this._ignoreResizeEvents();
+ }
+
+ this._resizeScreen();
+ this._resizeData = null;
+ this._orientationchangeInProgress = false;
+ }
+ } else {
+ this._resizeData = null;
+ this._orientationchangeInProgress = false;
+ }
+ },
+
+ _stopIgnoringResizeEvents: function () {
+ this._ignoreResizeTo = 0;
+ },
+
+ _ignoreResizeEvents: function () {
+ if (this._ignoreResizeTo) {
+ clearTimeout(this._ignoreResizeTo);
+ }
+ this._ignoreResizeTo = this._delay("_stopIgnoringResizeEvents", 1000);
+ },
+
+ _handleWindowResize: function (/* theEvent */) {
+ if (this._isOpen && this._ignoreResizeTo === 0) {
+ if ((this._expectResizeEvent() || this._orientationchangeInProgress) &&
+ !this._ui.container.hasClass("ui-popup-hidden")) {
+ // effectively rapid-close the popup while leaving the screen intact
+ this._ui.container
+ .addClass("ui-popup-hidden ui-popup-truncate")
+ .removeAttr("style");
+ }
+ }
+ },
+
+ _handleWindowOrientationchange: function (/* theEvent */) {
+ if (!this._orientationchangeInProgress && this._isOpen && this._ignoreResizeTo === 0) {
+ this._expectResizeEvent();
+ this._orientationchangeInProgress = true;
+ }
+ },
+
+ // When the popup is open, attempting to focus on an element that is not a
+ // child of the popup will redirect focus to the popup
+ _handleDocumentFocusIn: function (theEvent) {
+ var target,
+ targetElement = theEvent.target,
+ ui = this._ui;
+
+ if (!this._isOpen) {
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 = 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;
- }
+ if (targetElement !== ui.container[0]) {
+ target = $(targetElement);
+ if (!$.contains(ui.container[0], targetElement)) {
+ $(this.document[0].activeElement).one("focus", $.proxy(function () {
+ this._safelyBlur(targetElement);
+ }, this));
+ ui.focusElement.focus();
+ theEvent.preventDefault();
+ theEvent.stopImmediatePropagation();
+ return false;
+ } else if (ui.focusElement[0] === ui.container[0]) {
+ ui.focusElement = target;
}
}
- }
- return target;
- };
- $.widget.bridge = function (name, object) {
+ this._ignoreResizeEvents();
+ },
- var fullName = object.prototype.widgetFullName || name;
- $.fn[name] = function (options) {
- var isMethodCall = typeof options === "string",
- args = slice.call(arguments, 1),
- returnValue = this;
+ _themeClassFromOption: function (prefix, value) {
+ return (value ? (value === "none" ? "" : (prefix + value)) : (prefix + "inherit"));
+ },
- // allow multiple hashes to be passed on init
- options = !isMethodCall && args.length ?
- $.widget.extend.apply(null, [options].concat(args)) :
- options;
-
- if (isMethodCall) {
- this.each(function () {
- var methodValue,
- instance = $.data(this, fullName);
- if (options === "instance") {
- returnValue = instance;
- return false;
+ _applyTransition: function (value) {
+ if (value) {
+ this._ui.container.removeClass(this._fallbackTransition);
+ if (value !== "none") {
+ this._fallbackTransition = $.mobile._maybeDegradeTransition(value);
+ if (this._fallbackTransition === "none") {
+ this._fallbackTransition = "";
}
- 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 {
- this.each(function () {
- var instance = $.data(this, fullName);
- if (instance) {
- instance.option(options || {})._init();
- } else {
- $.data(this, fullName, new object(options, this));
- }
- });
+ this._ui.container.addClass(this._fallbackTransition);
+ }
}
+ return this;
+ },
+
+ _setOptions: function (newOptions) {
+ var currentOptions = this.options,
+ theElement = this.element,
+ screen = this._ui.screen;
+
+ if (newOptions.wrapperClass !== undefined) {
+ this._ui.container
+ .removeClass(currentOptions.wrapperClass)
+ .addClass(newOptions.wrapperClass);
+ }
+
+ if (newOptions.theme !== undefined) {
+ theElement
+ .removeClass(this._themeClassFromOption("ui-body-", currentOptions.theme))
+ .addClass(this._themeClassFromOption("ui-body-", newOptions.theme));
+ }
+
+ if (newOptions.overlayTheme !== undefined) {
+ screen
+ .removeClass(this._themeClassFromOption("ui-overlay-", currentOptions.overlayTheme))
+ .addClass(this._themeClassFromOption("ui-overlay-", newOptions.overlayTheme));
+
+ if (this._isOpen) {
+ screen.addClass("in");
+ }
+ }
+
+ if (newOptions.shadow !== undefined) {
+ theElement.toggleClass("ui-overlay-shadow", newOptions.shadow);
+ }
+
+ if (newOptions.corners !== undefined) {
+ theElement.toggleClass("ui-corner-all", newOptions.corners);
+ }
+
+ if (newOptions.transition !== undefined) {
+ if (!this._currentTransition) {
+ this._applyTransition(newOptions.transition);
+ }
+ }
+
+ if (newOptions.tolerance !== undefined) {
+ this._setTolerance(newOptions.tolerance);
+ }
+
+ if (newOptions.disabled !== undefined) {
+ if (newOptions.disabled) {
+ this.close();
+ }
+ }
+
+ return this._super(newOptions);
+ },
+
+ _setTolerance: function (value) {
+ var tol = { t: 30, r: 15, b: 30, l: 15 },
+ ar;
+
+ if (value !== undefined) {
+ ar = String(value).split(",");
+
+ $.each(ar, function (idx, val) { ar[idx] = parseInt(val, 10); });
+
+ switch (ar.length) {
+ // All values are to be the same
+ case 1:
+ if (!isNaN(ar[0])) {
+ tol.t = tol.r = tol.b = tol.l = ar[0];
+ }
+ break;
+
+ // The first value denotes top/bottom tolerance, and the second value denotes left/right tolerance
+ case 2:
+ if (!isNaN(ar[0])) {
+ tol.t = tol.b = ar[0];
+ }
+ if (!isNaN(ar[1])) {
+ tol.l = tol.r = ar[1];
+ }
+ break;
+
+ // The array contains values in the order top, right, bottom, left
+ case 4:
+ if (!isNaN(ar[0])) {
+ tol.t = ar[0];
+ }
+ if (!isNaN(ar[1])) {
+ tol.r = ar[1];
+ }
+ if (!isNaN(ar[2])) {
+ tol.b = ar[2];
+ }
+ if (!isNaN(ar[3])) {
+ tol.l = ar[3];
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ this._tolerance = tol;
+ return this;
+ },
+
+ _clampPopupWidth: function (infoOnly) {
+ var menuSize,
+ windowCoordinates = getWindowCoordinates(this.window),
+ // rectangle within which the popup must fit
+ rectangle = {
+ x: this._tolerance.l,
+ y: windowCoordinates.y + this._tolerance.t,
+ cx: windowCoordinates.cx - this._tolerance.l - this._tolerance.r,
+ cy: windowCoordinates.cy - this._tolerance.t - this._tolerance.b
+ };
+
+ if (!infoOnly) {
+ // Clamp the width of the menu before grabbing its size
+ this._ui.container.css("max-width", rectangle.cx);
+ }
+
+ menuSize = {
+ cx: this._ui.container.outerWidth(true),
+ cy: this._ui.container.outerHeight(true)
+ };
+
+ return { rc: rectangle, menuSize: menuSize };
+ },
+
+ _calculateFinalLocation: function (desired, clampInfo) {
+ var returnValue,
+ rectangle = clampInfo.rc,
+ menuSize = clampInfo.menuSize;
+
+ // Center the menu over the desired coordinates, while not going outside
+ // the window tolerances. This will center wrt. the window if the popup is
+ // too large.
+ returnValue = {
+ left: fitSegmentInsideSegment(rectangle.cx, menuSize.cx, rectangle.x, desired.x),
+ top: fitSegmentInsideSegment(rectangle.cy, menuSize.cy, rectangle.y, desired.y)
+ };
+
+ // Make sure the top of the menu is visible
+ returnValue.top = Math.max(0, returnValue.top);
+
+ // If the height of the menu is smaller than the height of the document
+ // align the bottom with the bottom of the document
+
+ returnValue.top -= Math.min(returnValue.top,
+ Math.max(0, returnValue.top + menuSize.cy - this.document.height()));
+
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 = uuid++;
- this.eventNamespace = "." + this.widgetName + this.uuid;
- this.options = $.widget.extend({},
- this.options,
- this._getCreateOptions(),
- options);
- this.bindings = $();
- this.hoverable = $();
- this.focusable = $();
+ // Try and center the overlay over the given coordinates
+ _placementCoords: function (desired) {
+ return this._calculateFinalLocation(desired, this._clampPopupWidth());
+ },
- if (element !== this) {
- $.data(element, this.widgetFullName, this);
- this._on(true, this.element, {
- remove: function (event) {
- if (event.target === element) {
- this.destroy();
+ _createPrerequisites: function (screenPrerequisite, containerPrerequisite, whenDone) {
+ var prerequisites,
+ self = this;
+
+ // It is important to maintain both the local variable prerequisites and
+ // self._prerequisites. The local variable remains in the closure of the
+ // functions which call the callbacks passed in. The comparison between the
+ // local variable and self._prerequisites is necessary, because once a
+ // function has been passed to .animationComplete() it will be called next
+ // time an animation completes, even if that's not the animation whose end
+ // the function was supposed to catch (for example, if an abort happens
+ // during the opening animation, the .animationComplete handler is not
+ // called for that animation anymore, but the handler remains attached, so
+ // it is called the next time the popup is opened - making it stale.
+ // Comparing the local variable prerequisites to the widget-level variable
+ // self._prerequisites ensures that callbacks triggered by a stale
+ // .animationComplete will be ignored.
+
+ prerequisites = {
+ screen: $.Deferred(),
+ container: $.Deferred()
+ };
+
+ prerequisites.screen.then(function () {
+ if (prerequisites === self._prerequisites) {
+ screenPrerequisite();
+ }
+ });
+
+ prerequisites.container.then(function () {
+ if (prerequisites === self._prerequisites) {
+ containerPrerequisite();
+ }
+ });
+
+ Promise.all([prerequisites.screen, prerequisites.container]).then(function () {
+ if (prerequisites === self._prerequisites) {
+ self._prerequisites = null;
+ whenDone();
+ }
+ });
+
+ self._prerequisites = prerequisites;
+ },
+
+ _animate: function (args) {
+ // NOTE before removing the default animation of the screen
+ // this had an animate callback that would resolve the deferred
+ // now the deferred is resolved immediately
+ // TODO remove the dependency on the screen deferred
+ this._ui.screen
+ .removeClass(args.classToRemove)
+ .addClass(args.screenClassToAdd);
+
+ args.prerequisites.screen.resolve();
+
+ if (args.transition && args.transition !== "none") {
+ if (args.applyTransition) {
+ this._applyTransition(args.transition);
+ }
+ if (this._fallbackTransition) {
+ this._ui.container
+ .addClass(args.containerClassToAdd)
+ .removeClass(args.classToRemove)
+ .animationComplete($.proxy(args.prerequisites.container, "resolve"));
+ return;
+ }
+ }
+ this._ui.container.removeClass(args.classToRemove);
+ args.prerequisites.container.resolve();
+ },
+
+ // The desired coordinates passed in will be returned untouched if no reference element can be identified via
+ // desiredPosition.positionTo. Nevertheless, this function ensures that its return value always contains valid
+ // x and y coordinates by specifying the center middle of the window if the coordinates are absent.
+ // options: { x: coordinate, y: coordinate, positionTo: string: "origin", "window", or jQuery selector
+ _desiredCoords: function (openOptions) {
+ var offset,
+ dst = null,
+ windowCoordinates = getWindowCoordinates(this.window),
+ x = openOptions.x,
+ y = openOptions.y,
+ pTo = openOptions.positionTo;
+
+ // Establish which element will serve as the reference
+ if (pTo && pTo !== "origin") {
+ if (pTo === "window") {
+ x = windowCoordinates.cx / 2 + windowCoordinates.x;
+ y = windowCoordinates.cy / 2 + windowCoordinates.y;
+ } else {
+ try {
+ dst = $(pTo);
+ } catch (err) {
+ dst = null;
+ }
+ if (dst) {
+ dst.filter(":visible");
+ if (dst.length === 0) {
+ dst = null;
}
}
- });
- 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._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 (value === undefined) {
- return curOption[key] === undefined ? null : curOption[key];
- }
- curOption[key] = value;
- } else {
- if (value === undefined) {
- 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]);
+ // If an element was found, center over it
+ if (dst) {
+ offset = dst.offset();
+ x = offset.left + dst.outerWidth() / 2;
+ y = offset.top + dst.outerHeight() / 2;
}
- return this;
- },
- _setOption: function (key, value) {
- this.options[key] = value;
-
- if (key === "disabled") {
- this.widget()
- .toggleClass(this.widgetFullName + "-disabled", !!value);
- this.hoverable.removeClass("ui-state-hover");
- this.focusable.removeClass("ui-state-focus");
+ // Make sure x and y are valid numbers - center over the window
+ if ($.type(x) !== "number" || isNaN(x)) {
+ x = windowCoordinates.cx / 2 + windowCoordinates.x;
+ }
+ if ($.type(y) !== "number" || isNaN(y)) {
+ y = windowCoordinates.cy / 2 + windowCoordinates.y;
}
- return this;
+ return { x: x, y: y };
},
- enable: function () {
- return this._setOptions({ disabled: false });
- },
- disable: function () {
- return this._setOptions({ disabled: true });
+ _reposition: function (openOptions) {
+ // We only care about position-related parameters for repositioning
+ openOptions = {
+ x: openOptions.x,
+ y: openOptions.y,
+ positionTo: openOptions.positionTo
+ };
+ this._trigger("beforeposition", undefined, openOptions);
+ this._ui.container.offset(this._placementCoords(this._desiredCoords(openOptions)));
},
- _on: function (suppressDisabledCheck, element, handlers) {
- var delegateElement,
- instance = this;
-
- // no suppressDisabledCheck flag, shuffle arguments
- if (typeof suppressDisabledCheck !== "boolean") {
- handlers = element;
- element = suppressDisabledCheck;
- suppressDisabledCheck = false;
+ reposition: function (openOptions) {
+ if (this._isOpen) {
+ this._reposition(openOptions);
}
+ },
- // no element argument, shuffle and use this.element
- if (!handlers) {
- handlers = element;
- element = this.element;
- delegateElement = this.widget();
- } else {
- // accept selectors, DOM elements
- element = delegateElement = $(element);
- this.bindings = this.bindings.add(element);
+ _safelyBlur: function (currentElement) {
+ if (currentElement !== this.window[0] &&
+ currentElement.nodeName.toLowerCase() !== "body") {
+ $(currentElement).blur();
}
+ },
- $.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;
+ _openPrerequisitesComplete: function () {
+ var id = this.element.attr("id");
+
+ this._ui.container.addClass("ui-popup-active");
+ this._isOpen = true;
+ this._resizeScreen();
+
+ // Check to see if currElement is not a child of the container. If it's not, blur
+ if (!$.contains(this._ui.container[0], this.document[0].activeElement)) {
+ this._safelyBlur(this.document[0].activeElement);
+ }
+ this._ignoreResizeEvents();
+ if (id) {
+ this.document.find("[aria-haspopup='true'][aria-owns='" + id + "']").attr("aria-expanded", true);
+ }
+ this._trigger("afteropen");
+ },
+
+ _open: function (options) {
+ var openOptions = $.extend({}, this.options, options),
+ // TODO move blacklist to private method
+ androidBlacklist = (function () {
+ var ua = navigator.userAgent,
+ // Rendering engine is Webkit, and capture major version
+ wkmatch = ua.match(/AppleWebKit\/([0-9\.]+)/),
+ wkversion = !!wkmatch && wkmatch[1],
+ androidmatch = ua.match(/Android (\d+(?:\.\d+))/),
+ andversion = !!androidmatch && androidmatch[1],
+ chromematch = ua.indexOf("Chrome") > -1;
+
+ // Platform is Android, WebKit version is greater than 534.13 ( Android 3.2.1 ) and not Chrome.
+ if (androidmatch !== null && andversion === "4.0" && wkversion && wkversion > 534.13 && !chromematch) {
+ return true;
}
- return (typeof handler === "string" ? instance[handler] : handler)
- .apply(instance, arguments);
- }
+ return false;
+ }());
- // copy the guid so direct unbinding works
- if (typeof handler !== "string") {
- handlerProxy.guid = handler.guid =
- handler.guid || handlerProxy.guid || $.guid++;
- }
+ // Count down to triggering "popupafteropen" - we have two prerequisites:
+ // 1. The popup window animation completes (container())
+ // 2. The screen opacity animation completes (screen())
+ this._createPrerequisites(
+ $.noop,
+ $.noop,
+ $.proxy(this, "_openPrerequisitesComplete"));
- 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);
- }
+ this._currentTransition = openOptions.transition;
+ this._applyTransition(openOptions.transition);
+
+ this._ui.screen.removeClass("ui-screen-hidden");
+ this._ui.container.removeClass("ui-popup-truncate");
+
+ // Give applications a chance to modify the contents of the container before it appears
+ this._reposition(openOptions);
+
+ this._ui.container.removeClass("ui-popup-hidden");
+
+ if (this.options.overlayTheme && androidBlacklist) {
+ /* TODO: The native browser on Android 4.0.X ("Ice Cream Sandwich") suffers from an issue where the popup overlay appears to be z-indexed above the popup itself when certain other styles exist on the same page -- namely, any element set to `position: fixed` and certain types of input. These issues are reminiscent of previously uncovered bugs in older versions of Android's native browser: https://github.com/scottjehl/Device-Bugs/issues/3
+ This fix closes the following bugs ( I use "closes" with reluctance, and stress that this issue should be revisited as soon as possible ):
+ https://github.com/jquery/jquery-mobile/issues/4816
+ https://github.com/jquery/jquery-mobile/issues/4844
+ https://github.com/jquery/jquery-mobile/issues/4874
+ */
+
+ // TODO sort out why this._page isn't working
+ this.element.closest(".ui-page").addClass("ui-popup-open");
+ }
+ this._animate({
+ additionalCondition: true,
+ transition: openOptions.transition,
+ classToRemove: "",
+ screenClassToAdd: "in",
+ containerClassToAdd: "in",
+ applyTransition: false,
+ prerequisites: this._prerequisites
});
},
- _off: function (element, eventName) {
- eventName = (eventName || "").split(" ").join(this.eventNamespace + " ") + this.eventNamespace;
- element.unbind(eventName).undelegate(eventName);
+ _closePrerequisiteScreen: function () {
+ this._ui.screen
+ .removeClass("out")
+ .addClass("ui-screen-hidden");
},
- _trigger: function (type, event, data) {
- var prop, orig,
- callback = this.options[type];
+ _closePrerequisiteContainer: function () {
+ this._ui.container
+ .removeClass("reverse out")
+ .addClass("ui-popup-hidden ui-popup-truncate")
+ .removeAttr("style");
+ },
- 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];
+ _closePrerequisitesDone: function () {
+ var container = this._ui.container,
+ id = this.element.attr("id");
- // 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];
- }
+ // remove the global mutex for popups
+ $.mobile.popup.active = undefined;
+
+ // Blur elements inside the container, including the container
+ $(":focus", container[0]).add(container[0]).blur();
+
+ if (id) {
+ this.document.find("[aria-haspopup='true'][aria-owns='" + id + "']").attr("aria-expanded", false);
+ }
+
+ // alert users that the popup is closed
+ this._trigger("afterclose");
+ },
+
+ _close: function (immediate) {
+ this._ui.container.removeClass("ui-popup-active");
+ this._page.removeClass("ui-popup-open");
+
+ this._isOpen = false;
+
+ // Count down to triggering "popupafterclose" - we have two prerequisites:
+ // 1. The popup window reverse animation completes (container())
+ // 2. The screen opacity animation completes (screen())
+ this._createPrerequisites(
+ $.proxy(this, "_closePrerequisiteScreen"),
+ $.proxy(this, "_closePrerequisiteContainer"),
+ $.proxy(this, "_closePrerequisitesDone"));
+
+ this._animate({
+ additionalCondition: this._ui.screen.hasClass("in"),
+ transition: (immediate ? "none" : (this._currentTransition)),
+ classToRemove: "in",
+ screenClassToAdd: "out",
+ containerClassToAdd: "reverse out",
+ applyTransition: true,
+ prerequisites: this._prerequisites
+ });
+ },
+
+ _unenhance: function () {
+ if (this.options.enhanced) {
+ return;
+ }
+
+ // Put the element back to where the placeholder was and remove the "ui-popup" class
+ this._setOptions({ theme: $.mobile.popup.prototype.options.theme });
+ this.element
+ // Cannot directly insertAfter() - we need to detach() first, because
+ // insertAfter() will do nothing if the payload div was not attached
+ // to the DOM at the time the widget was created, and so the payload
+ // will remain inside the container even after we call insertAfter().
+ // If that happens and we remove the container a few lines below, we
+ // will cause an infinite recursion - #5244
+ .detach()
+ .insertAfter(this._ui.placeholder)
+ .removeClass("ui-popup ui-overlay-shadow ui-corner-all ui-body-inherit");
+ this._ui.screen.remove();
+ this._ui.container.remove();
+ this._ui.placeholder.remove();
+ },
+
+ _destroy: function () {
+ if ($.mobile.popup.active === this) {
+ this.element.one("popupafterclose", $.proxy(this, "_unenhance"));
+ this.close();
+ } else {
+ this._unenhance();
+ }
+
+ return this;
+ },
+
+ _closePopup: function (theEvent, data) {
+ var parsedDst, toUrl,
+ currentOptions = this.options,
+ immediate = false;
+
+ if ((theEvent && theEvent.isDefaultPrevented()) || $.mobile.popup.active !== this) {
+ return;
+ }
+
+ // restore location on screen
+ window.scrollTo(0, this._scrollTop);
+
+ if (theEvent && theEvent.type === "pagebeforechange" && data) {
+ // Determine whether we need to rapid-close the popup, or whether we can
+ // take the time to run the closing transition
+ if (typeof data.toPage === "string") {
+ parsedDst = data.toPage;
+ } else {
+ parsedDst = data.toPage.data("url");
+ }
+ parsedDst = $.mobile.path.parseUrl(parsedDst);
+ toUrl = parsedDst.pathname + parsedDst.search + parsedDst.hash;
+
+ if (this._myUrl !== $.mobile.path.makeUrlAbsolute(toUrl)) {
+ // Going to a different page - close immediately
+ immediate = true;
+ } else {
+ theEvent.preventDefault();
}
}
- this.element[0].dispatchEvent(new CustomEvent(event.type, {
- bubbles: true,
- detail: {
- data: data,
- originalEvent: event
- }
- }));
+ // remove nav bindings
+ this.window.off(currentOptions.closeEvents);
+ // unbind click handlers added when history is disabled
+ this.element.undelegate(currentOptions.closeLinkSelector, currentOptions.closeLinkEvents);
- //this.element.trigger(event, data);
- return !($.isFunction(callback) &&
- callback.apply(this.element[0], [event].concat(data)) === false ||
- event.isDefaultPrevented());
+ this._close(immediate);
+ },
+
+ // any navigation event after a popup is opened should close the popup
+ // NOTE the pagebeforechange is bound to catch navigation events that don't
+ // alter the url (eg, dialogs from popups)
+ _bindContainerClose: function () {
+ this.window
+ .on(this.options.closeEvents, $.proxy(this, "_closePopup"));
+ },
+
+ widget: function () {
+ return this._ui.container;
+ },
+
+ // TODO no clear deliniation of what should be here and
+ // what should be in _open. Seems to be "visual" vs "history" for now
+ open: function (options) {
+ var url, hashkey, activePage, currentIsDialog, hasHash, urlHistory,
+ self = this,
+ currentOptions = this.options;
+
+ // make sure open is idempotent
+ if ($.mobile.popup.active || currentOptions.disabled) {
+ return this;
+ }
+
+ // set the global popup mutex
+ $.mobile.popup.active = this;
+ this._scrollTop = this.window.scrollTop();
+
+ // if history alteration is disabled close on navigate events
+ // and leave the url as is
+ if (!(currentOptions.history)) {
+ self._open(options);
+ self._bindContainerClose();
+
+ // When histoy is disabled we have to grab the data-rel
+ // back link clicks so we can close the popup instead of
+ // relying on history to do it for us
+ self.element
+ .delegate(currentOptions.closeLinkSelector, currentOptions.closeLinkEvents, function (theEvent) {
+ self.close();
+ theEvent.preventDefault();
+ });
+
+ return this;
+ }
+
+ // cache some values for min/readability
+ urlHistory = $.mobile.navigate.history;
+ hashkey = $.mobile.dialogHashKey;
+ activePage = $.mobile.activePage;
+ currentIsDialog = (activePage ? activePage.hasClass("ui-dialog") : false);
+ this._myUrl = url = urlHistory.getActive().url;
+ hasHash = (url.indexOf(hashkey) > -1) && !currentIsDialog && (urlHistory.activeIndex > 0);
+
+ if (hasHash) {
+ self._open(options);
+ self._bindContainerClose();
+ return this;
+ }
+
+ // if the current url has no dialog hash key proceed as normal
+ // otherwise, if the page is a dialog simply tack on the hash key
+ if (url.indexOf(hashkey) === -1 && !currentIsDialog) {
+ url = url + (url.indexOf("#") > -1 ? hashkey : "#" + hashkey);
+ } else {
+ url = $.mobile.path.parseLocation().hash + hashkey;
+ }
+
+ // swallow the the initial navigation event, and bind for the next
+ this.window.one("beforenavigate", function (theEvent) {
+ theEvent.preventDefault();
+ self._open(options);
+ self._bindContainerClose();
+ });
+
+ this.urlAltered = true;
+ $.mobile.navigate(url, { role: "dialog" });
+
+ return this;
+ },
+
+ close: function () {
+ // make sure close is idempotent
+ if ($.mobile.popup.active !== this) {
+ return this;
+ }
+
+ this._scrollTop = this.window.scrollTop();
+
+ if (this.options.history && this.urlAltered) {
+ $.mobile.pageContainer.pagecontainer("back");
+ this.urlAltered = false;
+ } else {
+ // simulate the nav bindings having fired
+ this._closePopup();
+ }
+
+ return this;
}
+ });
+
+ // TODO this can be moved inside the widget
+ $.mobile.popup.handleLink = function ($link) {
+ var offset,
+ path = $.mobile.path,
+
+ // NOTE make sure to get only the hash from the href because ie7 (wp7)
+ // returns the absolute href in this case ruining the element selection
+ popup = $(path.hashToSelector(path.parseUrl($link.attr("href")).hash)).first();
+
+ if (popup.length > 0 && popup.data("mobile-popup")) {
+ offset = $link.offset();
+ popup.popup("open", {
+ x: offset.left + $link.outerWidth() / 2,
+ y: offset.top + $link.outerHeight() / 2,
+ transition: $link.data("transition"),
+ positionTo: $link.data("position-to")
+ });
+ }
+
+ //remove after delay
+ setTimeout(function () {
+ $link.removeClass($.mobile.activeBtnClass);
+ }, 300);
};
+ // TODO move inside _create
+ $(document).on("pagebeforechange", function (theEvent, data) {
+ if (data.options.role === "popup") {
+ $.mobile.popup.handleLink(data.options.link);
+ theEvent.preventDefault();
+ }
+ });
+
})(jQuery);
+
(function ($, undefined) {
- $.extend($.Widget.prototype, {
- _getCreateOptions: function () {
+ var ieHack = ($.mobile.browser.oldIE && $.mobile.browser.oldIE <= 8),
+ uiTemplate = $(
+ "" +
+ ""
+ );
- var option, value,
- elem = this.element[0],
- options = {};
+ function getArrow() {
+ var clone = uiTemplate.clone(),
+ gd = clone.eq(0),
+ ct = clone.eq(1),
+ ar = ct.children();
- //
- if (!this.element.data("defaults")) {
- for (option in this.options) {
+ return { arEls: ct.add(gd), gd: gd, ct: ct, ar: ar };
+ }
- value = this.element.data(option);
+ $.widget("mobile.popup", $.mobile.popup, {
+ options: {
- if (value != null) {
- options[option] = value;
- }
+ arrow: ""
+ },
+
+ _create: function () {
+ var ar,
+ ret = this._super();
+
+ if (this.options.arrow) {
+ this._ui.arrow = ar = this._addArrow();
+ }
+
+ return ret;
+ },
+
+ _addArrow: function () {
+ var theme,
+ opts = this.options,
+ ar = getArrow();
+
+ theme = this._themeClassFromOption("ui-body-", opts.theme);
+ ar.ar.addClass(theme + (opts.shadow ? " ui-overlay-shadow" : ""));
+ ar.arEls.hide().appendTo(this.element);
+
+ return ar;
+ },
+
+ _unenhance: function () {
+ var ar = this._ui.arrow;
+
+ if (ar) {
+ ar.arEls.remove();
+ }
+
+ return this._super();
+ },
+
+ // Pretend to show an arrow described by @p and @dir and calculate the
+ // distance from the desired point. If a best-distance is passed in, return
+ // the minimum of the one passed in and the one calculated.
+ _tryAnArrow: function (p, dir, desired, s, best) {
+ var result, r, diff, desiredForArrow = {}, tip = {};
+
+ // If the arrow has no wiggle room along the edge of the popup, it cannot
+ // be displayed along the requested edge without it sticking out.
+ if (s.arFull[p.dimKey] > s.guideDims[p.dimKey]) {
+ return best;
+ }
+
+ desiredForArrow[p.fst] = desired[p.fst] +
+ (s.arHalf[p.oDimKey] + s.menuHalf[p.oDimKey]) * p.offsetFactor -
+ s.contentBox[p.fst] + (s.clampInfo.menuSize[p.oDimKey] - s.contentBox[p.oDimKey]) * p.arrowOffsetFactor;
+ desiredForArrow[p.snd] = desired[p.snd];
+
+ result = s.result || this._calculateFinalLocation(desiredForArrow, s.clampInfo);
+ r = { x: result.left, y: result.top };
+
+ tip[p.fst] = r[p.fst] + s.contentBox[p.fst] + p.tipOffset;
+ tip[p.snd] = Math.max(result[p.prop] + s.guideOffset[p.prop] + s.arHalf[p.dimKey],
+ Math.min(result[p.prop] + s.guideOffset[p.prop] + s.guideDims[p.dimKey] - s.arHalf[p.dimKey],
+ desired[p.snd]));
+
+ diff = Math.abs(desired.x - tip.x) + Math.abs(desired.y - tip.y);
+ if (!best || diff < best.diff) {
+ // Convert tip offset to coordinates inside the popup
+ tip[p.snd] -= s.arHalf[p.dimKey] + result[p.prop] + s.contentBox[p.snd];
+ best = { dir: dir, diff: diff, result: result, posProp: p.prop, posVal: tip[p.snd] };
+ }
+
+ return best;
+ },
+
+ _getPlacementState: function (clamp) {
+ var offset, gdOffset,
+ ar = this._ui.arrow,
+ state = {
+ clampInfo: this._clampPopupWidth(!clamp),
+ arFull: { cx: ar.ct.width(), cy: ar.ct.height() },
+ guideDims: { cx: ar.gd.width(), cy: ar.gd.height() },
+ guideOffset: ar.gd.offset()
+ };
+
+ offset = this.element.offset();
+
+ ar.gd.css({ left: 0, top: 0, right: 0, bottom: 0 });
+ gdOffset = ar.gd.offset();
+ state.contentBox = {
+ x: gdOffset.left - offset.left,
+ y: gdOffset.top - offset.top,
+ cx: ar.gd.width(),
+ cy: ar.gd.height()
+ };
+ ar.gd.removeAttr("style");
+
+ // The arrow box moves between guideOffset and guideOffset + guideDims - arFull
+ state.guideOffset = { left: state.guideOffset.left - offset.left, top: state.guideOffset.top - offset.top };
+ state.arHalf = { cx: state.arFull.cx / 2, cy: state.arFull.cy / 2 };
+ state.menuHalf = { cx: state.clampInfo.menuSize.cx / 2, cy: state.clampInfo.menuSize.cy / 2 };
+
+ return state;
+ },
+
+ _placementCoords: function (desired) {
+ var state, best, params, elOffset, bgRef,
+ optionValue = this.options.arrow,
+ ar = this._ui.arrow;
+
+ if (!ar) {
+ return this._super(desired);
+ }
+
+ ar.arEls.show();
+
+ bgRef = {};
+ state = this._getPlacementState(true);
+ params = {
+ "l": { fst: "x", snd: "y", prop: "top", dimKey: "cy", oDimKey: "cx", offsetFactor: 1, tipOffset: -state.arHalf.cx, arrowOffsetFactor: 0 },
+ "r": { fst: "x", snd: "y", prop: "top", dimKey: "cy", oDimKey: "cx", offsetFactor: -1, tipOffset: state.arHalf.cx + state.contentBox.cx, arrowOffsetFactor: 1 },
+ "b": { fst: "y", snd: "x", prop: "left", dimKey: "cx", oDimKey: "cy", offsetFactor: -1, tipOffset: state.arHalf.cy + state.contentBox.cy, arrowOffsetFactor: 1 },
+ "t": { fst: "y", snd: "x", prop: "left", dimKey: "cx", oDimKey: "cy", offsetFactor: 1, tipOffset: -state.arHalf.cy, arrowOffsetFactor: 0 }
+ };
+
+ // Try each side specified in the options to see on which one the arrow
+ // should be placed such that the distance between the tip of the arrow and
+ // the desired coordinates is the shortest.
+ $.each((optionValue === true ? "l,t,r,b" : optionValue).split(","),
+ $.proxy(function (key, value) {
+ best = this._tryAnArrow(params[value], value, desired, state, best);
+ }, this));
+
+ // Could not place the arrow along any of the edges - behave as if showing
+ // the arrow was turned off.
+ if (!best) {
+ ar.arEls.hide();
+ return this._super(desired);
+ }
+
+ // Move the arrow into place
+ ar.ct
+ .removeClass("ui-popup-arrow-l ui-popup-arrow-t ui-popup-arrow-r ui-popup-arrow-b")
+ .addClass("ui-popup-arrow-" + best.dir)
+ .removeAttr("style").css(best.posProp, best.posVal)
+ .show();
+
+ // Do not move/size the background div on IE, because we use the arrow div for background as well.
+ if (!ieHack) {
+ elOffset = this.element.offset();
+ bgRef[params[best.dir].fst] = ar.ct.offset();
+ bgRef[params[best.dir].snd] = {
+ left: elOffset.left + state.contentBox.x,
+ top: elOffset.top + state.contentBox.y
+ };
+ }
+
+ return best.result;
+ },
+
+ _setOptions: function (opts) {
+ var newTheme,
+ oldTheme = this.options.theme,
+ ar = this._ui.arrow,
+ ret = this._super(opts);
+
+ if (opts.arrow !== undefined) {
+ if (!ar && opts.arrow) {
+ this._ui.arrow = this._addArrow();
+
+ // Important to return here so we don't set the same options all over
+ // again below.
+ return;
+ } else if (ar && !opts.arrow) {
+ ar.arEls.remove();
+ this._ui.arrow = null;
}
}
- return options;
- }
- });
+ // Reassign with potentially new arrow
+ ar = this._ui.arrow;
- })(jQuery);
+ if (ar) {
+ if (opts.theme !== undefined) {
+ oldTheme = this._themeClassFromOption("ui-body-", oldTheme);
+ newTheme = this._themeClassFromOption("ui-body-", opts.theme);
+ ar.ar.removeClass(oldTheme).addClass(newTheme);
+ }
- (function ($, undefined) {
+ if (opts.shadow !== undefined) {
+ ar.ar.toggleClass("ui-overlay-shadow", opts.shadow);
+ }
+ }
-
- var originalWidget = $.widget
-
- $.widget = (function (orig) {
- return function () {
- var constructor = orig.apply(this, arguments),
- name = constructor.prototype.widgetName;
-
- constructor.initSelector = ((constructor.prototype.initSelector !== undefined) ?
- constructor.prototype.initSelector : "*[data-role='" + name + "']:not([data-role='none'])");
-
- $.mobile.widgets[name] = constructor;
-
- return constructor;
- };
- })($.widget);
-
- // Make sure $.widget still has bridge and extend methods
- $.extend($.widget, originalWidget);
-
- })(jQuery);
-
-
-})();
-
-(function ($, undefined) {
- var props = {
- "animation": {},
- "transition": {}
- },
- testElement = document.createElement("a"),
- vendorPrefixes = ["", "webkit-", "moz-", "o-"];
-
- $.each(["animation", "transition"], function (i, test) {
-
- // Get correct name for test
- var testName = (i === 0) ? test + "-" + "name" : test;
-
- $.each(vendorPrefixes, function (j, prefix) {
- if (testElement.style[$.camelCase(prefix + testName)] !== undefined) {
- props[test]["prefix"] = prefix;
- return false;
- }
- });
-
- // Set event and duration names for later use
- props[test]["duration"] =
- $.camelCase(props[test]["prefix"] + test + "-" + "duration");
- props[test]["event"] =
- $.camelCase(props[test]["prefix"] + test + "-" + "end");
-
- // All lower case if not a vendor prop
- if (props[test]["prefix"] === "") {
- props[test]["event"] = props[test]["event"].toLowerCase();
- }
- });
-
- // Remove the testElement
- $(testElement).remove();
-
- // Animation complete callback
- $.fn.animationComplete = function (callback, type, fallbackTime) {
- var timer, duration,
- that = this,
- eventBinding = function () {
-
- // Clear the timer so we don't call callback twice
- clearTimeout(timer);
- callback.apply(this, arguments);
+ return ret;
},
- animationType = (!type || type === "animation") ? "animation" : "transition";
- // If a fallback time was not passed set one
- if (fallbackTime === undefined) {
+ _destroy: function () {
+ var ar = this._ui.arrow;
- // Make sure the was not bound to document before checking .css
- if ($(this).context !== document) {
+ if (ar) {
+ ar.arEls.remove();
+ }
- // Parse the durration since its in second multiple by 1000 for milliseconds
- // Multiply by 3 to make sure we give the animation plenty of time.
- duration = parseFloat(
- $(this).css(props[animationType].duration)
- ) * 3000;
+ return this._super();
}
+ });
- // If we could not read a duration use the default
- if (duration === 0 || duration === undefined || isNaN(duration)) {
- duration = $.fn.animationComplete.defaultDuration;
- }
- }
-
- // Sets up the fallback if event never comes
- timer = setTimeout(function () {
- $(that).off(props[animationType].event, eventBinding);
- callback.apply(that);
- }, duration);
-
- // Bind the event
- return $(this).one(props[animationType].event, eventBinding);
- };
-
- // Allow default callback to be configured on mobileInit
- $.fn.animationComplete.defaultDuration = 1000;
-})(jQuery);
-
-(function ($, undefined) {
-
- function fitSegmentInsideSegment(windowSize, segmentSize, offset, desired) {
- var returnValue = desired;
-
- if (windowSize < segmentSize) {
- // Center segment if it's bigger than the window
- returnValue = offset + (windowSize - segmentSize) / 2;
- } else {
- // Otherwise center it at the desired coordinate while keeping it completely inside the window
- returnValue = Math.min(Math.max(offset, desired - segmentSize / 2), offset + windowSize - segmentSize);
- }
-
- return returnValue;
- }
-
- function getWindowCoordinates(theWindow) {
- return {
- x: theWindow.scrollLeft(),
- y: theWindow.scrollTop(),
- cx: (theWindow[0].innerWidth || theWindow.width()),
- cy: (theWindow[0].innerHeight || theWindow.height())
- };
- }
-
- // non-UA-based IE version check by James Padolsey, modified by jdalton - from http://gist.github.com/527683
- // allows for inclusion of IE 6+, including Windows Mobile 7
- $.extend($.mobile, { browser: {} });
- $.mobile.browser.oldIE = (function () {
- var v = 3,
- div = document.createElement("div"),
- a = div.all || [];
-
- do {
- div.innerHTML = "";
- } while (a[0]);
-
- return v > 4 ? v : !v;
- })();
-
- $.widget("mobile.popup", {
- options: {
- wrapperClass: null,
- theme: null,
- overlayTheme: null,
- shadow: true,
- corners: true,
- transition: "none",
- positionTo: "origin",
- tolerance: null,
- closeLinkSelector: "a[data-rel='back']",
- closeLinkEvents: "click.popup",
- navigateEvents: "navigate.popup",
- closeEvents: "navigate.popup pagebeforechange.popup",
- dismissible: true,
- enhanced: false,
-
- // NOTE Windows Phone 7 has a scroll position caching issue that
- // requires us to disable popup history management by default
- // https://github.com/jquery/jquery-mobile/issues/4784
- //
- // NOTE this option is modified in _create!
- history: !$.mobile.browser.oldIE
- },
-
- // When the user depresses the mouse/finger on an element inside the popup while the popup is
- // open, we ignore resize events for a short while. This prevents #6961.
- _handleDocumentVmousedown: function (theEvent) {
- if (this._isOpen && $.contains(this._ui.container[0], theEvent.target)) {
- this._ignoreResizeEvents();
- }
- },
-
- _create: function () {
- var theElement = this.element,
- myId = theElement.attr("id"),
- currentOptions = this.options;
-
- // We need to adjust the history option to be false if there's no AJAX nav.
- // We can't do it in the option declarations because those are run before
- // it is determined whether there shall be AJAX nav.
- currentOptions.history = currentOptions.history && $.mobile.ajaxEnabled && $.mobile.hashListeningEnabled;
-
- this._on(this.document, {
- "mousedown": "_handleDocumentVmousedown"
- });
-
- // Define instance variables
- $.extend(this, {
- _scrollTop: 0,
- _page: theElement.closest(".ui-page"),
- _ui: null,
- _fallbackTransition: "",
- _currentTransition: false,
- _prerequisites: null,
- _isOpen: false,
- _tolerance: null,
- _resizeData: null,
- _ignoreResizeTo: 0,
- _orientationchangeInProgress: false
- });
-
- if (this._page.length === 0) {
- this._page = $("body");
- }
-
- if (currentOptions.enhanced) {
- this._ui = {
- container: theElement.parent(),
- screen: theElement.parent().prev(),
- placeholder: $(this.document[0].getElementById(myId + "-placeholder"))
- };
- } else {
- this._ui = this._enhance(theElement, myId);
- this._applyTransition(currentOptions.transition);
- }
- this
- ._setTolerance(currentOptions.tolerance)
- ._ui.focusElement = this._ui.container;
-
- // Event handlers
- this._on(this._ui.screen, { "click": "_eatEventAndClose" });
- this._on(this.window, {
- orientationchange: $.proxy(this, "_handleWindowOrientationchange"),
- resize: $.proxy(this, "_handleWindowResize")
- });
- this._on(this.document, { "focusin": "_handleDocumentFocusIn" });
- },
-
- _delay: function (handler, delay) {
- function handlerProxy() {
- return (typeof handler === "string" ? instance[handler] : handler)
- .apply(instance, arguments);
- }
- var instance = this;
- return setTimeout(handlerProxy, delay || 0);
- },
-
- _enhance: function (theElement, myId) {
- var currentOptions = this.options,
- wrapperClass = currentOptions.wrapperClass,
- ui = {
- screen: $(""),
- placeholder: $("
"),
- container: $("")
- },
- fragment = this.document[0].createDocumentFragment();
-
- fragment.appendChild(ui.screen[0]);
- fragment.appendChild(ui.container[0]);
-
- if (myId) {
- ui.screen.attr("id", myId + "-screen");
- ui.container.attr("id", myId + "-popup");
- ui.placeholder
- .attr("id", myId + "-placeholder")
- .html("");
- }
-
- // Apply the proto
- this._page[0].appendChild(fragment);
- // Leave a placeholder where the element used to be
- ui.placeholder.insertAfter(theElement);
- theElement
- .detach()
- .addClass("ui-popup " +
- this._themeClassFromOption("ui-body-", currentOptions.theme) + " " +
- (currentOptions.shadow ? "ui-overlay-shadow " : "") +
- (currentOptions.corners ? "ui-corner-all " : ""))
- .appendTo(ui.container);
-
- return ui;
- },
-
- _eatEventAndClose: function (theEvent) {
- theEvent.preventDefault();
- theEvent.stopImmediatePropagation();
- if (this.options.dismissible) {
- this.close();
- }
- return false;
- },
-
- // Make sure the screen covers the entire document - CSS is sometimes not
- // enough to accomplish this.
- _resizeScreen: function () {
- var screen = this._ui.screen,
- popupHeight = this._ui.container.outerHeight(true),
- screenHeight = screen.removeAttr("style").height(),
-
- // Subtracting 1 here is necessary for an obscure Andrdoid 4.0 bug where
- // the browser hangs if the screen covers the entire document :/
- documentHeight = this.document.height() - 1;
-
- if (screenHeight < documentHeight) {
- screen.height(documentHeight);
- } else if (popupHeight > screenHeight) {
- screen.height(popupHeight);
- }
- },
-
- _expectResizeEvent: function () {
- var windowCoordinates = getWindowCoordinates(this.window);
-
- if (this._resizeData) {
- if (windowCoordinates.x === this._resizeData.windowCoordinates.x &&
- windowCoordinates.y === this._resizeData.windowCoordinates.y &&
- windowCoordinates.cx === this._resizeData.windowCoordinates.cx &&
- windowCoordinates.cy === this._resizeData.windowCoordinates.cy) {
- // timeout not refreshed
- return false;
- } else {
- // clear existing timeout - it will be refreshed below
- clearTimeout(this._resizeData.timeoutId);
- }
- }
-
- this._resizeData = {
- timeoutId: this._delay("_resizeTimeout", 200),
- windowCoordinates: windowCoordinates
- };
-
- return true;
- },
-
- _resizeTimeout: function () {
- if (this._isOpen) {
- if (!this._expectResizeEvent()) {
- if (this._ui.container.hasClass("ui-popup-hidden")) {
- // effectively rapid-open the popup while leaving the screen intact
- this._ui.container.removeClass("ui-popup-hidden ui-popup-truncate");
- this.reposition({ positionTo: "window" });
- this._ignoreResizeEvents();
- }
-
- this._resizeScreen();
- this._resizeData = null;
- this._orientationchangeInProgress = false;
- }
- } else {
- this._resizeData = null;
- this._orientationchangeInProgress = false;
- }
- },
-
- _stopIgnoringResizeEvents: function () {
- this._ignoreResizeTo = 0;
- },
-
- _ignoreResizeEvents: function () {
- if (this._ignoreResizeTo) {
- clearTimeout(this._ignoreResizeTo);
- }
- this._ignoreResizeTo = this._delay("_stopIgnoringResizeEvents", 1000);
- },
-
- _handleWindowResize: function (/* theEvent */) {
- if (this._isOpen && this._ignoreResizeTo === 0) {
- if ((this._expectResizeEvent() || this._orientationchangeInProgress) &&
- !this._ui.container.hasClass("ui-popup-hidden")) {
- // effectively rapid-close the popup while leaving the screen intact
- this._ui.container
- .addClass("ui-popup-hidden ui-popup-truncate")
- .removeAttr("style");
- }
- }
- },
-
- _handleWindowOrientationchange: function (/* theEvent */) {
- if (!this._orientationchangeInProgress && this._isOpen && this._ignoreResizeTo === 0) {
- this._expectResizeEvent();
- this._orientationchangeInProgress = true;
- }
- },
-
- // When the popup is open, attempting to focus on an element that is not a
- // child of the popup will redirect focus to the popup
- _handleDocumentFocusIn: function (theEvent) {
- var target,
- targetElement = theEvent.target,
- ui = this._ui;
-
- if (!this._isOpen) {
- return;
- }
-
- if (targetElement !== ui.container[0]) {
- target = $(targetElement);
- if (!$.contains(ui.container[0], targetElement)) {
- $(this.document[0].activeElement).one("focus", $.proxy(function () {
- this._safelyBlur(targetElement);
- }, this));
- ui.focusElement.focus();
- theEvent.preventDefault();
- theEvent.stopImmediatePropagation();
- return false;
- } else if (ui.focusElement[0] === ui.container[0]) {
- ui.focusElement = target;
- }
- }
-
- this._ignoreResizeEvents();
- },
-
- _themeClassFromOption: function (prefix, value) {
- return (value ? (value === "none" ? "" : (prefix + value)) : (prefix + "inherit"));
- },
-
- _applyTransition: function (value) {
- if (value) {
- this._ui.container.removeClass(this._fallbackTransition);
- if (value !== "none") {
- this._fallbackTransition = $.mobile._maybeDegradeTransition(value);
- if (this._fallbackTransition === "none") {
- this._fallbackTransition = "";
- }
- this._ui.container.addClass(this._fallbackTransition);
- }
- }
-
- return this;
- },
-
- _setOptions: function (newOptions) {
- var currentOptions = this.options,
- theElement = this.element,
- screen = this._ui.screen;
-
- if (newOptions.wrapperClass !== undefined) {
- this._ui.container
- .removeClass(currentOptions.wrapperClass)
- .addClass(newOptions.wrapperClass);
- }
-
- if (newOptions.theme !== undefined) {
- theElement
- .removeClass(this._themeClassFromOption("ui-body-", currentOptions.theme))
- .addClass(this._themeClassFromOption("ui-body-", newOptions.theme));
- }
-
- if (newOptions.overlayTheme !== undefined) {
- screen
- .removeClass(this._themeClassFromOption("ui-overlay-", currentOptions.overlayTheme))
- .addClass(this._themeClassFromOption("ui-overlay-", newOptions.overlayTheme));
-
- if (this._isOpen) {
- screen.addClass("in");
- }
- }
-
- if (newOptions.shadow !== undefined) {
- theElement.toggleClass("ui-overlay-shadow", newOptions.shadow);
- }
-
- if (newOptions.corners !== undefined) {
- theElement.toggleClass("ui-corner-all", newOptions.corners);
- }
-
- if (newOptions.transition !== undefined) {
- if (!this._currentTransition) {
- this._applyTransition(newOptions.transition);
- }
- }
-
- if (newOptions.tolerance !== undefined) {
- this._setTolerance(newOptions.tolerance);
- }
-
- if (newOptions.disabled !== undefined) {
- if (newOptions.disabled) {
- this.close();
- }
- }
-
- return this._super(newOptions);
- },
-
- _setTolerance: function (value) {
- var tol = { t: 30, r: 15, b: 30, l: 15 },
- ar;
-
- if (value !== undefined) {
- ar = String(value).split(",");
-
- $.each(ar, function (idx, val) { ar[idx] = parseInt(val, 10); });
-
- switch (ar.length) {
- // All values are to be the same
- case 1:
- if (!isNaN(ar[0])) {
- tol.t = tol.r = tol.b = tol.l = ar[0];
- }
- break;
-
- // The first value denotes top/bottom tolerance, and the second value denotes left/right tolerance
- case 2:
- if (!isNaN(ar[0])) {
- tol.t = tol.b = ar[0];
- }
- if (!isNaN(ar[1])) {
- tol.l = tol.r = ar[1];
- }
- break;
-
- // The array contains values in the order top, right, bottom, left
- case 4:
- if (!isNaN(ar[0])) {
- tol.t = ar[0];
- }
- if (!isNaN(ar[1])) {
- tol.r = ar[1];
- }
- if (!isNaN(ar[2])) {
- tol.b = ar[2];
- }
- if (!isNaN(ar[3])) {
- tol.l = ar[3];
- }
- break;
-
- default:
- break;
- }
- }
-
- this._tolerance = tol;
- return this;
- },
-
- _clampPopupWidth: function (infoOnly) {
- var menuSize,
- windowCoordinates = getWindowCoordinates(this.window),
- // rectangle within which the popup must fit
- rectangle = {
- x: this._tolerance.l,
- y: windowCoordinates.y + this._tolerance.t,
- cx: windowCoordinates.cx - this._tolerance.l - this._tolerance.r,
- cy: windowCoordinates.cy - this._tolerance.t - this._tolerance.b
- };
-
- if (!infoOnly) {
- // Clamp the width of the menu before grabbing its size
- this._ui.container.css("max-width", rectangle.cx);
- }
-
- menuSize = {
- cx: this._ui.container.outerWidth(true),
- cy: this._ui.container.outerHeight(true)
- };
-
- return { rc: rectangle, menuSize: menuSize };
- },
-
- _calculateFinalLocation: function (desired, clampInfo) {
- var returnValue,
- rectangle = clampInfo.rc,
- menuSize = clampInfo.menuSize;
-
- // Center the menu over the desired coordinates, while not going outside
- // the window tolerances. This will center wrt. the window if the popup is
- // too large.
- returnValue = {
- left: fitSegmentInsideSegment(rectangle.cx, menuSize.cx, rectangle.x, desired.x),
- top: fitSegmentInsideSegment(rectangle.cy, menuSize.cy, rectangle.y, desired.y)
- };
-
- // Make sure the top of the menu is visible
- returnValue.top = Math.max(0, returnValue.top);
-
- // If the height of the menu is smaller than the height of the document
- // align the bottom with the bottom of the document
-
- returnValue.top -= Math.min(returnValue.top,
- Math.max(0, returnValue.top + menuSize.cy - this.document.height()));
-
- return returnValue;
- },
-
- // Try and center the overlay over the given coordinates
- _placementCoords: function (desired) {
- return this._calculateFinalLocation(desired, this._clampPopupWidth());
- },
-
- _createPrerequisites: function (screenPrerequisite, containerPrerequisite, whenDone) {
- var prerequisites,
- self = this;
-
- // It is important to maintain both the local variable prerequisites and
- // self._prerequisites. The local variable remains in the closure of the
- // functions which call the callbacks passed in. The comparison between the
- // local variable and self._prerequisites is necessary, because once a
- // function has been passed to .animationComplete() it will be called next
- // time an animation completes, even if that's not the animation whose end
- // the function was supposed to catch (for example, if an abort happens
- // during the opening animation, the .animationComplete handler is not
- // called for that animation anymore, but the handler remains attached, so
- // it is called the next time the popup is opened - making it stale.
- // Comparing the local variable prerequisites to the widget-level variable
- // self._prerequisites ensures that callbacks triggered by a stale
- // .animationComplete will be ignored.
-
- prerequisites = {
- screen: $.Deferred(),
- container: $.Deferred()
- };
-
- prerequisites.screen.then(function () {
- if (prerequisites === self._prerequisites) {
- screenPrerequisite();
- }
- });
-
- prerequisites.container.then(function () {
- if (prerequisites === self._prerequisites) {
- containerPrerequisite();
- }
- });
-
- Promise.all([prerequisites.screen, prerequisites.container]).then(function () {
- if (prerequisites === self._prerequisites) {
- self._prerequisites = null;
- whenDone();
- }
- });
-
- self._prerequisites = prerequisites;
- },
-
- _animate: function (args) {
- // NOTE before removing the default animation of the screen
- // this had an animate callback that would resolve the deferred
- // now the deferred is resolved immediately
- // TODO remove the dependency on the screen deferred
- this._ui.screen
- .removeClass(args.classToRemove)
- .addClass(args.screenClassToAdd);
-
- args.prerequisites.screen.resolve();
-
- if (args.transition && args.transition !== "none") {
- if (args.applyTransition) {
- this._applyTransition(args.transition);
- }
- if (this._fallbackTransition) {
- this._ui.container
- .addClass(args.containerClassToAdd)
- .removeClass(args.classToRemove)
- .animationComplete($.proxy(args.prerequisites.container, "resolve"));
- return;
- }
- }
- this._ui.container.removeClass(args.classToRemove);
- args.prerequisites.container.resolve();
- },
-
- // The desired coordinates passed in will be returned untouched if no reference element can be identified via
- // desiredPosition.positionTo. Nevertheless, this function ensures that its return value always contains valid
- // x and y coordinates by specifying the center middle of the window if the coordinates are absent.
- // options: { x: coordinate, y: coordinate, positionTo: string: "origin", "window", or jQuery selector
- _desiredCoords: function (openOptions) {
- var offset,
- dst = null,
- windowCoordinates = getWindowCoordinates(this.window),
- x = openOptions.x,
- y = openOptions.y,
- pTo = openOptions.positionTo;
-
- // Establish which element will serve as the reference
- if (pTo && pTo !== "origin") {
- if (pTo === "window") {
- x = windowCoordinates.cx / 2 + windowCoordinates.x;
- y = windowCoordinates.cy / 2 + windowCoordinates.y;
- } else {
- try {
- dst = $(pTo);
- } catch (err) {
- dst = null;
- }
- if (dst) {
- dst.filter(":visible");
- if (dst.length === 0) {
- dst = null;
- }
- }
- }
- }
-
- // If an element was found, center over it
- if (dst) {
- offset = dst.offset();
- x = offset.left + dst.outerWidth() / 2;
- y = offset.top + dst.outerHeight() / 2;
- }
-
- // Make sure x and y are valid numbers - center over the window
- if ($.type(x) !== "number" || isNaN(x)) {
- x = windowCoordinates.cx / 2 + windowCoordinates.x;
- }
- if ($.type(y) !== "number" || isNaN(y)) {
- y = windowCoordinates.cy / 2 + windowCoordinates.y;
- }
-
- return { x: x, y: y };
- },
-
- _reposition: function (openOptions) {
- // We only care about position-related parameters for repositioning
- openOptions = {
- x: openOptions.x,
- y: openOptions.y,
- positionTo: openOptions.positionTo
- };
- this._trigger("beforeposition", undefined, openOptions);
- this._ui.container.offset(this._placementCoords(this._desiredCoords(openOptions)));
- },
-
- reposition: function (openOptions) {
- if (this._isOpen) {
- this._reposition(openOptions);
- }
- },
-
- _safelyBlur: function (currentElement) {
- if (currentElement !== this.window[0] &&
- currentElement.nodeName.toLowerCase() !== "body") {
- $(currentElement).blur();
- }
- },
-
- _openPrerequisitesComplete: function () {
- var id = this.element.attr("id");
-
- this._ui.container.addClass("ui-popup-active");
- this._isOpen = true;
- this._resizeScreen();
-
- // Check to see if currElement is not a child of the container. If it's not, blur
- if (!$.contains(this._ui.container[0], this.document[0].activeElement)) {
- this._safelyBlur(this.document[0].activeElement);
- }
- this._ignoreResizeEvents();
- if (id) {
- this.document.find("[aria-haspopup='true'][aria-owns='" + id + "']").attr("aria-expanded", true);
- }
- this._trigger("afteropen");
- },
-
- _open: function (options) {
- var openOptions = $.extend({}, this.options, options),
- // TODO move blacklist to private method
- androidBlacklist = (function () {
- var ua = navigator.userAgent,
- // Rendering engine is Webkit, and capture major version
- wkmatch = ua.match(/AppleWebKit\/([0-9\.]+)/),
- wkversion = !!wkmatch && wkmatch[1],
- androidmatch = ua.match(/Android (\d+(?:\.\d+))/),
- andversion = !!androidmatch && androidmatch[1],
- chromematch = ua.indexOf("Chrome") > -1;
-
- // Platform is Android, WebKit version is greater than 534.13 ( Android 3.2.1 ) and not Chrome.
- if (androidmatch !== null && andversion === "4.0" && wkversion && wkversion > 534.13 && !chromematch) {
- return true;
- }
- return false;
- }());
-
- // Count down to triggering "popupafteropen" - we have two prerequisites:
- // 1. The popup window animation completes (container())
- // 2. The screen opacity animation completes (screen())
- this._createPrerequisites(
- $.noop,
- $.noop,
- $.proxy(this, "_openPrerequisitesComplete"));
-
- this._currentTransition = openOptions.transition;
- this._applyTransition(openOptions.transition);
-
- this._ui.screen.removeClass("ui-screen-hidden");
- this._ui.container.removeClass("ui-popup-truncate");
-
- // Give applications a chance to modify the contents of the container before it appears
- this._reposition(openOptions);
-
- this._ui.container.removeClass("ui-popup-hidden");
-
- if (this.options.overlayTheme && androidBlacklist) {
- /* TODO: The native browser on Android 4.0.X ("Ice Cream Sandwich") suffers from an issue where the popup overlay appears to be z-indexed above the popup itself when certain other styles exist on the same page -- namely, any element set to `position: fixed` and certain types of input. These issues are reminiscent of previously uncovered bugs in older versions of Android's native browser: https://github.com/scottjehl/Device-Bugs/issues/3
- This fix closes the following bugs ( I use "closes" with reluctance, and stress that this issue should be revisited as soon as possible ):
- https://github.com/jquery/jquery-mobile/issues/4816
- https://github.com/jquery/jquery-mobile/issues/4844
- https://github.com/jquery/jquery-mobile/issues/4874
- */
-
- // TODO sort out why this._page isn't working
- this.element.closest(".ui-page").addClass("ui-popup-open");
- }
- this._animate({
- additionalCondition: true,
- transition: openOptions.transition,
- classToRemove: "",
- screenClassToAdd: "in",
- containerClassToAdd: "in",
- applyTransition: false,
- prerequisites: this._prerequisites
- });
- },
-
- _closePrerequisiteScreen: function () {
- this._ui.screen
- .removeClass("out")
- .addClass("ui-screen-hidden");
- },
-
- _closePrerequisiteContainer: function () {
- this._ui.container
- .removeClass("reverse out")
- .addClass("ui-popup-hidden ui-popup-truncate")
- .removeAttr("style");
- },
-
- _closePrerequisitesDone: function () {
- var container = this._ui.container,
- id = this.element.attr("id");
-
- // remove the global mutex for popups
- $.mobile.popup.active = undefined;
-
- // Blur elements inside the container, including the container
- $(":focus", container[0]).add(container[0]).blur();
-
- if (id) {
- this.document.find("[aria-haspopup='true'][aria-owns='" + id + "']").attr("aria-expanded", false);
- }
-
- // alert users that the popup is closed
- this._trigger("afterclose");
- },
-
- _close: function (immediate) {
- this._ui.container.removeClass("ui-popup-active");
- this._page.removeClass("ui-popup-open");
-
- this._isOpen = false;
-
- // Count down to triggering "popupafterclose" - we have two prerequisites:
- // 1. The popup window reverse animation completes (container())
- // 2. The screen opacity animation completes (screen())
- this._createPrerequisites(
- $.proxy(this, "_closePrerequisiteScreen"),
- $.proxy(this, "_closePrerequisiteContainer"),
- $.proxy(this, "_closePrerequisitesDone"));
-
- this._animate({
- additionalCondition: this._ui.screen.hasClass("in"),
- transition: (immediate ? "none" : (this._currentTransition)),
- classToRemove: "in",
- screenClassToAdd: "out",
- containerClassToAdd: "reverse out",
- applyTransition: true,
- prerequisites: this._prerequisites
- });
- },
-
- _unenhance: function () {
- if (this.options.enhanced) {
- return;
- }
-
- // Put the element back to where the placeholder was and remove the "ui-popup" class
- this._setOptions({ theme: $.mobile.popup.prototype.options.theme });
- this.element
- // Cannot directly insertAfter() - we need to detach() first, because
- // insertAfter() will do nothing if the payload div was not attached
- // to the DOM at the time the widget was created, and so the payload
- // will remain inside the container even after we call insertAfter().
- // If that happens and we remove the container a few lines below, we
- // will cause an infinite recursion - #5244
- .detach()
- .insertAfter(this._ui.placeholder)
- .removeClass("ui-popup ui-overlay-shadow ui-corner-all ui-body-inherit");
- this._ui.screen.remove();
- this._ui.container.remove();
- this._ui.placeholder.remove();
- },
-
- _destroy: function () {
- if ($.mobile.popup.active === this) {
- this.element.one("popupafterclose", $.proxy(this, "_unenhance"));
- this.close();
- } else {
- this._unenhance();
- }
-
- return this;
- },
-
- _closePopup: function (theEvent, data) {
- var parsedDst, toUrl,
- currentOptions = this.options,
- immediate = false;
-
- if ((theEvent && theEvent.isDefaultPrevented()) || $.mobile.popup.active !== this) {
- return;
- }
-
- // restore location on screen
- window.scrollTo(0, this._scrollTop);
-
- if (theEvent && theEvent.type === "pagebeforechange" && data) {
- // Determine whether we need to rapid-close the popup, or whether we can
- // take the time to run the closing transition
- if (typeof data.toPage === "string") {
- parsedDst = data.toPage;
- } else {
- parsedDst = data.toPage.data("url");
- }
- parsedDst = $.mobile.path.parseUrl(parsedDst);
- toUrl = parsedDst.pathname + parsedDst.search + parsedDst.hash;
-
- if (this._myUrl !== $.mobile.path.makeUrlAbsolute(toUrl)) {
- // Going to a different page - close immediately
- immediate = true;
- } else {
- theEvent.preventDefault();
- }
- }
-
- // remove nav bindings
- this.window.off(currentOptions.closeEvents);
- // unbind click handlers added when history is disabled
- this.element.undelegate(currentOptions.closeLinkSelector, currentOptions.closeLinkEvents);
-
- this._close(immediate);
- },
-
- // any navigation event after a popup is opened should close the popup
- // NOTE the pagebeforechange is bound to catch navigation events that don't
- // alter the url (eg, dialogs from popups)
- _bindContainerClose: function () {
- this.window
- .on(this.options.closeEvents, $.proxy(this, "_closePopup"));
- },
-
- widget: function () {
- return this._ui.container;
- },
-
- // TODO no clear deliniation of what should be here and
- // what should be in _open. Seems to be "visual" vs "history" for now
- open: function (options) {
- var url, hashkey, activePage, currentIsDialog, hasHash, urlHistory,
- self = this,
- currentOptions = this.options;
-
- // make sure open is idempotent
- if ($.mobile.popup.active || currentOptions.disabled) {
- return this;
- }
-
- // set the global popup mutex
- $.mobile.popup.active = this;
- this._scrollTop = this.window.scrollTop();
-
- // if history alteration is disabled close on navigate events
- // and leave the url as is
- if (!(currentOptions.history)) {
- self._open(options);
- self._bindContainerClose();
-
- // When histoy is disabled we have to grab the data-rel
- // back link clicks so we can close the popup instead of
- // relying on history to do it for us
- self.element
- .delegate(currentOptions.closeLinkSelector, currentOptions.closeLinkEvents, function (theEvent) {
- self.close();
- theEvent.preventDefault();
- });
-
- return this;
- }
-
- // cache some values for min/readability
- urlHistory = $.mobile.navigate.history;
- hashkey = $.mobile.dialogHashKey;
- activePage = $.mobile.activePage;
- currentIsDialog = (activePage ? activePage.hasClass("ui-dialog") : false);
- this._myUrl = url = urlHistory.getActive().url;
- hasHash = (url.indexOf(hashkey) > -1) && !currentIsDialog && (urlHistory.activeIndex > 0);
-
- if (hasHash) {
- self._open(options);
- self._bindContainerClose();
- return this;
- }
-
- // if the current url has no dialog hash key proceed as normal
- // otherwise, if the page is a dialog simply tack on the hash key
- if (url.indexOf(hashkey) === -1 && !currentIsDialog) {
- url = url + (url.indexOf("#") > -1 ? hashkey : "#" + hashkey);
- } else {
- url = $.mobile.path.parseLocation().hash + hashkey;
- }
-
- // swallow the the initial navigation event, and bind for the next
- this.window.one("beforenavigate", function (theEvent) {
- theEvent.preventDefault();
- self._open(options);
- self._bindContainerClose();
- });
-
- this.urlAltered = true;
- $.mobile.navigate(url, { role: "dialog" });
-
- return this;
- },
-
- close: function () {
- // make sure close is idempotent
- if ($.mobile.popup.active !== this) {
- return this;
- }
-
- this._scrollTop = this.window.scrollTop();
-
- if (this.options.history && this.urlAltered) {
- $.mobile.pageContainer.pagecontainer("back");
- this.urlAltered = false;
- } else {
- // simulate the nav bindings having fired
- this._closePopup();
- }
-
- return this;
- }
- });
-
- // TODO this can be moved inside the widget
- $.mobile.popup.handleLink = function ($link) {
- var offset,
- path = $.mobile.path,
-
- // NOTE make sure to get only the hash from the href because ie7 (wp7)
- // returns the absolute href in this case ruining the element selection
- popup = $(path.hashToSelector(path.parseUrl($link.attr("href")).hash)).first();
-
- if (popup.length > 0 && popup.data("mobile-popup")) {
- offset = $link.offset();
- popup.popup("open", {
- x: offset.left + $link.outerWidth() / 2,
- y: offset.top + $link.outerHeight() / 2,
- transition: $link.data("transition"),
- positionTo: $link.data("position-to")
- });
- }
-
- //remove after delay
- setTimeout(function () {
- $link.removeClass($.mobile.activeBtnClass);
- }, 300);
- };
-
- // TODO move inside _create
- $(document).on("pagebeforechange", function (theEvent, data) {
- if (data.options.role === "popup") {
- $.mobile.popup.handleLink(data.options.link);
- theEvent.preventDefault();
- }
- });
-
-})(jQuery);
-
-
-(function ($, undefined) {
-
- var ieHack = ($.mobile.browser.oldIE && $.mobile.browser.oldIE <= 8),
- uiTemplate = $(
- "" +
- ""
- );
-
- function getArrow() {
- var clone = uiTemplate.clone(),
- gd = clone.eq(0),
- ct = clone.eq(1),
- ar = ct.children();
-
- return { arEls: ct.add(gd), gd: gd, ct: ct, ar: ar };
- }
-
- $.widget("mobile.popup", $.mobile.popup, {
- options: {
-
- arrow: ""
- },
-
- _create: function () {
- var ar,
- ret = this._super();
-
- if (this.options.arrow) {
- this._ui.arrow = ar = this._addArrow();
- }
-
- return ret;
- },
-
- _addArrow: function () {
- var theme,
- opts = this.options,
- ar = getArrow();
-
- theme = this._themeClassFromOption("ui-body-", opts.theme);
- ar.ar.addClass(theme + (opts.shadow ? " ui-overlay-shadow" : ""));
- ar.arEls.hide().appendTo(this.element);
-
- return ar;
- },
-
- _unenhance: function () {
- var ar = this._ui.arrow;
-
- if (ar) {
- ar.arEls.remove();
- }
-
- return this._super();
- },
-
- // Pretend to show an arrow described by @p and @dir and calculate the
- // distance from the desired point. If a best-distance is passed in, return
- // the minimum of the one passed in and the one calculated.
- _tryAnArrow: function (p, dir, desired, s, best) {
- var result, r, diff, desiredForArrow = {}, tip = {};
-
- // If the arrow has no wiggle room along the edge of the popup, it cannot
- // be displayed along the requested edge without it sticking out.
- if (s.arFull[p.dimKey] > s.guideDims[p.dimKey]) {
- return best;
- }
-
- desiredForArrow[p.fst] = desired[p.fst] +
- (s.arHalf[p.oDimKey] + s.menuHalf[p.oDimKey]) * p.offsetFactor -
- s.contentBox[p.fst] + (s.clampInfo.menuSize[p.oDimKey] - s.contentBox[p.oDimKey]) * p.arrowOffsetFactor;
- desiredForArrow[p.snd] = desired[p.snd];
-
- result = s.result || this._calculateFinalLocation(desiredForArrow, s.clampInfo);
- r = { x: result.left, y: result.top };
-
- tip[p.fst] = r[p.fst] + s.contentBox[p.fst] + p.tipOffset;
- tip[p.snd] = Math.max(result[p.prop] + s.guideOffset[p.prop] + s.arHalf[p.dimKey],
- Math.min(result[p.prop] + s.guideOffset[p.prop] + s.guideDims[p.dimKey] - s.arHalf[p.dimKey],
- desired[p.snd]));
-
- diff = Math.abs(desired.x - tip.x) + Math.abs(desired.y - tip.y);
- if (!best || diff < best.diff) {
- // Convert tip offset to coordinates inside the popup
- tip[p.snd] -= s.arHalf[p.dimKey] + result[p.prop] + s.contentBox[p.snd];
- best = { dir: dir, diff: diff, result: result, posProp: p.prop, posVal: tip[p.snd] };
- }
-
- return best;
- },
-
- _getPlacementState: function (clamp) {
- var offset, gdOffset,
- ar = this._ui.arrow,
- state = {
- clampInfo: this._clampPopupWidth(!clamp),
- arFull: { cx: ar.ct.width(), cy: ar.ct.height() },
- guideDims: { cx: ar.gd.width(), cy: ar.gd.height() },
- guideOffset: ar.gd.offset()
- };
-
- offset = this.element.offset();
-
- ar.gd.css({ left: 0, top: 0, right: 0, bottom: 0 });
- gdOffset = ar.gd.offset();
- state.contentBox = {
- x: gdOffset.left - offset.left,
- y: gdOffset.top - offset.top,
- cx: ar.gd.width(),
- cy: ar.gd.height()
- };
- ar.gd.removeAttr("style");
-
- // The arrow box moves between guideOffset and guideOffset + guideDims - arFull
- state.guideOffset = { left: state.guideOffset.left - offset.left, top: state.guideOffset.top - offset.top };
- state.arHalf = { cx: state.arFull.cx / 2, cy: state.arFull.cy / 2 };
- state.menuHalf = { cx: state.clampInfo.menuSize.cx / 2, cy: state.clampInfo.menuSize.cy / 2 };
-
- return state;
- },
-
- _placementCoords: function (desired) {
- var state, best, params, elOffset, bgRef,
- optionValue = this.options.arrow,
- ar = this._ui.arrow;
-
- if (!ar) {
- return this._super(desired);
- }
-
- ar.arEls.show();
-
- bgRef = {};
- state = this._getPlacementState(true);
- params = {
- "l": { fst: "x", snd: "y", prop: "top", dimKey: "cy", oDimKey: "cx", offsetFactor: 1, tipOffset: -state.arHalf.cx, arrowOffsetFactor: 0 },
- "r": { fst: "x", snd: "y", prop: "top", dimKey: "cy", oDimKey: "cx", offsetFactor: -1, tipOffset: state.arHalf.cx + state.contentBox.cx, arrowOffsetFactor: 1 },
- "b": { fst: "y", snd: "x", prop: "left", dimKey: "cx", oDimKey: "cy", offsetFactor: -1, tipOffset: state.arHalf.cy + state.contentBox.cy, arrowOffsetFactor: 1 },
- "t": { fst: "y", snd: "x", prop: "left", dimKey: "cx", oDimKey: "cy", offsetFactor: 1, tipOffset: -state.arHalf.cy, arrowOffsetFactor: 0 }
- };
-
- // Try each side specified in the options to see on which one the arrow
- // should be placed such that the distance between the tip of the arrow and
- // the desired coordinates is the shortest.
- $.each((optionValue === true ? "l,t,r,b" : optionValue).split(","),
- $.proxy(function (key, value) {
- best = this._tryAnArrow(params[value], value, desired, state, best);
- }, this));
-
- // Could not place the arrow along any of the edges - behave as if showing
- // the arrow was turned off.
- if (!best) {
- ar.arEls.hide();
- return this._super(desired);
- }
-
- // Move the arrow into place
- ar.ct
- .removeClass("ui-popup-arrow-l ui-popup-arrow-t ui-popup-arrow-r ui-popup-arrow-b")
- .addClass("ui-popup-arrow-" + best.dir)
- .removeAttr("style").css(best.posProp, best.posVal)
- .show();
-
- // Do not move/size the background div on IE, because we use the arrow div for background as well.
- if (!ieHack) {
- elOffset = this.element.offset();
- bgRef[params[best.dir].fst] = ar.ct.offset();
- bgRef[params[best.dir].snd] = {
- left: elOffset.left + state.contentBox.x,
- top: elOffset.top + state.contentBox.y
- };
- }
-
- return best.result;
- },
-
- _setOptions: function (opts) {
- var newTheme,
- oldTheme = this.options.theme,
- ar = this._ui.arrow,
- ret = this._super(opts);
-
- if (opts.arrow !== undefined) {
- if (!ar && opts.arrow) {
- this._ui.arrow = this._addArrow();
-
- // Important to return here so we don't set the same options all over
- // again below.
- return;
- } else if (ar && !opts.arrow) {
- ar.arEls.remove();
- this._ui.arrow = null;
- }
- }
-
- // Reassign with potentially new arrow
- ar = this._ui.arrow;
-
- if (ar) {
- if (opts.theme !== undefined) {
- oldTheme = this._themeClassFromOption("ui-body-", oldTheme);
- newTheme = this._themeClassFromOption("ui-body-", opts.theme);
- ar.ar.removeClass(oldTheme).addClass(newTheme);
- }
-
- if (opts.shadow !== undefined) {
- ar.ar.toggleClass("ui-overlay-shadow", opts.shadow);
- }
- }
-
- return ret;
- },
-
- _destroy: function () {
- var ar = this._ui.arrow;
-
- if (ar) {
- ar.arEls.remove();
- }
-
- return this._super();
- }
- });
-
-})(jQuery);
\ No newline at end of file
+ })(jQuery);
+});
\ No newline at end of file
diff --git a/dashboard-ui/thirdparty/jquerymobile-1.4.5/jqm.widget.js b/dashboard-ui/thirdparty/jquerymobile-1.4.5/jqm.widget.js
new file mode 100644
index 0000000000..83864e58ea
--- /dev/null
+++ b/dashboard-ui/thirdparty/jquerymobile-1.4.5/jqm.widget.js
@@ -0,0 +1,523 @@
+(function () {
+
+ if (jQuery.widget) {
+ return;
+ }
+
+ /*!
+ * jQuery UI Widget c0ab71056b936627e8a7821f03c044aec6280a40
+ * http://jqueryui.com
+ *
+ * Copyright 2013 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/jQuery.widget/
+ */
+ (function ($, undefined) {
+
+ var uuid = 0,
+ slice = Array.prototype.slice,
+ _cleanData = $.cleanData;
+ $.cleanData = function (elems) {
+ for (var i = 0, elem; (elem = elems[i]) != null; i++) {
+ try {
+ $(elem).triggerHandler("remove");
+ // http://bugs.jquery.com/ticket/8235
+ } catch (e) { }
+ }
+ _cleanData(elems);
+ };
+
+ $.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 = 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 = slice.call(arguments, 1),
+ returnValue = this;
+
+ // allow multiple hashes to be passed on init
+ options = !isMethodCall && args.length ?
+ $.widget.extend.apply(null, [options].concat(args)) :
+ options;
+
+ 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 {
+ this.each(function () {
+ var instance = $.data(this, fullName);
+ if (instance) {
+ instance.option(options || {})._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 = uuid++;
+ this.eventNamespace = "." + this.widgetName + this.uuid;
+ this.options = $.widget.extend({},
+ this.options,
+ this._getCreateOptions(),
+ options);
+
+ 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._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 (value === undefined) {
+ return curOption[key] === undefined ? null : curOption[key];
+ }
+ curOption[key] = value;
+ } else {
+ if (value === undefined) {
+ 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);
+ 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 {
+ // accept selectors, DOM elements
+ 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);
+ },
+
+ _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[0].dispatchEvent(new CustomEvent(event.type, {
+ bubbles: true,
+ detail: {
+ data: data,
+ originalEvent: event
+ }
+ }));
+
+ //this.element.trigger(event, data);
+ return !($.isFunction(callback) &&
+ callback.apply(this.element[0], [event].concat(data)) === false ||
+ event.isDefaultPrevented());
+ }
+ };
+
+ })(jQuery);
+
+ (function ($, undefined) {
+
+ $.extend($.Widget.prototype, {
+ _getCreateOptions: function () {
+
+ var option, value,
+ elem = this.element[0],
+ options = {};
+
+ //
+ if (!this.element.data("defaults")) {
+ for (option in this.options) {
+
+ value = this.element.data(option);
+
+ if (value != null) {
+ options[option] = value;
+ }
+ }
+ }
+
+ return options;
+ }
+ });
+
+ })(jQuery);
+
+ (function ($, undefined) {
+
+
+ var originalWidget = $.widget
+
+ $.widget = (function (orig) {
+ return function () {
+ var constructor = orig.apply(this, arguments),
+ name = constructor.prototype.widgetName;
+
+ constructor.initSelector = ((constructor.prototype.initSelector !== undefined) ?
+ constructor.prototype.initSelector : "*[data-role='" + name + "']:not([data-role='none'])");
+
+ $.mobile.widgets[name] = constructor;
+
+ return constructor;
+ };
+ })($.widget);
+
+ // Make sure $.widget still has bridge and extend methods
+ $.extend($.widget, originalWidget);
+
+ })(jQuery);
+
+
+})();
\ No newline at end of file