jquery.dolPopup.js 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049
  1. /**
  2. * Copyright (c) UNA, Inc - https://una.io
  3. * MIT License - https://opensource.org/licenses/MIT
  4. *
  5. * @defgroup UnaCore UNA Core
  6. * @{
  7. */
  8. (function($) {
  9. $.fn.dolPopupDefaultOptions = {
  10. parent: 'body', // parent element selector
  11. closeOnOuterClick: true,
  12. removeOnClose: false,
  13. closeElement: '.bx-popup-element-close', // link to element which will close popup
  14. position: 'centered', // | 'absolute' | 'fixed' | event | element,
  15. fog: true, // false | true | {color:string, opacity: float},
  16. pointer: false, // {el:(string_id|jquery_object), align: (left|right|center)},
  17. left: 0, // only for fixed or absolute
  18. top: 0, // only for fixed
  19. bottom: 'auto', // only for fixed or absolute
  20. moveToDocRoot: true,
  21. displayMode: 'trans', // trans | box | is needed for dynamic loading with dolPopupAjax
  22. onBeforeShow: function () {},
  23. onShow: function () {},
  24. onBeforeHide: function () {},
  25. onHide: function () {},
  26. speed: 200,
  27. cue: true // play the open/close interface sound (see bx_sound); alerts report outcomes, which play their own
  28. };
  29. $.fn.dolPopupDefaultPointerOptions = {
  30. align: 'right',
  31. offset: '0 0',
  32. offset_pointer: '0 0'
  33. };
  34. $.fn.dolPopupCenter = function () {
  35. var dy = $(window).height() > $(this).outerHeight() ? ($(window).height() - $(this).outerHeight()) / 2 : 0;
  36. var dx = $(window).width() > $(this).outerWidth() ? ($(window).width() - $(this).outerWidth()) / 2 : 0;
  37. this.css("position","absolute");
  38. this.css("top", Math.max(0, dy + $(window).scrollTop()) + "px");
  39. this.css("left", Math.max(0, dx + $(window).scrollLeft()) + "px");
  40. return this;
  41. }
  42. $.fn.dolPopupCenterHor = function () {
  43. var dx = $(window).width() > $(this).outerWidth() ? ($(window).width() - $(this).outerWidth()) / 2 : 0;
  44. this.css("left", Math.max(0, dx + $(window).scrollLeft()) + "px");
  45. return this;
  46. }
  47. function _getScrollbarWidth () {
  48. if ($(document.body).height() <= $(window).height()) {
  49. return 0;
  50. }
  51. var outer = document.createElement("div"),
  52. inner = document.createElement("div"),
  53. widthNoScroll,
  54. widthWithScroll;
  55. outer.style.visibility = "hidden";
  56. outer.style.width = "100px";
  57. document.body.appendChild(outer);
  58. widthNoScroll = outer.offsetWidth;
  59. // Force scrollbars
  60. outer.style.overflow = "scroll";
  61. // Add innerdiv
  62. inner.style.width = "100%";
  63. outer.appendChild(inner);
  64. widthWithScroll = inner.offsetWidth;
  65. // Remove divs
  66. outer.parentNode.removeChild(outer);
  67. return widthNoScroll - widthWithScroll;
  68. };
  69. /**
  70. * A popup sounds as it opens and when the visitor closes it (close element, Escape, outer click, its trigger).
  71. * One closed from code after a save stays quiet: the save plays its own cue. Menus anchored to a pointer are
  72. * frequent, so they are subtle.
  73. */
  74. function _dolPopupCue (o, sCue, $el) {
  75. if (!o || o.cue === false || typeof(bx_sound) != 'function')
  76. return;
  77. // A press on the trigger of an open popup is an outer mousedown and then the trigger's own click: one close.
  78. if ($el) {
  79. var iNow = Date.now();
  80. if (sCue == 'close' && iNow - ($el.data('bx-popup-cue-closed') || 0) < 500)
  81. return;
  82. $el.data('bx-popup-cue-closed', sCue == 'close' ? iNow : 0);
  83. }
  84. bx_sound(sCue, {emphasis: false != o.pointer ? 'subtle' : 'normal'});
  85. };
  86. function _dolPopupLockScreen (bLock) {
  87. var eBody = $(document.body);
  88. var eBodyHtml = $("html, body");
  89. if((bLock && eBodyHtml.hasClass('bx-popup-lock')) || (!bLock && !eBodyHtml.hasClass('bx-popup-lock')))
  90. return;
  91. var iPaddingRight = parseInt(eBody.css("padding-right")) + ((bLock ? 1 : -1) * _getScrollbarWidth());
  92. eBody.css("padding-right", iPaddingRight + "px");
  93. eBodyHtml.toggleClass('bx-popup-lock', bLock);
  94. };
  95. $.fn.dolPopup = function(options) {
  96. var $this = this;
  97. var options = options || {};
  98. var o = $.extend({}, $.fn.dolPopupDefaultOptions, options);
  99. if (false != o.pointer) {
  100. o.fog = false;
  101. o.pointer = $.extend({}, $.fn.dolPopupDefaultPointerOptions, $(document).data('bx-popup-options') ? $(document).data('bx-popup-options') : {}, o.pointer);
  102. }
  103. if (o.fog && !$('#bx-popup-fog').length) {
  104. $('<div id="bx-popup-fog" class="bx-popup-fog bx-def-z-index-overlay" style="display: none;">&nbsp;</div>').prependTo('body');
  105. }
  106. var oFogCss = {
  107. width: $(window).width(),
  108. height: $(window).height(),
  109. };
  110. if(typeof o.fog == 'object') {
  111. if(o.fog.opacity != undefined)
  112. oFogCss = $.extend({}, oFogCss, {opacity: o.fog.opacity});
  113. if(o.fog.color != undefined)
  114. oFogCss = $.extend({}, oFogCss, {backgroundColor: o.fog.color});
  115. }
  116. $('#bx-popup-fog').css(oFogCss);
  117. $(window).on('resize.popupFog', function () {
  118. $('#bx-popup-fog').css({
  119. width: $(window).width(),
  120. height: $(window).height()
  121. });
  122. }).on('keyup.popup', function(oEvent) {
  123. if(o.closeOnOuterClick && oEvent.which == 27) {
  124. _dolPopupCue(o, 'close', $this);
  125. $this.dolPopupHide();
  126. }
  127. });
  128. return this.each(function() {
  129. var $el = $(this);
  130. $el.addClass('bx-def-z-index-modal bx-popup-responsive');
  131. // element must have id
  132. if (!$el.attr('id'))
  133. return false;
  134. if ($el.is(":visible")) { // if popup is shown - hide it
  135. _dolPopupCue($el.data('bx-popup-options') || o, 'close', $el);
  136. $el.dolPopupHide();
  137. return true;
  138. }
  139. _dolPopupCue(o, 'open', $el);
  140. if (false != o.pointer)
  141. $el.addClass('bx-popup-with-pointer'); // to make all popups with pointer not responsive add: .removeClass('bx-popup-responsive')
  142. if (o.cssClass && o.cssClass != '' && !$el.hasClass(o.cssClass))
  143. $el.addClass(o.cssClass);
  144. // default style for correct positioning
  145. $el.css({
  146. display: 'block',
  147. visibility: 'hidden',
  148. position: 'absolute',
  149. top: 0,
  150. left: 0
  151. });
  152. if (o.moveToDocRoot)
  153. $el.detach().appendTo('body');
  154. setTimeout(function() { // timeout is needed for some browsers to render element
  155. if (o.fog)
  156. _dolPopupLockScreen(true);
  157. // a popup behind a fog is modal for assistive technology as well
  158. $el.attr('aria-modal', o.fog ? 'true' : null);
  159. // remove any transitions before setting popup position
  160. $el.removeClass('bx-popup-transitions bx-popup-inactive');
  161. // set popup position
  162. $el._dolPopupSetPosition(o);
  163. if (!$el.hasClass('bx-popup-applied')) { // do this only once
  164. $el.addClass('bx-popup-applied');
  165. // save options for element
  166. $el.data('bx-popup-options', o);
  167. // attach event for "close element"
  168. if (o.closeElement) {
  169. $(o.closeElement, $el)
  170. .css('cursor', 'hand')
  171. .click(function() {
  172. _dolPopupCue($el.data('bx-popup-options'), 'close', $el);
  173. $el.dolPopupHide();
  174. });
  175. }
  176. // attach event for outer click checking
  177. if (o.closeOnOuterClick) {
  178. var fCallback = function(e) {
  179. if ($el.hasClass('bx-popup-applied') && $el.is(':visible')) {
  180. if ($(e.target).parents('#' + $el.attr('id')).length == 0) {
  181. _dolPopupCue($el.data('bx-popup-options'), 'close', $el);
  182. $el.dolPopupHide();
  183. }
  184. }
  185. return true;
  186. }
  187. $(document).on({
  188. mousedown: fCallback,
  189. touchend: fCallback
  190. });
  191. }
  192. }
  193. if(typeof(o.onBeforeShow) == 'function')
  194. o.onBeforeShow($el);
  195. else if(typeof(o.onBeforeShow) == 'string')
  196. eval(o.onBeforeShow);
  197. // transition effect
  198. if (o.moveToDocRoot) {
  199. // we need to disable classes with "max-height:100%", since popup isn't in the root element, so animation will not work when moveToDocRoot option is set
  200. $el.addClass('bx-popup-inactive');
  201. setTimeout(function () {
  202. $el.addClass('bx-popup-transitions bx-popup-active');
  203. }, 10);
  204. }
  205. // Don't should popup with pointer if there is no parent. Checking before showing.
  206. if(typeof o.pointer.el == 'string')
  207. o.pointer.el = $(o.pointer.el);
  208. if($(o.pointer.el).length > 0 && !$.contains(document, o.pointer.el[0])) {
  209. $el.remove();
  210. return;
  211. }
  212. // show popup
  213. $el.css({display: 'block', visibility: 'visible'});
  214. if (o.fog) {
  215. var oOnHide = function() {
  216. $(window).triggerHandler('resize.popupFog');
  217. };
  218. if (o.speed > 0)
  219. $('#bx-popup-fog').fadeIn(o.speed, oOnHide);
  220. else
  221. $('#bx-popup-fog').show(oOnHide);
  222. }
  223. /*
  224. * Trap focus inside popup.
  225. */
  226. $el.find('.bx-focus-trap').bind('focus', function() {
  227. var aFocusable = bx_get_focusable($el.get(0));
  228. if(aFocusable && aFocusable.length > 0)
  229. $(aFocusable[0]).focus();
  230. });
  231. /*
  232. * Add onHide to return focus back.
  233. */
  234. if(bx_clicked_stack_lenth()) {
  235. var onHide = null;
  236. if(typeof(o.onHide) == 'function')
  237. onHide = o.onHide;
  238. else if(typeof(o.onHide) == 'string')
  239. onHide = function(oPopup) {
  240. eval(o.onHide);
  241. };
  242. o.onHide = function() {
  243. if(typeof(onHide) == 'function')
  244. onHide($el);
  245. $(bx_clicked_stack_pop()).focus();
  246. };
  247. }
  248. setTimeout(function () {
  249. // Don't should popup with pointer if there is no parent. Checking after showing.
  250. if(typeof o.pointer.el == 'string')
  251. o.pointer.el = $(o.pointer.el);
  252. if($(o.pointer.el).length > 0 && !$.contains(document, o.pointer.el[0])) {
  253. $el.remove();
  254. return;
  255. }
  256. var aFocusable = bx_get_focusable($el.get(0));
  257. if(aFocusable && aFocusable.length > 0)
  258. $(aFocusable[0]).focus();
  259. if(typeof(o.onShow) == 'function')
  260. o.onShow($el);
  261. else if(typeof(o.onShow) == 'string')
  262. eval(o.onShow);
  263. }, o.speed);
  264. }, 100);
  265. });
  266. };
  267. $.fn.dolPopupInline = function(oOptionsCustom) {
  268. if(typeof(oOptionsCustom) == 'undefined' || typeof(oOptionsCustom) != 'object')
  269. oOptionsCustom = {};
  270. var oOptionsTotal = $.extend({}, oOptionsCustom, {
  271. position: 'fixed',
  272. top: '0px',
  273. fog: false,
  274. closeElement: '.bx-popup-close',
  275. onBeforeShow: function(oPopup) {
  276. if(typeof(oOptionsCustom.onBeforeShow) == 'function')
  277. oOptionsCustom.onBeforeShow(oPopup);
  278. $('body').addClass('bx-popup-inline-holder');
  279. },
  280. onBeforeHide: function(oPopup) {
  281. if(typeof(oOptionsCustom.onBeforeHide) == 'function')
  282. oOptionsCustom.onBeforeHide(oPopup);
  283. $('body').removeClass('bx-popup-inline-holder');
  284. },
  285. onHide: function(oPopup) {
  286. if(typeof(oOptionsCustom.onHide) == 'function')
  287. oOptionsCustom.onHide(oPopup);
  288. if(oOptionsCustom.removeOnClose == true)
  289. $(oPopup).remove();
  290. }
  291. });
  292. return this.each(function() {
  293. $(this).addClass('bx-popup-inline').dolPopup(oOptionsTotal);
  294. });
  295. };
  296. $.fn.dolPopupFullScreen = function(oOptions) {
  297. return this.each(function() {
  298. $(this).addClass('bx-popup-full-screen').dolPopup(oOptions);
  299. });
  300. };
  301. $.fn.dolPopupHide = function(options) {
  302. if ('undefined' == typeof(options) || 'object' != typeof(options))
  303. options = {};
  304. return this.each(function() {
  305. var $el = $(this);
  306. if (!$el.hasClass('bx-popup-applied'))
  307. return false;
  308. if (!$el.is(':visible') || 'hidden' == $el.css('visibility') || 'none' == $el.css('display'))
  309. return false;
  310. var o = $.extend({}, $el.data('bx-popup-options'), options);
  311. if (!o)
  312. return false;
  313. if ($el.data('bx-popup-timer'))
  314. clearInterval($el.data('bx-popup-timer'));
  315. $(window).off('resize.popupWindow');
  316. $(window).off('resize.popupPointer');
  317. $(window).off('resize.popupFog');
  318. $(window).off('keyup.popup');
  319. if(typeof(o.onBeforeHide) == 'function')
  320. o.onBeforeHide($el);
  321. else if(typeof(o.onBeforeHide) == 'string')
  322. eval(o.onBeforeHide);
  323. $el.removeClass('bx-popup-active').addClass('bx-popup-inactive').removeAttr('aria-modal');
  324. var onHide = null;
  325. if(typeof(o.onHide) == 'function')
  326. onHide = o.onHide;
  327. else if(typeof(o.onHide) == 'string')
  328. onHide = function(oPopup) {
  329. eval(o.onHide);
  330. };
  331. if (o.speed > 0) {
  332. if (o.fog)
  333. $('#bx-popup-fog').fadeOut(o.speed);
  334. setTimeout(function () {
  335. $el.hide();
  336. if(typeof(onHide) == 'function')
  337. onHide($el);
  338. if(o.removeOnClose == true)
  339. $el.remove();
  340. }, o.speed);
  341. } else {
  342. if (o.fog)
  343. $('#bx-popup-fog').hide();
  344. $el.hide(function() {
  345. if(typeof(onHide) == 'function')
  346. onHide($el);
  347. if(o.removeOnClose == true)
  348. $el.remove();
  349. });
  350. }
  351. _dolPopupLockScreen(false);
  352. });
  353. };
  354. $.fn.dolPopupAjax = function(options) {
  355. options = options || {};
  356. options = $.extend({}, $.fn.dolPopupDefaultOptions, options);
  357. if(!options.url)
  358. return;
  359. if(!options.container)
  360. options.container = '.bx-popup-content-wrapped';
  361. var bDisplayModeBox = false;
  362. if(options.displayMode && options.displayMode == 'box')
  363. bDisplayModeBox = true;
  364. var bFullScreen = false;
  365. if(options.fullScreen !== undefined)
  366. bFullScreen = options.fullScreen;
  367. var bx_menu_on = function (e, b) {
  368. var li = $(e).parents('li:first');
  369. if (!li.length)
  370. return;
  371. if (b) {
  372. var ul = $(e).parents('ul:first');
  373. ul.find('li').removeClass('bx-menu-tab-active');
  374. li.addClass('bx-menu-tab-active');
  375. } else {
  376. li.removeClass('bx-menu-tab-active');
  377. }
  378. }
  379. var bx_menu_is_on = function (e) {
  380. var li = $(e).parents('li:first');
  381. if (!li.length)
  382. return false;
  383. return li.hasClass('bx-menu-tab-active');
  384. }
  385. return this.each(function() {
  386. var e = $(this);
  387. // get id
  388. var sPopupId = '';
  389. var sIdPrefix = 'bx-popup-ajax-wrapper-';
  390. if(typeof(e.attr('bx-popup-id')) != 'undefined')
  391. sPopupId = sIdPrefix + e.attr('bx-popup-id');
  392. else if(typeof(options.id) != 'undefined')
  393. switch(typeof(options.id)) {
  394. case 'string':
  395. sPopupId = sIdPrefix + options.id;
  396. break;
  397. case 'object':
  398. sPopupId = typeof(options.id.force) != 'undefined' && options.id.force ? options.id.value : sIdPrefix + options.id.value;
  399. break;
  400. }
  401. else
  402. sPopupId = sIdPrefix + parseInt(2147483647 * Math.random());
  403. var oPointerOptions = $.isWindow(e[0]) ? false : $.extend({}, {el:$(e), align:'center'}, options.pointer);
  404. if ($('#' + sPopupId + ':visible').length) { // if popup exists and is shown - hide it
  405. $('#' + sPopupId).dolPopupHide();
  406. }
  407. else if ($('#' + sPopupId).length) { // if popup exists but not shown - unhide it
  408. if (!$.isWindow(e[0]))
  409. bx_menu_on(e, true);
  410. if (options.cssClass && options.cssClass != '' && !$('#' + sPopupId).hasClass(options.cssClass)) {
  411. $('#' + sPopupId).addClass(options.cssClass);
  412. }
  413. var oPopupOptions = $.extend({}, options, {
  414. pointer: oPointerOptions,
  415. onHide: function (oPopup) {
  416. if (!$.isWindow(e[0]))
  417. bx_menu_on(e, false);
  418. if(typeof(options.onHide) == 'function')
  419. options.onHide(oPopup);
  420. }
  421. });
  422. if(bFullScreen)
  423. $('#' + sPopupId).dolPopupFullScreen(oPopupOptions);
  424. else
  425. $('#' + sPopupId).dolPopup(oPopupOptions);
  426. }
  427. else { // if popup doesn't exists - create new one from provided url
  428. if (!$.isWindow(e[0]))
  429. bx_menu_on(e, true);
  430. $('<div id="' + sPopupId + '" role="dialog" style="display:none;">' + $('#bx-popup-loading').html() + '</div>').appendTo(options.parent).find(options.container).hide();
  431. $('#' + sPopupId).addClass($('#bx-popup-loading').attr('class'));
  432. if (options.cssClass && options.cssClass != ''){
  433. $('#' + sPopupId).addClass(options.cssClass);
  434. }
  435. var oLoading = $('#' + sPopupId + ' .bx-popup-loading-wrapped');
  436. bx_loading_content(oLoading, true, true);
  437. var oPopupOptions = $.extend({}, options, {
  438. pointer: oPointerOptions,
  439. onHide: function (oPopup) {
  440. if (!$.isWindow(e[0]))
  441. bx_menu_on(e, false);
  442. if(typeof(options.onHide) == 'function')
  443. options.onHide(oPopup);
  444. }
  445. });
  446. if(bFullScreen && !bDisplayModeBox)
  447. $('#' + sPopupId).dolPopupFullScreen(oPopupOptions);
  448. else
  449. $('#' + sPopupId).dolPopup(oPopupOptions);
  450. var fOnLoad = function() {
  451. bx_loading_content(oLoading, false);
  452. var oPopup = $('#' + sPopupId);
  453. oPopup.find(options.container).bxProcessHtml().show();
  454. oPopup._dolPopupSetPosition({
  455. pointer: oPointerOptions
  456. });
  457. var aFocusable = bx_get_focusable(oPopup.get(0));
  458. if(aFocusable && aFocusable.length > 0)
  459. $(aFocusable[0]).focus();
  460. if (typeof (options.onLoad) == 'function')
  461. options.onLoad('#' + sPopupId);
  462. else if (typeof (options.onLoad) == 'string')
  463. eval(options.onLoad);
  464. };
  465. var fOnLoadImg = function () {
  466. if($('#' + sPopupId).find('img').length > 0 && !$('#' + sPopupId).find('img').get(0).complete)
  467. $('#' + sPopupId).find('img').load(fOnLoad);
  468. else
  469. fOnLoad();
  470. };
  471. var sUrl = (options.url.indexOf('http://') == 0 || options.url.indexOf('https://') == 0 || options.url.indexOf('/') == 0 ? '' : sUrlRoot) + options.url;
  472. if(bDisplayModeBox) {
  473. options.container = '.bx-popup-content:first';
  474. $.get(sUrl, function(sData) {
  475. $('#' + sPopupId).replaceWith(sData);
  476. if(bFullScreen)
  477. $('#' + sPopupId).dolPopupFullScreen(oPopupOptions);
  478. else
  479. $('#' + sPopupId).dolPopup(oPopupOptions);
  480. setTimeout(fOnLoadImg, 100); // TODO: better way is to check if item is animating before positioning it in the code where popup is positioning
  481. });
  482. }
  483. else
  484. $('#' + sPopupId).find(options.container).load(sUrl, function () {
  485. setTimeout(fOnLoadImg, 100); // TODO: better way is to check if item is animating before positioning it in the code where popup is positioning
  486. });
  487. }
  488. });
  489. };
  490. $.fn.dolPopupImage = function(sUrl, sLoadingElement) {
  491. return this.each(function() {
  492. var ePopup = $(this);
  493. var k = .97,
  494. w = $(window).width(),
  495. h = $(window).height(),
  496. eImg = new Image();
  497. if (!ePopup.find('img').size())
  498. return;
  499. ePopup.filter('.bx-popup-wrapper').addClass('bx-popup-image-wrapper');
  500. eImg.src = sUrl;
  501. if ('undefined' != typeof(sLoadingElement))
  502. bx_loading (sLoadingElement, true);
  503. $(eImg).on('load', function () {
  504. var ri = eImg.width / eImg.height;
  505. var rs = w/h;
  506. if ('undefined' != typeof(sLoadingElement))
  507. bx_loading (sLoadingElement, false);
  508. ePopup.find('img').attr('src', sUrl);
  509. if ('undefined' != typeof(window.matchMedia) && window.matchMedia("(max-width:720px)").matches)
  510. k = 1.0;
  511. // fit image into the browser window
  512. if (eImg.width < w * k && eImg.height < h * k) {
  513. ePopup.find('img').css({
  514. width: 'auto',
  515. height: 'auto'
  516. });
  517. }
  518. else {
  519. ePopup.find('img').css({
  520. width: rs > ri ? parseInt(k * eImg.width * h/eImg.height) + 'px' : 'auto',
  521. height: rs > ri ? 'auto' : parseInt(k * eImg.height * w/eImg.width) + 'px',
  522. }).addClass('bx-constrain-height');
  523. }
  524. // show popup
  525. ePopup.dolPopup();
  526. // hide popup upon clicking/tapping on the image
  527. var fCallback = function (e) {
  528. e.stopPropagation();
  529. ePopup.dolPopupHide();
  530. };
  531. ePopup.find('img').on({
  532. click: fCallback,
  533. touchend: fCallback
  534. });
  535. });
  536. });
  537. };
  538. $.fn.dolPopupAlert = function(options) {
  539. var oAPopup = $('#bx-popup-alert');
  540. var sDefMessage = '', sDefBtnOkTitle = '';
  541. var oMessage = null;
  542. if(options.message != undefined && options.message.length > 0) {
  543. oMessage = oAPopup.find('.popup_alert_text');
  544. sDefMessage = oMessage.html();
  545. oMessage.html(options.message).bxTime();
  546. }
  547. var oBtnOk = oAPopup.find('.popup_alert_ok');
  548. if(options.params != undefined && options.params.ok != undefined && options.params.ok.title != undefined && options.params.ok.title.length > 0) {
  549. sDefBtnOkTitle = oBtnOk.html();
  550. oBtnOk.html(options.params.ok.title);
  551. }
  552. var bFuncOk = options.onClickOk && typeof(options.onClickOk) == 'function';
  553. if(bFuncOk)
  554. options.closeOnOuterClick = false;
  555. oBtnOk.bind('click', function() {
  556. if(bFuncOk)
  557. options.onClickOk(oAPopup);
  558. oAPopup.dolPopupHide();
  559. });
  560. var fOnShow = options.onShow;
  561. options.onShow = function(oPopup) {
  562. oBtnOk.focus();
  563. if(typeof(fOnShow) == 'function')
  564. fOnShow(oAPopup);
  565. };
  566. var fOnHide = options.onHide;
  567. options.onHide = function(oPopup) {
  568. if(typeof(fOnHide) == 'function')
  569. fOnHide(oAPopup);
  570. /**
  571. * Restore default functions and layout
  572. * if the last one was customized.
  573. */
  574. oAPopup.find('.bx-btn').unbind('click');
  575. if(sDefMessage.length > 0)
  576. oMessage.html(sDefMessage);
  577. if(sDefBtnOkTitle.length > 0)
  578. oBtnOk.html(sDefBtnOkTitle);
  579. };
  580. options.cue = false;
  581. oAPopup.dolPopup(options);
  582. };
  583. $.fn.dolPopupConfirm = function(options) {
  584. var oCPopup = $('#bx-popup-confirm');
  585. var sDefMessage = '', sDefBtnYesTitle = '', sDefBtnNoTitle = '';
  586. var oMessage = null;
  587. if(options.message != undefined && options.message.length > 0) {
  588. oMessage = oCPopup.find('.popup_confirm_text');
  589. sDefMessage = oMessage.html();
  590. oMessage.html(options.message);
  591. }
  592. var bParams = options.params != undefined;
  593. var oBtnYes = oCPopup.find('.popup_confirm_yes');
  594. if(bParams && options.params.yes != undefined && options.params.yes.title != undefined && options.params.yes.title.length > 0) {
  595. sDefBtnYesTitle = oBtnYes.html();
  596. oBtnYes.html(options.params.yes.title);
  597. }
  598. var oBtnNo = oCPopup.find('.popup_confirm_no');
  599. if(bParams && options.params.no != undefined && options.params.no.title != undefined && options.params.no.title.length > 0) {
  600. sDefBtnNoTitle = oBtnNo.html();
  601. oBtnNo.html(options.params.no.title);
  602. }
  603. var bFuncYes = options.onClickYes && typeof(options.onClickYes) == 'function';
  604. var bFuncNo = options.onClickNo && typeof(options.onClickNo) == 'function';
  605. if(bFuncYes || bFuncNo)
  606. options.closeOnOuterClick = false;
  607. oBtnYes.bind('click', function(event) {
  608. event.stopPropagation();
  609. if(bFuncYes)
  610. options.onClickYes(oCPopup);
  611. oCPopup.dolPopupHide();
  612. });
  613. oBtnNo.bind('click', function(event) {
  614. event.stopPropagation();
  615. if(bFuncNo)
  616. options.onClickNo(oCPopup);
  617. _dolPopupCue(options, 'close', oCPopup);
  618. oCPopup.dolPopupHide();
  619. });
  620. var fOnShow = options.onShow;
  621. options.onShow = function(oPopup) {
  622. oBtnYes.focus();
  623. if(typeof(fOnShow) == 'function')
  624. fOnShow(oCPopup);
  625. };
  626. var fOnHide = options.onHide;
  627. options.onHide = function(oPopup) {
  628. if(typeof(fOnHide) == 'function')
  629. fOnHide(oCPopup);
  630. /**
  631. * Restore default functions and layout
  632. * if the last one was customized.
  633. */
  634. oCPopup.find('.bx-btn').unbind('click');
  635. if(sDefMessage.length > 0)
  636. oMessage.html(sDefMessage);
  637. if(sDefBtnYesTitle.length > 0)
  638. oBtnYes.html(sDefBtnYesTitle);
  639. if(sDefBtnNoTitle.length > 0)
  640. oBtnNo.html(sDefBtnNoTitle);
  641. };
  642. oCPopup.dolPopup(options);
  643. };
  644. $.fn.dolPopupPrompt = function(options) {
  645. var oPPopup = $('#bx-popup-prompt');
  646. var sDefMessage = '', sDefValue = '', sDefBtnOkTitle = '', sDefBtnCancelTitle = '';
  647. oPPopup.setValue = function(mixedValue) {
  648. return oPPopup.find('[name="bx-popup-prompt-value"]').val(mixedValue);
  649. };
  650. oPPopup.getValue = function() {
  651. return oPPopup.find('[name="bx-popup-prompt-value"]').val();
  652. };
  653. var oMessage = null;
  654. if(options.message != undefined && options.message.length > 0) {
  655. oMessage = oPPopup.find('.popup_prompt_text');
  656. sDefMessage = oMessage.html();
  657. oMessage.html(options.message);
  658. }
  659. if(options.value != undefined && options.value.length > 0) {
  660. sDefValue = oPPopup.getValue();
  661. oPPopup.setValue(options.value);
  662. }
  663. var bParams = options.params != undefined;
  664. var oBtnOk = oPPopup.find('.popup_prompt_ok');
  665. if(bParams && options.params.ok != undefined && options.params.ok.title != undefined && options.params.ok.title.length > 0) {
  666. sDefBtnOkTitle = oBtnOk.html();
  667. oBtnOk.html(options.params.ok.title);
  668. }
  669. var oBtnCancel = oPPopup.find('.popup_prompt_cancel');
  670. if(bParams && options.params.cancel != undefined && options.params.cancel.title != undefined && options.params.cancel.title.length > 0) {
  671. sDefBtnCancelTitle = oBtnCancel.html();
  672. oBtnCancel.html(options.params.cancel.title);
  673. }
  674. var bFuncOk = options.onClickOk && typeof(options.onClickOk) == 'function';
  675. var bFuncCancel = options.onClickCancel && typeof(options.onClickCancel) == 'function';
  676. if(bFuncOk || bFuncCancel)
  677. options.closeOnOuterClick = false;
  678. oBtnOk.bind('click', function() {
  679. if(bFuncOk)
  680. options.onClickOk(oPPopup);
  681. oPPopup.dolPopupHide();
  682. });
  683. oBtnCancel.bind('click', function() {
  684. if(bFuncCancel)
  685. options.onClickCancel(oPPopup);
  686. oPPopup.dolPopupHide();
  687. });
  688. var fOnShow = options.onShow;
  689. options.onShow = function(oPopup) {
  690. oBtnOk.focus();
  691. if(typeof(fOnShow) == 'function')
  692. fOnShow(oPPopup);
  693. };
  694. var fOnHide = options.onHide;
  695. options.onHide = function(oPopup) {
  696. if(typeof(fOnHide) == 'function')
  697. fOnHide(oPPopup);
  698. /**
  699. * Restore default functions and layout
  700. * if the last one was customized.
  701. */
  702. oPPopup.find('.bx-btn').unbind('click');
  703. if(sDefMessage.length > 0)
  704. oMessage.html(sDefMessage);
  705. if(sDefValue.length > 0)
  706. oPPopup.setValue(sDefValue);
  707. else
  708. oPPopup.setValue('');
  709. if(sDefBtnOkTitle.length > 0)
  710. oBtnOk.html(sDefBtnOkTitle);
  711. if(sDefBtnCancelTitle.length > 0)
  712. oBtnCancel.html(sDefBtnCancelTitle);
  713. };
  714. oPPopup.dolPopup(options);
  715. };
  716. $.fn._dolPopupSetPosition = function(options) {
  717. var o = $.extend({}, $.fn.dolPopupDefaultOptions, options);
  718. if (undefined != o.pointer && false != o.pointer)
  719. o.pointer = $.extend({}, $.fn.dolPopupDefaultPointerOptions, $(document).data('bx-popup-options') ? $(document).data('bx-popup-options') : {}, o.pointer);
  720. return this.each(function() {
  721. var $el = $(this);
  722. if (o.pointer != false) {
  723. var yOffset = 8;
  724. var xMargin = 8; // min distance from the window's left and right edges
  725. var ePointAt = typeof o.pointer.el == 'string' ? $(o.pointer.el) : o.pointer.el;
  726. if (!ePointAt)
  727. ePointAt = $('body');
  728. var aOffset = ('' + o.pointer.offset).split(' ', 2);
  729. var aOffsetPointer = ('' + o.pointer.offset_pointer).split(' ', 2);
  730. if (undefined == aOffset[0] || undefined == aOffset[1])
  731. aOffset = [0, 0];
  732. if (undefined == aOffsetPointer[0] || undefined == aOffsetPointer[1])
  733. aOffsetPointer = [0, 0];
  734. var fPosition = function() {
  735. // .position() moves the popup through .offset(), which measures the transformed box,
  736. // so while the show animation scales the popup it would land up and to the left
  737. // of its place: lay it out unscaled until it is placed
  738. var oStyle = $el.get(0).style;
  739. var sTransition = oStyle.transition, sTransform = oStyle.transform;
  740. $el.css({transition: 'none', transform: 'none'});
  741. $el.position({
  742. of: ePointAt,
  743. my: o.pointer.align + '+' + parseInt(aOffset[0]) + ' top+' + yOffset + '+' + parseInt(aOffset[1] - 0),
  744. at: o.pointer.align + ' bottom',
  745. collision: 'fit none'
  746. });
  747. // 'fit' only keeps the popup inside the window, flush with its edge
  748. var iWindowLeft = $(window).scrollLeft();
  749. var iLeftMin = iWindowLeft + xMargin;
  750. var iLeftMax = iWindowLeft + $(window).width() - xMargin - $el.outerWidth();
  751. var iLeft = $el.offset().left;
  752. if (iLeftMin <= iLeftMax && (iLeft < iLeftMin || iLeft > iLeftMax))
  753. $el.offset({left: Math.min(Math.max(iLeft, iLeftMin), iLeftMax)});
  754. $el.find('.bx-popup-box-pointer').css('display', 'block').position({
  755. of: ePointAt,
  756. my: 'center+' + (parseInt(aOffsetPointer[0]) + parseInt(aOffset[0])) + ' top+' + yOffset + '+' + (parseInt(aOffsetPointer[1]) + parseInt(aOffset[1]) + 0),
  757. at: 'center bottom'
  758. });
  759. $el.css({transition: sTransition, transform: sTransform});
  760. };
  761. fPosition();
  762. $(window).on('resize.popupPointer', fPosition);
  763. } else if (o.position == 'fixed' || o.position == 'absolute') {
  764. var bCenterHor = o.left != undefined && o.left == 'center';
  765. var oCss = {
  766. position: o.position,
  767. left: o.left,
  768. top: o.top,
  769. bottom: o.bottom
  770. };
  771. if(!bCenterHor)
  772. oCss.left = o.left;
  773. $el.css(oCss);
  774. if(bCenterHor) {
  775. var fReposition = function(oElement) {
  776. oElement.dolPopupCenterHor();
  777. };
  778. fReposition($el);
  779. // reposition popup when its height is changed
  780. $el.data('bx-popup-height', $el.height());
  781. $el.data('bx-popup-timer', setInterval(function () {
  782. if ($el.height() > $el.data('bx-popup-height')) {
  783. fReposition($el);
  784. $el.data('bx-popup-height', $el.height());
  785. }
  786. }, 500));
  787. // attach window resize event
  788. $(window).on('resize.popupWindow', function() {
  789. fReposition($el);
  790. }).on('scroll', function() {
  791. fReposition($el);
  792. });
  793. }
  794. } else if (o.position == 'centered') {
  795. var oPosition = function(oElement) {
  796. oElement.dolPopupCenter();
  797. };
  798. oPosition($el);
  799. // reposition popup when its height is changed
  800. $el.data('bx-popup-height', $el.height());
  801. $el.data('bx-popup-timer', setInterval(function () {
  802. if ($el.height() > $el.data('bx-popup-height')) {
  803. oPosition($el);
  804. $el.data('bx-popup-height', $el.height());
  805. }
  806. }, 500));
  807. // attach window resize event
  808. $(window).on('resize.popupWindow', function() {
  809. oPosition($el);
  810. }).on('scroll', function() {
  811. oPosition($el);
  812. });
  813. } else if (typeof o.position == 'object') {
  814. $el.position({
  815. of: o.position,
  816. my: 'center top',
  817. at: 'center bottom',
  818. collision: 'flip flip'
  819. });
  820. }
  821. });
  822. };
  823. })(jQuery);
  824. /** @} */