nanomodal.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. var nanoModal;
  2. (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  3. var ModalEvent = require("./ModalEvent");
  4. function El(tag, classNames) {
  5. var doc = document;
  6. var el = (tag.nodeType || tag === window) ? tag : doc.createElement(tag);
  7. var eventHandlers = [];
  8. if (classNames) {
  9. el.className = classNames;
  10. }
  11. var onShowEvent = ModalEvent();
  12. var onHideEvent = ModalEvent();
  13. var addListener = function(event, handler) {
  14. if (el.addEventListener) {
  15. el.addEventListener(event, handler, false);
  16. } else {
  17. el.attachEvent("on" + event, handler);
  18. }
  19. eventHandlers.push({
  20. event: event,
  21. handler: handler
  22. });
  23. };
  24. var removeListener = function(event, handler) {
  25. if (el.removeEventListener) {
  26. el.removeEventListener(event, handler);
  27. } else {
  28. el.detachEvent("on" + event, handler);
  29. }
  30. var t = eventHandlers.length;
  31. var handlerObj;
  32. while (t-- > 0) {
  33. handlerObj = eventHandlers[t];
  34. if (handlerObj.event === event && handlerObj.handler === handler) {
  35. eventHandlers.splice(t, 1);
  36. break;
  37. }
  38. }
  39. };
  40. var addClickListener = function(handler) {
  41. var throttle = false;
  42. var throttleHandler = function(e) {
  43. if (!throttle) {
  44. throttle = true;
  45. setTimeout(function() {
  46. throttle = false;
  47. }, 100);
  48. handler(e);
  49. }
  50. };
  51. addListener("touchstart", throttleHandler);
  52. addListener("mousedown", throttleHandler);
  53. };
  54. var show = function(arg) {
  55. if (el) {
  56. el.style.display = "block";
  57. onShowEvent.fire(arg);
  58. }
  59. };
  60. var hide = function(arg) {
  61. if (el) {
  62. el.style.display = "none";
  63. onHideEvent.fire(arg);
  64. }
  65. };
  66. var isShowing = function() {
  67. return el.style && el.style.display === "block";
  68. };
  69. var html = function(html) {
  70. if (el) {
  71. el.innerHTML = html;
  72. }
  73. };
  74. var text = function(text) {
  75. if (el) {
  76. html("");
  77. el.appendChild(doc.createTextNode(text));
  78. }
  79. };
  80. var remove = function() {
  81. if (el.parentNode) {
  82. var x = eventHandlers.length;
  83. var eventHandler;
  84. while (x-- > 0) {
  85. eventHandler = eventHandlers[x];
  86. removeListener(eventHandler.event, eventHandler.handler);
  87. }
  88. el.parentNode.removeChild(el);
  89. onShowEvent.removeAllListeners();
  90. onHideEvent.removeAllListeners();
  91. }
  92. };
  93. var add = function(elObject) {
  94. var elementToAppend = elObject.el || elObject;
  95. el.appendChild(elementToAppend);
  96. };
  97. return {
  98. el: el,
  99. addListener: addListener,
  100. addClickListener: addClickListener,
  101. onShowEvent: onShowEvent,
  102. onHideEvent: onHideEvent,
  103. show: show,
  104. hide: hide,
  105. isShowing: isShowing,
  106. html: html,
  107. text: text,
  108. remove: remove,
  109. add: add
  110. };
  111. }
  112. module.exports = El;
  113. },{"./ModalEvent":3}],2:[function(require,module,exports){
  114. var El = require("./El");
  115. function Modal(content, options, overlay, customShow, customHide) {
  116. if (content === undefined) {
  117. return;
  118. }
  119. options = options || {};
  120. var modal = El("div", "nanoModal nanoModalOverride " + (options.classes || ""));
  121. var contentContainer = El("div", "nanoModalContent");
  122. var buttonArea = El("div", "nanoModalButtons");
  123. var onRequestHideListenerId;
  124. modal.add(contentContainer);
  125. modal.add(buttonArea);
  126. modal.el.style.display = "none";
  127. var buttons = [];
  128. var pub;
  129. options.buttons = options.buttons || [{
  130. text: "Close",
  131. handler: "hide",
  132. primary: true
  133. }];
  134. var removeButtons = function() {
  135. var t = buttons.length;
  136. while (t-- > 0) {
  137. var button = buttons[t];
  138. button.remove();
  139. }
  140. buttons = [];
  141. };
  142. var center = function() {
  143. modal.el.style.marginLeft = -modal.el.clientWidth / 2 + "px";
  144. };
  145. var anyModalsOpen = function() {
  146. var modals = document.querySelectorAll(".nanoModal");
  147. var t = modals.length;
  148. while (t-- > 0) {
  149. if (modals[t].style.display !== "none") {
  150. return true;
  151. }
  152. }
  153. return false;
  154. };
  155. var defaultShow = function() {
  156. if (!modal.isShowing()) {
  157. // Call the static method from the Modal module.
  158. Modal.resizeOverlay();
  159. overlay.show(overlay);
  160. modal.show(pub);
  161. center();
  162. }
  163. };
  164. var defaultHide = function() {
  165. if (modal.isShowing()) {
  166. modal.hide(pub);
  167. if (!anyModalsOpen()) {
  168. overlay.hide(overlay);
  169. }
  170. if (options.autoRemove) {
  171. pub.remove();
  172. }
  173. }
  174. };
  175. var quickClone = function(obj) {
  176. var newObj = {};
  177. for (var key in obj) {
  178. if (obj.hasOwnProperty(key)) {
  179. newObj[key] = obj[key];
  180. }
  181. }
  182. return newObj;
  183. };
  184. pub = {
  185. modal: modal,
  186. overlay: overlay,
  187. show: function() {
  188. if (customShow) {
  189. customShow(defaultShow, pub);
  190. } else {
  191. defaultShow();
  192. }
  193. return pub;
  194. },
  195. hide: function() {
  196. if (customHide) {
  197. customHide(defaultHide, pub);
  198. } else {
  199. defaultHide();
  200. }
  201. return pub;
  202. },
  203. onShow: function(callback) {
  204. modal.onShowEvent.addListener(function() {
  205. callback(pub);
  206. });
  207. return pub;
  208. },
  209. onHide: function(callback) {
  210. modal.onHideEvent.addListener(function() {
  211. callback(pub);
  212. });
  213. return pub;
  214. },
  215. remove: function() {
  216. overlay.onRequestHide.removeListener(onRequestHideListenerId);
  217. onRequestHideListenerId = null;
  218. removeButtons();
  219. modal.remove();
  220. },
  221. setButtons: function(buttonList) {
  222. var btnIdx = buttonList.length;
  223. var btnObj;
  224. var btnEl;
  225. var classes;
  226. var giveButtonCustomClickListener = function(btnEl, btnObj) {
  227. var pubCopy = quickClone(pub);
  228. btnEl.addClickListener(function(e) {
  229. pubCopy.event = e || window.event;
  230. btnObj.handler(pubCopy);
  231. });
  232. };
  233. removeButtons();
  234. if (btnIdx === 0) {
  235. buttonArea.hide();
  236. } else {
  237. buttonArea.show();
  238. while (btnIdx-- > 0) {
  239. btnObj = buttonList[btnIdx];
  240. classes = "nanoModalBtn";
  241. if (btnObj.primary) {
  242. classes += " nanoModalBtnPrimary";
  243. }
  244. classes += btnObj.classes ? " " + btnObj.classes : "";
  245. btnEl = El("button", classes);
  246. if (btnObj.handler === "hide") {
  247. btnEl.addClickListener(pub.hide);
  248. } else if (btnObj.handler) {
  249. giveButtonCustomClickListener(btnEl, btnObj);
  250. }
  251. btnEl.text(btnObj.text);
  252. buttonArea.add(btnEl);
  253. buttons.push(btnEl);
  254. }
  255. }
  256. center();
  257. return pub;
  258. },
  259. setContent: function(newContent) {
  260. // Only good way of checking if a node in IE8...
  261. if (newContent.nodeType) {
  262. contentContainer.html("");
  263. contentContainer.add(newContent);
  264. } else {
  265. contentContainer.html(newContent);
  266. }
  267. center();
  268. content = newContent;
  269. return pub;
  270. },
  271. getContent: function() {
  272. return content;
  273. }
  274. };
  275. onRequestHideListenerId = overlay.onRequestHide.addListener(function() {
  276. if (options.overlayClose !== false && modal.isShowing()) {
  277. pub.hide();
  278. }
  279. });
  280. pub.setContent(content).setButtons(options.buttons);
  281. document.body.appendChild(modal.el);
  282. return pub;
  283. }
  284. var doc = document;
  285. var getDocumentDim = function(name) {
  286. var docE = doc.documentElement;
  287. var scroll = "scroll" + name;
  288. var offset = "offset" + name;
  289. return Math.max(doc.body[scroll], docE[scroll],
  290. doc.body[offset], docE[offset], docE["client" + name]);
  291. };
  292. // Make this a static function so that main.js has access to it so it can
  293. // add a window keydown event listener. Modal.js also needs this function.
  294. Modal.resizeOverlay = function() {
  295. var overlay = doc.getElementById("nanoModalOverlay");
  296. overlay.style.width = getDocumentDim("Width") + "px";
  297. overlay.style.height = getDocumentDim("Height") + "px";
  298. };
  299. module.exports = Modal;
  300. },{"./El":1}],3:[function(require,module,exports){
  301. function ModalEvent() {
  302. var listeners = {};
  303. var nextListenerId = 0;
  304. var addListener = function(callback) {
  305. listeners[nextListenerId] = callback;
  306. return nextListenerId++;
  307. };
  308. var removeListener = function(id) {
  309. if (id) {
  310. delete listeners[id];
  311. }
  312. };
  313. var removeAllListeners = function() {
  314. listeners = {};
  315. };
  316. var fire = function() {
  317. for (var x = 0, num = nextListenerId; x < num; ++x) {
  318. if (listeners[x]) {
  319. listeners[x].apply(null, arguments);
  320. }
  321. }
  322. };
  323. return {
  324. addListener: addListener,
  325. removeListener: removeListener,
  326. removeAllListeners: removeAllListeners,
  327. fire: fire
  328. };
  329. }
  330. module.exports = ModalEvent;
  331. },{}],4:[function(require,module,exports){
  332. var ModalEvent = require("./ModalEvent");
  333. var nanoModalAPI = (function() {
  334. var El = require("./El");
  335. var Modal = require("./Modal");
  336. var overlay;
  337. var doc = document;
  338. function init() {
  339. if (!doc.querySelector("#nanoModalOverlay")) {
  340. // Put the main styles on the page.
  341. var styleObj = El("style");
  342. var style = styleObj.el;
  343. var firstElInHead = doc.querySelectorAll("head")[0].childNodes[0];
  344. firstElInHead.parentNode.insertBefore(style, firstElInHead);
  345. var styleText = ".nanoModal{position:absolute;top:100px;left:50%;display:none;z-index:9999;min-width:300px;padding:15px 20px 10px;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;background:#fff;background:-moz-linear-gradient(top,#fff 0,#ddd 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#fff),color-stop(100%,#ddd));background:-webkit-linear-gradient(top,#fff 0,#ddd 100%);background:-o-linear-gradient(top,#fff 0,#ddd 100%);background:-ms-linear-gradient(top,#fff 0,#ddd 100%);background:linear-gradient(to bottom,#fff 0,#ddd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#dddddd', GradientType=0)}.nanoModalOverlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:9998;background:#000;display:none;-ms-filter:\"alpha(Opacity=50)\";-moz-opacity:.5;-khtml-opacity:.5;opacity:.5}.nanoModalButtons{border-top:1px solid #ddd;margin-top:15px;text-align:right}.nanoModalBtn{color:#333;background-color:#fff;display:inline-block;padding:6px 12px;margin:8px 4px 0;font-size:14px;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid transparent;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nanoModalBtn:active,.nanoModalBtn:focus,.nanoModalBtn:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.nanoModalBtn.nanoModalBtnPrimary{color:#fff;background-color:#428bca;border-color:#357ebd}.nanoModalBtn.nanoModalBtnPrimary:active,.nanoModalBtn.nanoModalBtnPrimary:focus,.nanoModalBtn.nanoModalBtnPrimary:hover{color:#fff;background-color:#3071a9;border-color:#285e8e}";
  346. if (style.styleSheet) {
  347. style.styleSheet.cssText = styleText;
  348. } else {
  349. styleObj.text(styleText);
  350. }
  351. // Make the overlay and put it on the page.
  352. overlay = El("div", "nanoModalOverlay nanoModalOverride");
  353. overlay.el.id = "nanoModalOverlay";
  354. doc.body.appendChild(overlay.el);
  355. // Add an event so that the modals can hook into it to close.
  356. overlay.onRequestHide = ModalEvent();
  357. var overlayCloseFunc = function() {
  358. overlay.onRequestHide.fire();
  359. };
  360. overlay.addClickListener(overlayCloseFunc);
  361. El(doc).addListener("keydown", function(e) {
  362. var keyCode = e.which || e.keyCode;
  363. if (keyCode === 27) { // 27 is Escape
  364. overlayCloseFunc();
  365. }
  366. });
  367. var windowEl = El(window);
  368. var resizeOverlayTimeout;
  369. windowEl.addListener("resize", function() {
  370. if (resizeOverlayTimeout) {
  371. clearTimeout(resizeOverlayTimeout);
  372. }
  373. resizeOverlayTimeout = setTimeout(Modal.resizeOverlay, 100);
  374. });
  375. // Make SURE we have the correct dimensions so we make the overlay the right size.
  376. // Some devices fire the event before the document is ready to return the new dimensions.
  377. windowEl.addListener("orientationchange", function() {
  378. for (var t = 0; t < 3; ++t) {
  379. setTimeout(Modal.resizeOverlay, 1000 * t + 200);
  380. }
  381. });
  382. }
  383. }
  384. if (document.body) {
  385. init();
  386. }
  387. var api = function(content, options) {
  388. init();
  389. return Modal(content, options, overlay, api.customShow, api.customHide);
  390. };
  391. api.resizeOverlay = Modal.resizeOverlay;
  392. return api;
  393. })();
  394. // expose api to var outside browserify so that we can export a module correctly.
  395. nanoModal = nanoModalAPI;
  396. },{"./El":1,"./Modal":2,"./ModalEvent":3}]},{},[1,2,3,4]);
  397. if (typeof window !== "undefined") {
  398. if (typeof window.define === "function" && window.define.amd) {
  399. window.define(function() {
  400. return nanoModal;
  401. });
  402. }
  403. window.nanoModal = nanoModal;
  404. }
  405. if (typeof module !== "undefined") {
  406. module.exports = nanoModal;
  407. }