stag-popup.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. window.stagPopupsQueue = [];
  2. function showStagPopup(_key, _noAutoFocus) {
  3. /*$('html, body').addClass('no-scroll');
  4. $(window.top.document.body).find('#stag_mcp_lhs').addClass('no-scroll');*/
  5. let stagPopup = $('[stag-popup-key="' + _key + '"]');
  6. if(stagPopup.is('.show')) return false;
  7. else {
  8. let zIndex = $('.stag-popup.show[stag-popup-key]').last().css('z-index');
  9. if(zIndex) zIndex++; else zIndex = 100;
  10. stagPopup.css('z-index', zIndex);
  11. }
  12. stagPopup.addClass('show');
  13. stagPopup.find('[moe][initialized]').removeAttr('initialized');
  14. initMoes();
  15. initFileInputs();
  16. if(!_noAutoFocus) {
  17. window.setTimeout(function() {
  18. stagPopup.find('input[type="text"]:not([readonly]):visible,select:visible').first().focus();
  19. }, 150);
  20. }
  21. stagPopupsQueue.push(stagPopup);
  22. return false;
  23. }
  24. function submitStagPopup(_form) {
  25. if(!_form[0].checkValidity()) {
  26. _form[0].reportValidity();
  27. return false;
  28. }
  29. showMask();
  30. $.post(_form.attr('action'), _form.serialize(), function(_data) {
  31. stagPopupsQueue = [];
  32. fastReload();
  33. });
  34. return false;
  35. }
  36. function closeStagPopup(_noEvent = false) {
  37. hideMoeFormMask();
  38. if(!stagPopupsQueue.length) return false;
  39. let popup = stagPopupsQueue[stagPopupsQueue.length - 1];
  40. let closeAll = !!popup.attr('close-all-with-self');
  41. popup.removeClass('show');
  42. stagPopupsQueue.splice(stagPopupsQueue.length - 1, 1);
  43. if(closeAll) {
  44. while(stagPopupsQueue.length) {
  45. closeStagPopup(true);
  46. }
  47. }
  48. else {
  49. if(popup.is('[update-parent]') && !_noEvent) {
  50. let hook = popup.attr('update-parent');
  51. if(!!$.trim(hook) && $.trim(hook) !== 'true') {
  52. let hooks = hook.split(',');
  53. for (let i = 0; i < hooks.length; i++) {
  54. hooks[i] = $.trim(hooks[i]);
  55. if(hasMCHook(hooks[i])) {
  56. runMCHook(hooks[i]);
  57. }
  58. }
  59. }
  60. else {
  61. if(stagPopupsQueue.length) {
  62. refreshDynamicStagPopup();
  63. }
  64. else {
  65. fastReload(popup.is('[update-target]') ? popup.attr('update-target') : '');
  66. return false;
  67. }
  68. }
  69. }
  70. }
  71. // remove from the DOM
  72. if(popup.is('.dynamic-popup')) popup.remove();
  73. // if all closed
  74. if(!stagPopupsQueue.length) {
  75. $('html, body').removeClass('no-scroll');
  76. $(window.top.document.body).find('#stag_mcp_lhs').removeClass('no-scroll');
  77. if(!_noEvent) {
  78. $('body').trigger('stag-popup-closed');
  79. }
  80. }
  81. return false;
  82. }
  83. function convertContentLinksForInPopupNavigation(popup) {
  84. popup.find('.stag-popup-content-inner').find('a').each(function() {
  85. let a = $(this);
  86. if(!(!a.attr('href') ||
  87. a.is('[open-in-stag-popup]') ||
  88. a.is('[native]') ||
  89. a.attr('href') === '#' ||
  90. a[0].onclick)) {
  91. a.attr('replace-in-stag-popup', 1);
  92. }
  93. });
  94. }
  95. function openDynamicStagPopup(_url, initer, title, updateParent, style = '', replace = false, updateTarget = null) {
  96. let url = _url;
  97. if(url.indexOf('popupmode') === -1) {
  98. url += (url.indexOf('?') !== -1 ? '&' : '?') + 'popupmode=1';
  99. }
  100. // close out any open inline visit-segment
  101. $('.note-section.visit-segment.edit').removeClass('edit');
  102. showMask();
  103. window.noMc = true;
  104. $.get(url, (_data) => {
  105. let popup = null;
  106. if(replace) {
  107. if(!stagPopupsQueue.length) {
  108. console.error('No stag-popup currently visible!');
  109. return false;
  110. }
  111. popup = stagPopupsQueue[stagPopupsQueue.length - 1];
  112. if(!popup.is('.dynamic-popup')) {
  113. console.error('Topmost stag-popup is not dynamic!');
  114. return false;
  115. }
  116. popup.attr('stag-popup-key', url);
  117. }
  118. else {
  119. popup = $('.dynamic-popup[stag-popup-key="' + url + '"]');
  120. if(!popup.length) {
  121. $('main.stag-content').append(
  122. '<div class="stag-popup ' + (style ? style : 'stag-popup-lg') + ' dynamic-popup draggable resizable mcp-theme-1" stag-popup-key="' + url + '">' +
  123. '<div class="stag-popup-content p-0">' +
  124. '<h3 class="stag-popup-title mb-0 mt-3 mx-3 pb-0 border-bottom-0"><span></span>' +
  125. '<a href="#" class="ml-auto text-secondary" onclick="return closeStagPopup()"><i class="fa fa-times-circle"></i></a>\n' +
  126. '</h3>' +
  127. '<div class="stag-popup-content-inner"></div>' +
  128. '</div>' +
  129. '</div>'
  130. );
  131. popup = $('.dynamic-popup[stag-popup-key="' + url + '"]');
  132. }
  133. }
  134. popup.attr('mc-initer', initer);
  135. popup.find('.stag-popup-title>span').html(title);
  136. popup.find('.stag-popup-content-inner').html(_data);
  137. convertContentLinksForInPopupNavigation(popup);
  138. if(!replace) {
  139. if(updateParent) {
  140. popup.attr('update-parent', updateParent);
  141. }
  142. else {
  143. popup.removeAttr('update-parent');
  144. }
  145. showStagPopup(url, true);
  146. if(updateTarget) {
  147. popup.attr('update-target', updateTarget);
  148. }
  149. }
  150. if(initer) runMCInitializer(initer);
  151. runMCInitializer('pro-suggest'); // not the place for this! Move to better place.
  152. initMoes();
  153. hideMask();
  154. initFileInputs();
  155. }).fail(() => {
  156. toastr.error('Unable to open ' + _url);
  157. hideMask();
  158. });
  159. }
  160. function isDynamicStagPopupPresent() {
  161. if(!stagPopupsQueue.length) return false;
  162. let popup = stagPopupsQueue[stagPopupsQueue.length - 1];
  163. if(popup.is('.dynamic-popup')) return true;
  164. return false;
  165. }
  166. function refreshDynamicStagPopup(_url = false, _target = null) {
  167. if(!stagPopupsQueue.length) return false;
  168. let popup = stagPopupsQueue[stagPopupsQueue.length - 1];
  169. if(popup.is('.dynamic-popup')) {
  170. showMask();
  171. window.noMc = true;
  172. if(_url) {
  173. popup.attr('stag-popup-key', _url);
  174. }
  175. let url = popup.attr('stag-popup-key'),
  176. initer = popup.attr('mc-initer');
  177. $.get(url, (_data) => {
  178. if(_target) {
  179. _data = '<div>' + _data + '</div>';
  180. _target = _target.split(',').map(_x => $.trim(_x));
  181. for (let i = 0; i < _target.length; i++) {
  182. let t = _target[i];
  183. let targetElement = $(t).first();
  184. if(targetElement.length) {
  185. let sourceElement = $(_data).find(t).first();
  186. if (sourceElement && sourceElement.length) {
  187. targetElement.html(sourceElement.html());
  188. initFastLoad(targetElement);
  189. console.log('Replaced ' + t);
  190. }
  191. else {
  192. console.warn(t + ' not found in returned content');
  193. }
  194. }
  195. else {
  196. console.warn(t + ' not found in existing content');
  197. }
  198. }
  199. }
  200. else {
  201. popup.find('.stag-popup-content-inner').html(_data);
  202. }
  203. convertContentLinksForInPopupNavigation(popup);
  204. if(initer) runMCInitializer(initer);
  205. runMCInitializer('pro-suggest');
  206. initMoes();
  207. hideMask();
  208. initFileInputs();
  209. });
  210. }
  211. return false;
  212. }
  213. function hasResponseError(_data) {
  214. let msg = 'Unknown error!';
  215. if (_data) {
  216. if (_data.success) return false;
  217. else if (_data.message) msg = _data.message;
  218. }
  219. toastr.error(msg);
  220. return true;
  221. }
  222. (function() {
  223. window.initStagPopupEvents = function () {
  224. $(document)
  225. .off('mousedown.stag-popup-discard', '.stag-popup')
  226. .on('mousedown.stag-popup-discard', '.stag-popup', function(_e) {
  227. if($(_e.target).is('.stag-popup') && !isEventConsumed(_e)) {
  228. closeStagPopup();
  229. return false;
  230. }
  231. });
  232. // catch ESC and discard any visible popups
  233. $(document)
  234. .off('keydown.stag-popup-escape')
  235. .on('keydown.stag-popup-escape', function (e) {
  236. if(e.which === 27) {
  237. if(!isEventConsumed(e)) {
  238. if(stagPopupsQueue.length) {
  239. if($('.stag-popup.show [moe] [url]:not([show]):visible').length || $('.stag-popup.show [visit-moe] [url]:not([show]):visible').length) {
  240. return;
  241. }
  242. closeStagPopup();
  243. markEventAsConsumed(e);
  244. return false;
  245. }
  246. }
  247. }
  248. });
  249. $(document)
  250. .off('click.open-in-stag-popup', '[open-in-stag-popup]')
  251. .on('click.open-in-stag-popup', '[open-in-stag-popup]', function() {
  252. let trig = $(this);
  253. let updateParent = trig.is('[update-parent]');
  254. if(updateParent) {
  255. if(!!$.trim(trig.attr('update-parent'))) {
  256. updateParent = trig.attr('update-parent');
  257. }
  258. else {
  259. updateParent = true;
  260. }
  261. }
  262. openDynamicStagPopup(
  263. trig.attr('href'),
  264. trig.attr('mc-initer'),
  265. trig.attr('title'),
  266. updateParent,
  267. trig.attr('popup-style'),
  268. false,
  269. trig.is('[update-target]') ? trig.attr('update-target') : null
  270. );
  271. return false;
  272. });
  273. $(document)
  274. .off('click.replace-in-stag-popup', '[replace-in-stag-popup]')
  275. .on('click.replace-in-stag-popup', '[replace-in-stag-popup]', function() {
  276. let trig = $(this);
  277. openDynamicStagPopup(
  278. trig.attr('href'),
  279. trig.attr('mc-initer'),
  280. trig.attr('title'),
  281. null, // will be inherited when replacing
  282. null, // will be inherited when replacing
  283. true,
  284. null
  285. );
  286. return false;
  287. });
  288. $(document)
  289. .off('click.close-stag-popup', '.btn-close-stag-popup')
  290. .on('click.close-stag-popup', '.btn-close-stag-popup', function() {
  291. closeStagPopup();
  292. return false;
  293. });
  294. // draggable
  295. let dragging = false, dragX, dragY;
  296. $(document)
  297. .off('mousedown.start-drag', '.stag-popup.dynamic-popup.draggable .stag-popup-title')
  298. .on('mousedown.start-drag', '.stag-popup.dynamic-popup.draggable .stag-popup-title', function(_e) {
  299. if(_e.which !== 1) return;
  300. if(dragging && dragging.length) {
  301. dragging = false;
  302. }
  303. dragging = $(this).closest('.stag-popup-content');
  304. dragX = _e.screenX;
  305. dragY = _e.screenY;
  306. });
  307. $(document)
  308. .off('mousemove.drag')
  309. .on('mousemove.drag', function(_e) {
  310. if(dragging && dragging.length) {
  311. let targetX = dragging.position().left + (_e.screenX - dragX),
  312. targetY = dragging.position().top + (_e.screenY - dragY);
  313. if(targetX >= 0) dragX = _e.screenX;
  314. if(targetY >= 0) dragY = _e.screenY;
  315. if(targetX < 0) targetX = 0;
  316. if(targetY < 0) targetY = 0;
  317. dragging[0].style.left = targetX + 'px';
  318. dragging[0].style.top = targetY + 'px';
  319. dragging[0].style.transform = 'none';
  320. return false;
  321. }
  322. });
  323. // resizable
  324. let resizeHighlighting = false, resizeDirection = false, resizeAnchor = false, resizing = false, resizeGutter = 8, resizeX, resizeY;
  325. $(document)
  326. .off('mousemove.highlight-resize', '.stag-popup.dynamic-popup.resizable .stag-popup-content')
  327. .on('mousemove.highlight-resize', '.stag-popup.dynamic-popup.resizable .stag-popup-content', function(_e) {
  328. if(dragging && dragging.length) return;
  329. if(resizing && resizing.length) return;
  330. let mouseX = _e.pageX - $(this).offset().left,
  331. mouseY = _e.pageY - $(this).offset().top;
  332. if((mouseX >= 0 && mouseX <= resizeGutter) || (mouseX >= $(this).outerWidth() - resizeGutter && mouseX <= $(this).outerWidth())) {
  333. $(this).addClass('resizing-x');
  334. resizeHighlighting = $(this);
  335. resizeDirection = 'x';
  336. resizeAnchor = (mouseX >= 0 && mouseX <= resizeGutter) ? 'left' : 'right';
  337. }
  338. else if((mouseY >= 0 && mouseY <= resizeGutter) || (mouseY >= $(this).outerHeight() - resizeGutter && mouseY <= $(this).outerHeight())) {
  339. $(this).addClass('resizing-y');
  340. resizeHighlighting = $(this);
  341. resizeDirection = 'y';
  342. resizeAnchor = (mouseY >= 0 && mouseY <= resizeGutter) ? 'top' : 'bottom';
  343. }
  344. else {
  345. $(this).removeClass('resizing-x');
  346. $(this).removeClass('resizing-y');
  347. resizeHighlighting = false;
  348. }
  349. });
  350. $(document)
  351. .off('mousedown.start-resize', '.stag-popup.dynamic-popup.resizable .stag-popup-content')
  352. .on('mousedown.start-resize', '.stag-popup.dynamic-popup.resizable .stag-popup-content', function(_e) {
  353. if(_e.which !== 1) return;
  354. if(resizeHighlighting && resizeHighlighting.length) {
  355. if(resizing && resizing.length) {
  356. resizing.removeClass('resizing-x resizing-y');
  357. resizing = false;
  358. }
  359. resizing = $(this);
  360. resizeX = _e.screenX;
  361. resizeY = _e.screenY;
  362. }
  363. });
  364. $(document)
  365. .off('mousemove.resize')
  366. .on('mousemove.resize', function(_e) {
  367. if(resizing && resizing.length) {
  368. console.log(resizeDirection);
  369. console.log(resizeAnchor);
  370. // x
  371. if(resizeDirection === 'x') {
  372. let deltaX = _e.screenX - resizeX;
  373. // anchor: left => update left and width of the popup
  374. if(resizeAnchor === 'left') {
  375. resizing[0].style.left = resizing.position().left + deltaX + 'px';
  376. resizing[0].style.width = resizing.outerWidth() - deltaX + 'px';
  377. resizing[0].style.transform = 'none';
  378. }
  379. // anchor: right => update width of the popup
  380. else if(resizeAnchor === 'right') {
  381. resizing[0].style.left = resizing.position().left + 'px'
  382. resizing[0].style.width = resizing.outerWidth() + deltaX + 'px';
  383. resizing[0].style.transform = 'none';
  384. }
  385. }
  386. // x
  387. if(resizeDirection === 'y') {
  388. let deltaY = _e.screenY - resizeY;
  389. // anchor: top => update top and height of the popup
  390. if(resizeAnchor === 'top') {
  391. resizing[0].style.top = resizing.position().top + deltaY + 'px';
  392. resizing[0].style.height = resizing.outerHeight() - deltaY + 'px';
  393. }
  394. // anchor: bottom => update height of the popup
  395. else if(resizeAnchor === 'bottom') {
  396. resizing[0].style.height = resizing.outerHeight() + deltaY + 'px';
  397. }
  398. }
  399. resizeX = _e.screenX;
  400. resizeY = _e.screenY;
  401. return false;
  402. }
  403. });
  404. $(document)
  405. .off('mouseleave.stop-resize', '.stag-popup.dynamic-popup.resizable .stag-popup-content')
  406. .on('mouseleave.stop-resize', '.stag-popup.dynamic-popup.resizable .stag-popup-content', function(_e) {
  407. if(resizing && resizing.length) return;
  408. if(resizeHighlighting && resizeHighlighting.length) {
  409. resizeHighlighting.removeClass('resizing-x resizing-y');
  410. resizeHighlighting = false;
  411. return false;
  412. }
  413. });
  414. // common
  415. $(document)
  416. .off('mouseleave.stop-drag-resize')
  417. .on('mouseleave.stop-drag-resize', function() {
  418. if(dragging && dragging.length) {
  419. dragging = false;
  420. }
  421. if(resizeHighlighting && resizeHighlighting.length) {
  422. resizeHighlighting.removeClass('resizing-x resizing-y');
  423. resizeHighlighting = false;
  424. }
  425. if(resizing && resizing.length) {
  426. resizing.removeClass('resizing-x resizing-y');
  427. resizing = false;
  428. }
  429. });
  430. $(document)
  431. .off('mouseup.stop-drag-resize')
  432. .on('mouseup.stop-drag-resize', function() {
  433. if(dragging && dragging.length) {
  434. dragging = false;
  435. }
  436. if(resizeHighlighting && resizeHighlighting.length) {
  437. resizeHighlighting.removeClass('resizing-x resizing-y');
  438. resizeHighlighting = false;
  439. }
  440. if(resizing && resizing.length) {
  441. resizing.removeClass('resizing-x resizing-y');
  442. resizing = false;
  443. }
  444. });
  445. }
  446. addMCInitializer('stag-popups', window.initStagPopupEvents);
  447. })();