jqmodal.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. /**
  2. * jqModal - Minimalist Modaling with jQuery
  3. * (http://dev.iceburg.net/jquery/jqmodal/)
  4. *
  5. * Copyright (c) 2007,2008 Brice Burgess <bhb@iceburg.net>
  6. * Dual licensed under the MIT and GPL licenses:
  7. * http://www.opensource.org/licenses/mit-license.php
  8. * http://www.gnu.org/licenses/gpl.html
  9. *
  10. * $Version: 07/06/2008 +r13
  11. * Changed by Oleg Kiriljuk, oleg.kiriljuk@ok-soft-gmbh.com
  12. * Copyright (c) 2014-2018, Oleg Kiriljuk, oleg.kiriljuk@ok-soft-gmbh.com
  13. */
  14. /*jslint browser: true, nomen: true, plusplus: true, white: true */
  15. /*global jQuery, define, exports, module, require */
  16. (function (global, factory) {
  17. "use strict";
  18. if (typeof define === "function" && define.amd) {
  19. // AMD. Register as an anonymous module.
  20. define([
  21. "jquery"
  22. ], function ($) {
  23. return factory($, global.document);
  24. });
  25. } else if (typeof module === "object" && module.exports) {
  26. // Node/CommonJS
  27. module.exports = function (root, $) {
  28. if (!root) {
  29. root = window;
  30. }
  31. if ($ === undefined) {
  32. // require("jquery") returns a factory that requires window to
  33. // build a jQuery instance, we normalize how we use modules
  34. // that require this pattern but the window provided is a noop
  35. // if it's defined (how jquery works)
  36. $ = typeof window !== "undefined" ?
  37. require("jquery") :
  38. require("jquery")(root);
  39. }
  40. factory($, root.document);
  41. return $;
  42. };
  43. } else {
  44. // Browser globals
  45. factory(jQuery, global.document);
  46. }
  47. }(typeof window !== "undefined" ? window : this, function ($, document) {
  48. "use strict";
  49. // begin module jqmodal
  50. var jqmHashLength = 0,
  51. jqmHash,
  52. createdModals = [],
  53. setFocusOnFirstVisibleInput = function (h) {
  54. try {
  55. $(":input:visible", h.w).first().focus();
  56. } catch (ignore) {}
  57. },
  58. setFocus = function (h) {
  59. setFocusOnFirstVisibleInput(h);
  60. },
  61. keyOrMouseEventHandler = function (e) {
  62. var activeModal = jqmHash[createdModals[createdModals.length - 1]],
  63. modal = !$(e.target).parents(".jqmID" + activeModal.s)[0],
  64. targetOffset = $(e.target).offset(),
  65. eX = e.pageX !== undefined ? e.pageX : targetOffset.left,
  66. eY = e.pageY !== undefined ? e.pageY : targetOffset.top,
  67. isEventInsideOfModal = function () {
  68. var isInside = false;
  69. $(".jqmID" + activeModal.s).each(function () {
  70. var $self = $(this), offset = $self.offset();
  71. // mouse event have e.pageX and e.pageY
  72. // keyboard event have e.type == "keydown" or "keypress",
  73. // e.pageX and e.pageY are undefined and one can use
  74. // $(e.target).offset()
  75. if (offset.top <= eY && eY <= offset.top + $self.height() &&
  76. offset.left <= eX && eX <= offset.left + $self.width()) {
  77. isInside = true;
  78. return false; // stop enumeration
  79. }
  80. });
  81. return isInside;
  82. };
  83. if (e.type !== "mousedown" && isEventInsideOfModal()) {
  84. // allows keyboard events inside of the modal
  85. return true;
  86. }
  87. if (e.type === "mousedown" && modal) {
  88. if (isEventInsideOfModal()) {
  89. modal = false;
  90. }
  91. if (modal && !$(e.target).is(":input")) {
  92. setFocusOnFirstVisibleInput(activeModal);
  93. }
  94. }
  95. return !modal;
  96. },
  97. bindOrUnbindEvents = function (bindOrUnbind) {
  98. // bindOrUnbind is either "bind" or "unbind" string
  99. $(document)[bindOrUnbind]("keypress keydown mousedown", keyOrMouseEventHandler);
  100. },
  101. registerHideOrShow = function (w, trigger, key) {
  102. return w.each(function () {
  103. var jqm = this._jqm;
  104. $(trigger).each(function () {
  105. if (!this[key]) {
  106. this[key] = [];
  107. $(this).click(function () {
  108. var i, method, propertyName, methods = ["jqmShow", "jqmHide"];
  109. for (i = 0; i < methods.length; i++) {
  110. method = methods[i];
  111. for (propertyName in this[method]) {
  112. if (this[method].hasOwnProperty(propertyName) && jqmHash[this[method][propertyName]]) {
  113. jqmHash[this[method][propertyName]].w[method](this);
  114. }
  115. }
  116. }
  117. return false;
  118. });
  119. }
  120. this[key].push(jqm);
  121. });
  122. });
  123. };
  124. $.fn.jqm = function (o) {
  125. var p = {
  126. overlay: 50,
  127. closeoverlay: false,
  128. overlayClass: "jqmOverlay",
  129. closeClass: "jqmClose",
  130. trigger: ".jqModal",
  131. ajax: false,
  132. ajaxText: "",
  133. target: false,
  134. modal: false,
  135. toTop: false,
  136. onShow: false,
  137. onHide: false,
  138. onLoad: false
  139. };
  140. return this.each(function () {
  141. if (this._jqm) {
  142. jqmHash[this._jqm].c = $.extend({}, jqmHash[this._jqm].c, o);
  143. return jqmHash[this._jqm].c;
  144. }
  145. jqmHashLength++;
  146. this._jqm = jqmHashLength;
  147. jqmHash[jqmHashLength] = {
  148. // comment from https://github.com/briceburg/jqModal/blob/master/jqModal.js
  149. // hash object;
  150. // w: (jQuery object) The modal element
  151. // c: (object) The modal's options object
  152. // o: (jQuery object) The overlay element
  153. // t: (DOM object) The triggering element
  154. c: $.extend(p, $.jqm.params, o),
  155. a: false,
  156. w: $(this).addClass("jqmID" + jqmHashLength),
  157. s: jqmHashLength // used as id too
  158. };
  159. if (p.trigger) {
  160. $(this).jqmAddTrigger(p.trigger);
  161. }
  162. });
  163. };
  164. $.fn.jqmAddClose = function (trigger) {
  165. return registerHideOrShow(this, trigger, "jqmHide");
  166. };
  167. $.fn.jqmAddTrigger = function (trigger) {
  168. return registerHideOrShow(this, trigger, "jqmShow");
  169. };
  170. $.fn.jqmShow = function (trigger) {
  171. return this.each(function () {
  172. $.jqm.open(this._jqm, trigger);
  173. });
  174. };
  175. $.fn.jqmHide = function (trigger) {
  176. return this.each(function () {
  177. $.jqm.close(this._jqm, trigger);
  178. });
  179. };
  180. $.jqm = {
  181. hash: {},
  182. open: function (s, trigger) {
  183. var h = jqmHash[s], $overlay, target, url,
  184. options = h.c, parentOffset = h.w.parent().offset(), left, top,
  185. cc = "." + options.closeClass,
  186. z = (parseInt(h.w.css("z-index"), 10));
  187. z = (z > 0) ? z : 3000;
  188. $overlay = $("<div></div>").css({
  189. height: "100%",
  190. width: "100%",
  191. position: "fixed",
  192. left: 0,
  193. top: 0,
  194. "z-index": z - 1,
  195. opacity: options.overlay / 100
  196. });
  197. if (h.a) {
  198. return false;
  199. }
  200. h.t = trigger;
  201. h.a = true;
  202. h.w.css("z-index", z);
  203. if ($(h.w[0].ownerDocument).data("ui-dialog-overlays")) {
  204. h.w.addClass("ui-dialog"); // hack to allow input inside of jQuery UI modal
  205. }
  206. if (options.modal) {
  207. if (!createdModals[0]) {
  208. setTimeout(function () {
  209. bindOrUnbindEvents("bind");
  210. }, 1);
  211. }
  212. createdModals.push(s);
  213. } else if (options.overlay > 0) {
  214. if (options.closeoverlay) {
  215. h.w.jqmAddClose($overlay);
  216. }
  217. } else {
  218. $overlay = false;
  219. }
  220. h.o = $overlay ? $overlay.addClass(options.overlayClass).prependTo("body") : false;
  221. if (options.ajax) {
  222. target = options.target || h.w;
  223. url = options.ajax;
  224. target = (typeof target === "string") ? $(target, h.w) : $(target);
  225. url = (url.substr(0, 1) === "@") ? $(trigger).attr(url.substring(1)) : url;
  226. target.html(options.ajaxText)
  227. .load(url, function () {
  228. if (options.onLoad) {
  229. options.onLoad.call(this, h);
  230. }
  231. if (cc) {
  232. h.w.jqmAddClose($(cc, h.w));
  233. }
  234. setFocus(h);
  235. });
  236. } else if (cc) {
  237. h.w.jqmAddClose($(cc, h.w));
  238. }
  239. if (options.toTop && h.o) {
  240. parentOffset = h.w.parent().offset();
  241. left = parseFloat(h.w.css("left") || 0);
  242. top = parseFloat(h.w.css("top") || 0);
  243. h.w.before('<span id="jqmP' + h.w[0]._jqm + '"></span>')
  244. .insertAfter(h.o);
  245. h.w.css({ top: parentOffset.top + top, left: parentOffset.left + left });
  246. }
  247. if (options.onShow) {
  248. options.onShow(h);
  249. } else {
  250. h.w.show();
  251. }
  252. setFocus(h);
  253. return false;
  254. },
  255. close: function (s) {
  256. var h = jqmHash[s];
  257. if (!h.a) {
  258. return false;
  259. }
  260. h.a = false;
  261. if (createdModals[0]) {
  262. createdModals.pop();
  263. if (!createdModals[0]) {
  264. bindOrUnbindEvents("unbind");
  265. }
  266. }
  267. if (h.c.toTop && h.o) {
  268. $("#jqmP" + h.w[0]._jqm)
  269. .after(h.w)
  270. .remove();
  271. }
  272. if (h.c.onHide) {
  273. h.c.onHide(h);
  274. } else {
  275. h.w.hide();
  276. if (h.o) {
  277. h.o.remove();
  278. }
  279. }
  280. return false;
  281. },
  282. params: {}
  283. };
  284. jqmHash = $.jqm.hash;
  285. // end module jqmodal
  286. }));