app.bundle.js 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903
  1. //--------------------------------------------------------------------------
  2. // HEADSUP!
  3. // Please be sure to re-run gulp again if you do not see the config changes
  4. //--------------------------------------------------------------------------
  5. var myapp_config = {
  6. /*
  7. APP VERSION
  8. */
  9. VERSION: '4.0.2',
  10. /*
  11. SAVE INSTANCE REFERENCE
  12. Save a reference to the global object (window in the browser)
  13. */
  14. root_: $('body'), // used for core app reference
  15. root_logo: $('.page-sidebar > .page-logo'), // used for core app reference
  16. /*
  17. DELAY VAR FOR FIRING REPEATED EVENTS (eg., scroll & resize events)
  18. Lowering the variable makes faster response time but taxing on the CPU
  19. Reference: http://benalman.com/code/projects/jquery-throttle-debounce/examples/throttle/
  20. */
  21. throttleDelay: 450, // for window.scrolling & window.resizing
  22. filterDelay: 150, // for keyup.functions
  23. /*
  24. DETECT MOBILE DEVICES
  25. Description: Detects mobile device - if any of the listed device is
  26. detected a class is inserted to $.root_ and the variable thisDevice
  27. is decleard. (so far this is covering most hand held devices)
  28. */
  29. thisDevice: null, // desktop or mobile
  30. isMobile: (/iphone|ipad|ipod|android|blackberry|mini|windows\sce|palm/i.test(navigator.userAgent.toLowerCase())), //popular device types available on the market
  31. mobileMenuTrigger: null, // used by pagescrolling and appHeight script, do not change!
  32. mobileResolutionTrigger: 992, //the resolution when the mobile activation fires
  33. /*
  34. DETECT IF WEBKIT
  35. Description: this variable is used to fire the custom scroll plugin.
  36. If it is a non-webkit it will fire the plugin.
  37. */
  38. isWebkit: ((!!window.chrome && !!window.chrome.webstore) === true || Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0 === true),
  39. /*
  40. DETECT CHROME
  41. Description: this variable is used to fire the custom CSS hacks
  42. */
  43. isChrome: (/chrom(e|ium)/.test(navigator.userAgent.toLowerCase())),
  44. /*
  45. DETECT IE (it only detects the newer versions of IE)
  46. Description: this variable is used to fire the custom CSS hacks
  47. */
  48. isIE: ( (window.navigator.userAgent.indexOf('Trident/') ) > 0 === true ),
  49. /*
  50. DEBUGGING MODE
  51. debugState = true; will spit all debuging message inside browser console.
  52. */
  53. debugState: false, // outputs debug information on browser console
  54. /*
  55. Turn on ripple effect for buttons and touch events
  56. Dependency:
  57. */
  58. rippleEffect: true, // material design effect that appears on all buttons
  59. /*
  60. Primary theme anchor point ID
  61. This anchor is created dynamically and CSS is loaded as an override theme
  62. */
  63. mythemeAnchor: '#mytheme',
  64. /*
  65. Primary menu anchor point #js-primary-nav
  66. This is the root anchor point where the menu script will begin its build
  67. */
  68. navAnchor: $('#js-primary-nav'), //changing this may implicate slimscroll plugin target
  69. navHooks: $('#js-nav-menu'), //changing this may implicate CSS targets
  70. navAccordion: true, //nav item when one is expanded the other closes
  71. navInitalized: 'js-nav-built', //nav finished class
  72. navFilterInput: $('#nav_filter_input'), //changing this may implicate CSS targets
  73. navHorizontalWrapperId: 'js-nav-menu-wrapper',
  74. /*
  75. The rate at which the menu expands revealing child elements on click
  76. Lower rate reels faster expansion of nav childs
  77. */
  78. navSpeed: 500, //ms
  79. /*
  80. Color profile reference hook (needed for getting CSS value for theme colors in charts and various graphs)
  81. */
  82. mythemeColorProfileID: $('#js-color-profile'),
  83. /*
  84. Nav close and open signs
  85. This uses the fontawesome css class
  86. */
  87. navClosedSign: 'fal fa-angle-down',
  88. navOpenedSign: 'fal fa-angle-up',
  89. /*
  90. App date ID
  91. found inside the breadcrumb unit, displays current date to the app on pageload
  92. */
  93. appDateHook: $('.js-get-date'),
  94. /*
  95. * SaveSettings to localStorage
  96. * DOC: to store settings to a DB instead of LocalStorage see below:
  97. * initApp.pushSettings("className1 className2") //sets value
  98. * var DB_string = initApp.getSettings(); //returns setting string
  99. */
  100. storeLocally: true,
  101. /*
  102. * Used with initApp.loadScripts
  103. * DOC: Please leave it blank
  104. */
  105. jsArray : []
  106. };
  107. /*!
  108. * jQuery app.navigation v1.0.0
  109. *
  110. * Copyright 2019, 2020 SmartAdmin WebApp
  111. * Released under Marketplace License (see your license details for usage)
  112. *
  113. * Publish Date: 2018-01-01T17:42Z
  114. */
  115. (function($) {
  116. /**
  117. * Menu Plugin
  118. **/
  119. $.fn.extend({
  120. /**
  121. * pass the options variable to the function
  122. *
  123. * $(id).navigation({
  124. * accordion: true,
  125. * animate: 'easeOutExpo',
  126. * speed: 200,
  127. * closedSign: '[+]',
  128. * openedSign: '[-]',
  129. * initClass: 'js-nav-built'
  130. * });
  131. *
  132. **/
  133. navigation: function(options) {
  134. var defaults = {
  135. accordion: true,
  136. animate: 'easeOutExpo',
  137. speed: 200,
  138. closedSign: '[+]',
  139. openedSign: '[-]',
  140. initClass: 'js-nav-built'
  141. },
  142. /**
  143. * extend our default options with those provided.
  144. **/
  145. opts = $.extend(defaults, options),
  146. /**
  147. * assign current element to variable, in this case is UL element
  148. **/
  149. self = $(this);
  150. if (!self.hasClass(opts.initClass)) {
  151. /**
  152. * confirm build to prevent rebuild error
  153. **/
  154. self.addClass(opts.initClass);
  155. /**
  156. * add a mark [+] to a multilevel menu
  157. **/
  158. self.find("li").each(function() {
  159. if ($(this).find("ul").length !== 0) {
  160. /**
  161. * add the multilevel sign next to the link
  162. **/
  163. $(this).find("a:first").append("<b class='collapse-sign'>" + opts.closedSign + "</b>");
  164. /**
  165. * avoid jumping to the top of the page when the href is an #
  166. **/
  167. if ($(this).find("a:first").attr('href') == "#") {
  168. $(this).find("a:first").click(function() {
  169. return false;
  170. });
  171. }
  172. }
  173. });
  174. /**
  175. * add open sign to all active lists
  176. **/
  177. self.find("li.active").each(function() {
  178. $(this).parents("ul")
  179. .parent("li")
  180. .find("a:first")
  181. .attr('aria-expanded', true)
  182. .find("b:first")
  183. .html(opts.openedSign);
  184. });
  185. /**
  186. * click events
  187. **/
  188. self.find("li a").on('mousedown', function(e) {
  189. if ($(this).parent().find("ul").length !== 0) {
  190. if (opts.accordion) {
  191. /**
  192. * do nothing when the list is open
  193. **/
  194. if (!$(this).parent().find("ul").is(':visible')) {
  195. parents = $(this).parent().parents("ul");
  196. visible = self.find("ul:visible");
  197. visible.each(function(visibleIndex) {
  198. var close = true;
  199. parents.each(function(parentIndex) {
  200. if (parents[parentIndex] == visible[visibleIndex]) {
  201. close = false;
  202. return false;
  203. }
  204. });
  205. if (close) {
  206. if ($(this).parent().find("ul") != visible[visibleIndex]) {
  207. $(visible[visibleIndex]).slideUp(opts.speed + 300, opts.animate, function() {
  208. $(this).parent("li")
  209. .removeClass("open")
  210. .find("a:first")
  211. .attr('aria-expanded', false)
  212. .find("b:first")
  213. .html(opts.closedSign);
  214. if (myapp_config.debugState)
  215. console.log("nav item closed")
  216. });
  217. }
  218. }
  219. });
  220. }
  221. }
  222. /**
  223. * Add active class to open element
  224. **/
  225. if ($(this).parent().find("ul:first").is(":visible") && !$(this).parent().find("ul:first").hasClass("active")) {
  226. $(this).parent().find("ul:first").slideUp(opts.speed + 100, opts.animate, function() {
  227. $(this).parent("li")
  228. .removeClass("open")
  229. .find("a:first")
  230. .attr('aria-expanded', false)
  231. .find("b:first").delay(opts.speed)
  232. .html(opts.closedSign);
  233. if (myapp_config.debugState)
  234. console.log("nav item closed")
  235. });
  236. } else {
  237. $(this).parent().find("ul:first").slideDown(opts.speed, opts.animate, function() {
  238. $(this).parent("li")
  239. .addClass("open")
  240. .find("a:first")
  241. .attr('aria-expanded', true)
  242. .find("b:first").delay(opts.speed)
  243. .html(opts.openedSign);
  244. if (myapp_config.debugState)
  245. console.log("nav item opened");
  246. });
  247. }
  248. }
  249. });
  250. } else {
  251. if (myapp_config.debugState)
  252. console.log(self.get(0) + " this menu already exists");
  253. }
  254. },
  255. /**
  256. * DOC: $(id).destroy();
  257. **/
  258. navigationDestroy: function() {
  259. self = $(this);
  260. if (self.hasClass(myapp_config.navInitalized)) {
  261. self.find("li").removeClass("active open");
  262. self.find("li a").off('mousedown').removeClass("active").removeAttr("aria-expanded").find(".collapse-sign").remove();
  263. self.removeClass(myapp_config.navInitalized).find("ul").removeAttr("style");
  264. if (myapp_config.debugState)
  265. console.log( self.get(0) + " destroyed");
  266. } else {
  267. console.log("menu does not exist")
  268. }
  269. }
  270. });
  271. })(jQuery, window, document);
  272. /*!
  273. * jQuery menuSlider v1.0.0
  274. *
  275. * Copyright 2019, 2020 SmartAdmin WebApp
  276. * Released under Marketplace License (see your license details for usage)
  277. *
  278. * Publish Date: 2019-01-01T17:42Z
  279. */
  280. ;
  281. (function($) {
  282. var pluginName = 'menuSlider';
  283. function Plugin(element, options) {
  284. var $el = $(element),
  285. el = element;
  286. options = $.extend({}, $.fn[pluginName].defaults, options);
  287. function init() {
  288. /* reset margin */
  289. $el.css('margin-left', '0px');
  290. /* add wrapper around navigation */
  291. $el.wrap( '<div id="'+options.wrapperId+'" class="nav-menu-wrapper d-flex flex-grow-1 width-0 overflow-hidden"></div>' );
  292. /* add buttons for scroller */
  293. $('#' + options.wrapperId).before('<a href="#" id="' + options.wrapperId + '-left-btn" class="d-flex align-items-center justify-content-center width-4 btn mt-1 mb-1 mr-2 ml-1 p-0 fs-xxl text-primary"><i class="fal fa-angle-left"></i></a>');
  294. $('#' + options.wrapperId).after('<a href="#" id="' + options.wrapperId + '-right-btn" class="d-flex align-items-center justify-content-center width-4 btn mt-1 mb-1 mr-1 ml-2 p-0 fs-xxl text-primary"><i class="fal fa-angle-right"></i></a>');
  295. var getListWidth = $.map($el.children('li:not(.nav-title)'),function(val){ return $(val).outerWidth(true);}),
  296. /* define variables */
  297. wrapperWidth,
  298. currentMarginLeft,
  299. contentWidth,
  300. setMargin,
  301. maxMargin,
  302. /* update variables for margin calculations */
  303. _getValues = function() {
  304. wrapperWidth = $('#' + options.wrapperId).outerWidth(); /* incase its changed we get it again */
  305. contentWidth = $.map( $el.children('li:not(.nav-title)'), function(val){ return $(val).outerWidth(true); }).reduce(function(a, b) { return a + b; }, 0);
  306. currentMarginLeft = parseFloat($el.css('margin-left'));
  307. /*console.log("got new values");
  308. console.log("wrapperWidth :" + wrapperWidth);
  309. console.log("contentWidth :" + contentWidth);
  310. console.log("currentMarginLeft :" + currentMarginLeft);*/
  311. },
  312. /* scroll right */
  313. navMenuScrollRight = function() {
  314. _getValues();
  315. if (-currentMarginLeft + wrapperWidth < contentWidth) {
  316. setMargin = Math.max(currentMarginLeft - wrapperWidth, -(contentWidth - wrapperWidth) );
  317. } else {
  318. setMargin = currentMarginLeft;
  319. console.log("right end");
  320. }
  321. $el.css({
  322. marginLeft: setMargin
  323. });
  324. },
  325. /* scroll left */
  326. navMenuScrollLeft = function() {
  327. _getValues();
  328. if (currentMarginLeft < 0) {
  329. setMargin = Math.min(currentMarginLeft + wrapperWidth, 0);
  330. } else {
  331. setMargin = currentMarginLeft;
  332. console.log("left end");
  333. }
  334. $el.css({
  335. marginLeft: setMargin
  336. });
  337. };
  338. /* assign buttons for right*/
  339. $('#' + options.wrapperId + '-left-btn').click(function(e) {
  340. navMenuScrollLeft();
  341. e.preventDefault();
  342. });
  343. /* assign buttons for left */
  344. $('#' + options.wrapperId + '-right-btn').click(function(e) {
  345. navMenuScrollRight();
  346. e.preventDefault();
  347. });
  348. hook('onInit');
  349. }
  350. function option(key, val) {
  351. if (val) {
  352. options[key] = val;
  353. } else {
  354. return options[key];
  355. }
  356. }
  357. function destroy(options) {
  358. $el.each(function() {
  359. var el = this;
  360. var $el = $(this);
  361. // Add code to restore the element to its original state...
  362. $el.css('margin-left', '0px');
  363. $el.unwrap(parent);
  364. $el.prev().off().remove();
  365. $el.next().off().remove();
  366. hook('onDestroy');
  367. $el.removeData('plugin_' + pluginName);
  368. });
  369. }
  370. function hook(hookName) {
  371. if (options[hookName] !== undefined) {
  372. options[hookName].call(el);
  373. }
  374. }
  375. init();
  376. return {
  377. option: option,
  378. destroy: destroy
  379. };
  380. }
  381. $.fn[pluginName] = function(options) {
  382. if (typeof arguments[0] === 'string') {
  383. var methodName = arguments[0];
  384. var args = Array.prototype.slice.call(arguments, 1);
  385. var returnVal;
  386. this.each(function() {
  387. if ($.data(this, 'plugin_' + pluginName) && typeof $.data(this, 'plugin_' + pluginName)[methodName] === 'function') {
  388. returnVal = $.data(this, 'plugin_' + pluginName)[methodName].apply(this, args);
  389. } else {
  390. throw new Error('Method ' + methodName + ' does not exist on jQuery.' + pluginName);
  391. }
  392. });
  393. if (returnVal !== undefined) {
  394. return returnVal;
  395. } else {
  396. return this;
  397. }
  398. } else if (typeof options === "object" || !options) {
  399. return this.each(function() {
  400. if (!$.data(this, 'plugin_' + pluginName)) {
  401. $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
  402. }
  403. });
  404. }
  405. };
  406. $.fn[pluginName].defaults = {
  407. onInit: function() {},
  408. onDestroy: function() {},
  409. element: myapp_config.navHooks,
  410. wrapperId: myapp_config.navHorizontalWrapperId
  411. };
  412. })(jQuery);
  413. /*!
  414. * jQuery SmartAdmin v4.0.0
  415. *
  416. * Copyright 2019, 2020 SmartAdmin WebApp
  417. * Released under Marketplace License (see your license details for usage)
  418. *
  419. * Publish Date: 2019-01-01T17:42Z
  420. */
  421. var initApp = (function(app) {
  422. /**
  423. * List filter
  424. * DOC: searches list items, it could be UL or DIV elements
  425. * usage: initApp.listFilter($('.list'), $('#intput-id'));
  426. * inside the .list you will need to insert 'data-filter-tags' inside <a>
  427. * @param list
  428. * @param input
  429. * @param anchor
  430. * @return
  431. */
  432. app.listFilter = function (list, input, anchor) {
  433. /* add class to filter hide/show */
  434. if (anchor) {
  435. $(anchor).addClass('js-list-filter');
  436. } else {
  437. $(list).addClass('js-list-filter');
  438. }
  439. /* on change keyboard */
  440. $(input).change( function () {
  441. var filter = $(this).val().toLowerCase(),
  442. listPrev = $(list).next().filter('.js-filter-message');
  443. /* when user types more than 1 letter start search filter */
  444. if(filter.length > 1) {
  445. /* this finds all data-filter-tags in a list that contain the input val,
  446. hiding the ones not containing the input while showing the ones that do */
  447. /* (1) hide all that does not match */
  448. $(list).find($("[data-filter-tags]:not([data-filter-tags*='" + filter + "'])"))
  449. .parentsUntil(list).removeClass('js-filter-show')
  450. .addClass('js-filter-hide');
  451. /* (2) hide all that does match */
  452. $(list).find($("[data-filter-tags*='" + filter + "']"))
  453. .parentsUntil(list).removeClass('js-filter-hide')
  454. .addClass('js-filter-show');
  455. /* if element exists then print results */
  456. if (listPrev){
  457. listPrev.text("showing " + $(list).find('li.js-filter-show').length + " from " + $(list).find('[data-filter-tags]').length + " total");
  458. }
  459. } else {
  460. /* when filter length is blank reset the classes */
  461. $(list).find('[data-filter-tags]').parentsUntil(list).removeClass('js-filter-hide js-filter-show');
  462. /* if element exists reset print results */
  463. if (listPrev){
  464. listPrev.text("");
  465. }
  466. }
  467. return false;
  468. }).keyup( $.debounce( myapp_config.filterDelay, function (e) {
  469. /* fire the above change event after every letter is typed with a delay of 250ms */
  470. $(this).change();
  471. /*if(e.keyCode == 13) {
  472. console.log( $(list).find(".filter-show:not(.filter-hide) > a") );
  473. }*/
  474. }));
  475. };
  476. /**
  477. * Load scripts using lazyload method
  478. * usage: initApp.loadScript("js/my_lovely_script.js", myFunction);
  479. * @param {[type]} scriptName
  480. * @param {Function} callback
  481. * @return {[type]}
  482. */
  483. app.loadScript = function (scriptName, callback) {
  484. if (!myapp_config.jsArray[scriptName]) {
  485. var promise = jQuery.Deferred();
  486. /* adding the script tag to the head as suggested before */
  487. var body = document.getElementsByTagName('body')[0],
  488. script = document.createElement('script');
  489. script.type = 'text/javascript';
  490. script.src = scriptName;
  491. /* then bind the event to the callback function
  492. there are several events for cross browser compatibility */
  493. script.onload = function() {
  494. promise.resolve();
  495. };
  496. /* fire the loading */
  497. body.appendChild(script);
  498. myapp_config.jsArray[scriptName] = promise.promise();
  499. }
  500. else if (myapp_config.debugState)
  501. console.log("This script was already loaded: " + scriptName);
  502. myapp_config.jsArray[scriptName].then(function () {
  503. if(typeof callback === 'function') {
  504. callback();
  505. }
  506. });
  507. };
  508. /**
  509. * Javascript Animation for save settings
  510. * @return
  511. **/
  512. app.saveSettings = function () {
  513. /* if saveSettings function exists */
  514. if (typeof saveSettings !== 'undefined' && $.isFunction(saveSettings) && myapp_config.storeLocally) {
  515. /* call accessIndicator animation */
  516. initApp.accessIndicator();
  517. /* call saveSettings function from myapp_config.root_ (HTML) */
  518. saveSettings();
  519. if (myapp_config.debugState)
  520. console.log('Theme settings: ' + '\n' +localStorage.getItem('themeSettings'));
  521. } else {
  522. console.log("save function does not exist");
  523. }
  524. };
  525. /**
  526. * Reset settings
  527. * DOC: removes all classes from root_ then saves
  528. * @return {[type]}
  529. **/
  530. app.resetSettings = function () {
  531. /* remove all setting classes nav|header|mod|display */
  532. myapp_config.root_.removeClass (function (index, className) {
  533. return (className.match (/(^|\s)(nav-|header-|mod-|display-)\S+/g) || []).join(' ');
  534. });
  535. /* detach custom css skin */
  536. $(myapp_config.mythemeAnchor).attr('href', "");
  537. /* check non-conflicting plugins */
  538. initApp.checkNavigationOrientation();
  539. /* save settings if "storeLocally == true" */
  540. initApp.saveSettings();
  541. if (myapp_config.debugState)
  542. console.log("App reset successful");
  543. };
  544. /**
  545. * Factory Reset
  546. * DOC: Resets all of localstorage
  547. * @return {[type]}
  548. **/
  549. app.factoryReset = function () {
  550. //backdrop sound
  551. initApp.playSound('media/sound', 'messagebox');
  552. //hide settings modal to bootstrap avoid modal bug
  553. $('.js-modal-settings').modal('hide');
  554. if (typeof bootbox != 'undefined') {
  555. bootbox.confirm({
  556. title: "<i class='fal fa-exclamation-triangle text-warning mr-2'></i> You are about to reset all of your localStorage settings",
  557. message: "<span><strong>Warning:</strong> This action is not reversable. You will lose all your layout settings.</span>",
  558. centerVertical: true,
  559. swapButtonOrder: true,
  560. buttons: {
  561. confirm: {
  562. label: 'Factory Reset',
  563. className: 'btn-warning shadow-0'
  564. },
  565. cancel: {
  566. label: 'Cancel',
  567. className: 'btn-success'
  568. }
  569. },
  570. className: "modal-alert",
  571. closeButton: false,
  572. callback: function (result) {
  573. if (result == true) {
  574. //close panel
  575. localStorage.clear();
  576. initApp.resetSettings();
  577. location.reload();
  578. }
  579. }
  580. });
  581. } else {
  582. if (confirm( 'You are about to reset all of your localStorage to null state. Do you wish to continue?' )) {
  583. localStorage.clear();
  584. initApp.resetSettings();
  585. location.reload();
  586. }
  587. }
  588. //e.preventDefault();
  589. if (myapp_config.debugState)
  590. console.log("App reset successful");
  591. };
  592. /**
  593. * Access Indicator
  594. * DOC: spinning icon that appears whenever you
  595. * access localstorage or change settings
  596. * @return {[type]}
  597. **/
  598. app.accessIndicator = function () {
  599. myapp_config.root_.addClass('saving').delay(600).queue(function(){
  600. $(this).removeClass('saving').dequeue();
  601. return true;
  602. });
  603. };
  604. /*
  605. * usage: initApp.pushSettings("className1 className2")
  606. * save settings to localstorage: initApp.pushSettings("className1 className2", true)
  607. * DOC: pushSettings will also auto save to localStorage if "storeLocally == true"
  608. * we will use this "pushSettings" when loading settings from a database
  609. * @param {[type]} DB_string
  610. * @param {[type]} saveToLocal
  611. * @return {[type]}
  612. */
  613. app.pushSettings = function (DB_string, saveToLocal) {
  614. /* clear localstorage variable 'themeSettings' */
  615. if (saveToLocal != false)
  616. localStorage.setItem("themeSettings", "");
  617. /* replace classes from <body> with fetched DB string */
  618. myapp_config.root_.addClass(DB_string); //ommited .removeClass()
  619. /* destroy or enable slimscroll */
  620. initApp.checkNavigationOrientation();
  621. /* save settings if "storeLocally == true" && "saveToLocal is true" */
  622. if (saveToLocal != false)
  623. initApp.saveSettings();
  624. /* return string */
  625. return DB_string;
  626. };
  627. /*
  628. * usage: var DB_string = initApp.getSettings();
  629. * we will use this "getSettings" when storing settings to a database
  630. * @return {[type]}
  631. */
  632. app.getSettings = function () {
  633. return myapp_config.root_.attr('class').split(/[^\w-]+/).filter(function(item) {
  634. return /^(nav|header|mod|display)-/i.test(item);
  635. }).join(' ');
  636. };
  637. /*
  638. * Play Sounds
  639. * usage: initApp.playSound(path, sound);
  640. * @param {[string]} path
  641. * @param {[string]} sound
  642. */
  643. app.playSound = function(path, sound) {
  644. var audioElement = document.createElement('audio');
  645. if (navigator.userAgent.match('Firefox/'))
  646. audioElement.setAttribute('src', path + "/" + sound + '.ogg');
  647. else
  648. audioElement.setAttribute('src', path + "/" + sound + '.mp3');
  649. //$.get();// <-- ??
  650. audioElement.addEventListener("load", function () {
  651. audioElement.play();
  652. }, true);
  653. audioElement.pause();
  654. audioElement.play();
  655. }
  656. /*
  657. * Checks and sets active settings selections
  658. * DOC: ?
  659. */
  660. /*app.indicateSelections = function () {
  661. var classNames = initApp.getSettings()
  662. .split(' ')
  663. .map(function(c) {
  664. return '[data-class="' + c + '"].js-indicateSelections';
  665. })
  666. .join(',');
  667. $('[data-class].active.js-indicateSelections').removeClass('active');
  668. $(classNames).addClass('active');
  669. if (myapp_config.debugState)
  670. console.log(classNames);
  671. }*/
  672. /**
  673. * detect browser type
  674. * DOC: detect if browser supports webkit CSS
  675. * @return {[type]}
  676. **/
  677. app.detectBrowserType = function () {
  678. /* safari, chrome or IE detect */
  679. if(myapp_config.isChrome){
  680. myapp_config.root_.addClass('chrome webkit');
  681. return 'chrome webkit';
  682. } else if (myapp_config.isWebkit) {
  683. myapp_config.root_.addClass('webkit');
  684. return 'webkit';
  685. } else if (myapp_config.isIE) {
  686. myapp_config.root_.addClass('ie');
  687. return 'ie';
  688. }
  689. };
  690. /**
  691. * Add device type
  692. * DOC: Detect if mobile or desktop
  693. **/
  694. app.addDeviceType = function() {
  695. if (!myapp_config.isMobile) {
  696. /* desktop */
  697. myapp_config.root_.addClass('desktop');
  698. myapp_config.thisDevice = 'desktop';
  699. } else {
  700. /* mobile */
  701. myapp_config.root_.addClass('mobile');
  702. myapp_config.thisDevice = 'mobile';
  703. }
  704. return myapp_config.thisDevice;
  705. };
  706. /**
  707. * Fix logo position on .header-function-fixed & .nav-function-hidden
  708. * DOC: Counters browser bug for fixed position and overflow:hidden for the logo (firefox/IE/Safari)
  709. * Will not fire for webkit devices or Chrome as its not needed
  710. * @return {[type]}
  711. **/
  712. app.windowScrollEvents = function () {
  713. if ( myapp_config.root_.is('.nav-function-hidden.header-function-fixed:not(.nav-function-top)') && myapp_config.thisDevice === 'desktop') {
  714. myapp_config.root_logo.css({
  715. 'top': $(window).scrollTop()
  716. });
  717. } else if ( myapp_config.root_.is('.header-function-fixed:not(.nav-function-top):not(.nav-function-hidden)') && myapp_config.thisDevice === 'desktop') {
  718. myapp_config.root_logo.attr("style", "");
  719. }
  720. };
  721. /**
  722. * checkNavigationOrientation by checking layout conditions
  723. * DOC: sometimes settings can trigger certain plugins; so we check this condition and activate accordingly
  724. * E.g: the fixed navigation activates custom scroll plugin for the navigation, but this only happens when
  725. * it detects desktop browser and destroys the plugin when navigation is on top or if its not fixed.
  726. * @return {[type]}
  727. **/
  728. app.checkNavigationOrientation = function() {
  729. /**
  730. * DOC: add the plugin with the following rules: fixed navigation is selected, top navigation is not active, minify nav is not active,
  731. * and the device is desktop. We do not need to activate the plugin when loading from a mobile phone as it is not needed for touch screens.
  732. **/
  733. switch ( true ) {
  734. case ( myapp_config.root_.hasClass('nav-function-fixed') && !myapp_config.root_.is('.nav-function-top, .nav-function-minify, .mod-main-boxed') && myapp_config.thisDevice === 'desktop' ):
  735. /* start slimscroll on nav */
  736. if ( typeof $.fn.slimScroll !== 'undefined' ) {
  737. myapp_config.navAnchor.slimScroll({
  738. height: '100%',
  739. color: '#fff',
  740. size: '4px',
  741. distance: '4px',
  742. railOpacity: 0.4,
  743. wheelStep: 10
  744. });
  745. if ( document.getElementById(myapp_config.navHorizontalWrapperId) ) {
  746. myapp_config.navHooks.menuSlider('destroy');
  747. if (myapp_config.debugState)
  748. console.log("----top controls destroyed");
  749. }
  750. if (myapp_config.debugState)
  751. console.log("slimScroll created");
  752. } else {
  753. console.log("$.fn.slimScroll...NOT FOUND");
  754. }
  755. break;
  756. case ( myapp_config.navAnchor.parent().hasClass('slimScrollDiv') && myapp_config.thisDevice === 'desktop' && typeof $.fn.slimScroll !== 'undefined' ):
  757. /* destroy the plugin if it is in violation of rules above */
  758. myapp_config.navAnchor.slimScroll({ destroy: true });
  759. myapp_config.navAnchor.attr('style', '');
  760. /* clear event listners (IE bug) */
  761. events = jQuery._data( myapp_config.navAnchor[0], "events" );
  762. if (events)
  763. jQuery._removeData( myapp_config.navAnchor[0], "events" );
  764. if (myapp_config.debugState)
  765. console.log("slimScroll destroyed");
  766. break;
  767. }
  768. switch ( true ) {
  769. /* fires when user switches to nav-function-top on desktop view */
  770. case ( $.fn.menuSlider && myapp_config.root_.hasClass('nav-function-top') && $("#js-nav-menu-wrapper").length == false && !myapp_config.root_.hasClass('mobile-view-activated') ):
  771. /* build horizontal navigation */
  772. myapp_config.navHooks.menuSlider({
  773. element: myapp_config.navHooks,
  774. wrapperId: myapp_config.navHorizontalWrapperId
  775. });
  776. /* build horizontal nav */
  777. if (myapp_config.debugState)
  778. console.log("----top controls created -- case 1");
  779. break;
  780. /* fires when user resizes screen to mobile size or app is loaded on mobile resolution */
  781. case ( myapp_config.root_.hasClass('nav-function-top') && $("#js-nav-menu-wrapper").length == true && myapp_config.root_.hasClass('mobile-view-activated') ):
  782. /* destroy horizontal nav */
  783. myapp_config.navHooks.menuSlider('destroy');
  784. /* build horizontal nav */
  785. if (myapp_config.debugState)
  786. console.log("----top controls destroyed -- case 2");
  787. break;
  788. /* fires when users switch off nav-function-top class */
  789. case ( !myapp_config.root_.hasClass('nav-function-top') && $("#js-nav-menu-wrapper").length == true ):
  790. /* destroy horizontal nav */
  791. myapp_config.navHooks.menuSlider('destroy');
  792. /* build horizontal nav */
  793. if (myapp_config.debugState)
  794. console.log("----top controls destroyed -- case 3");
  795. break;
  796. }
  797. };
  798. /**
  799. * Activate Nav
  800. * DOC: activation should not take place if top navigation is on
  801. * @param {[type]} id
  802. * @return {[type]}
  803. **/
  804. app.buildNavigation = function(id) {
  805. /**
  806. * build nav
  807. * app.navigation.js
  808. **/
  809. if ($.fn.navigation) {
  810. $(id).navigation({
  811. accordion : myapp_config.navAccordion,
  812. speed : myapp_config.navSpeed,
  813. closedSign : '<em class="' + myapp_config.navClosedSign + '"></em>',
  814. openedSign : '<em class="' + myapp_config.navOpenedSign + '"></em>',
  815. initClass: myapp_config.navInitalized
  816. });
  817. return (id);
  818. } else {
  819. if (myapp_config.debugState)
  820. console.log( "WARN: navigation plugin missing" );
  821. }
  822. };
  823. /**
  824. * Destroy Nav
  825. * @param {[type]} id
  826. * @return {[type]}
  827. **/
  828. app.destroyNavigation = function(id) {
  829. /**
  830. * destroy nav
  831. * app.navigation.js
  832. **/
  833. if ($.fn.navigation) {
  834. $(id).navigationDestroy();
  835. return (id);
  836. } else {
  837. if (myapp_config.debugState)
  838. console.log( "WARN: navigation plugin missing" );
  839. }
  840. };
  841. /**
  842. * App Forms
  843. * DOC: detects if input is selected or blured
  844. * @param {[type]} parentClass
  845. * @param {[type]} focusClass
  846. * @param {[type]} disabledClass
  847. * @return {[type]}
  848. **/
  849. app.appForms = function(parentClass,focusClass,disabledClass){
  850. /* go through each .form-control */
  851. /*$('.form-control').each(function () {
  852. checkLength(this);
  853. });*/
  854. /* if input has 'some value' add class .has-length to .form-group */
  855. /*function checkLength(e) {
  856. if (e.value.length > 0 ) {
  857. $(e).parents(parentClass).addClass(focusClass);
  858. if($(e).is('[readonly]') || $(e).is('[disabled]')) {
  859. $(e).parents(parentClass).addClass(disabledClass);
  860. }
  861. } else {
  862. $(e).parents(parentClass).removeClass(focusClass);
  863. if($(e).is('[readonly]') || $(e).is('[disabled]')) {
  864. $(e).parents(parentClass).removeClass(disabledClass);
  865. }
  866. }
  867. }*/
  868. function setClass(e, parentClass, focusClass) {
  869. $(e).parents(parentClass).addClass(focusClass);
  870. }
  871. function deleteClass(e, parentClass, focusClass) {
  872. /*if(e.value.length) {
  873. } else {*/
  874. $(e).parents(parentClass).removeClass(focusClass);
  875. /*}*/
  876. }
  877. $(parentClass).each(function () {
  878. var input = $(this).find('.form-control');
  879. input.on('focus', function(){
  880. setClass(this, parentClass, focusClass);
  881. });
  882. input.on('blur', function(){
  883. deleteClass(this, parentClass, focusClass);
  884. });
  885. });
  886. };
  887. /**
  888. * Mobile Check Activate
  889. * DOC: check on window resize if screen width is less than [value]
  890. * @return {int}
  891. */
  892. app.mobileCheckActivation = function(){
  893. if ( window.innerWidth < myapp_config.mobileResolutionTrigger ) {
  894. myapp_config.root_.addClass('mobile-view-activated');
  895. myapp_config.mobileMenuTrigger = true;
  896. } else {
  897. myapp_config.root_.removeClass('mobile-view-activated');
  898. myapp_config.mobileMenuTrigger = false;
  899. }
  900. if (myapp_config.debugState)
  901. console.log( "mobileCheckActivation on " + $(window).width() + " | activated: " + myapp_config.mobileMenuTrigger);
  902. return myapp_config.mobileMenuTrigger;
  903. };
  904. /**
  905. * Toggle visibility
  906. * DOC: show and hide content with a button action
  907. * Usage: onclick="initApp.toggleVisibility('foo');"
  908. * @param {[type]} id
  909. * @return {[type]}
  910. **/
  911. app.toggleVisibility = function (id) {
  912. var e = document.getElementById(id);
  913. if (e.style.display == 'block')
  914. e.style.display = 'none';
  915. else
  916. e.style.display = 'block';
  917. };
  918. /**
  919. * Miscelaneous DOM ready functions
  920. * DOC: start jQuery(document).ready calls
  921. * @return {[type]}
  922. **/
  923. app.domReadyMisc = function() {
  924. /* Add file name path to input files */
  925. $('.custom-file input').change(function (e) {
  926. var files = [];
  927. for (var i = 0; i < $(this)[0].files.length; i++) {
  928. files.push($(this)[0].files[i].name);
  929. }
  930. $(this).next('.custom-file-label').html(files.join(', '));
  931. });
  932. /* Give modal backdrop an extra class to make it customizable */
  933. $('.modal-backdrop-transparent').on('show.bs.modal', function (e) {
  934. setTimeout(function(){
  935. $('.modal-backdrop').addClass('modal-backdrop-transparent');
  936. });
  937. });
  938. /* Add app date to js-get-date */
  939. if ( myapp_config.appDateHook.length ) {
  940. var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
  941. day = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
  942. now = new Date(),
  943. formatted = day[now.getDay()] + ', ' +
  944. months[now.getMonth()] + ' ' +
  945. now.getDate() + ', ' +
  946. now.getFullYear();
  947. myapp_config.appDateHook.text(formatted);
  948. }
  949. /* Check conflicting classes to build/destroy slimscroll */
  950. initApp.checkNavigationOrientation();
  951. /* Activate the last tab clicked using localStorage */
  952. var lastTab = localStorage.getItem('lastTab');
  953. $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
  954. localStorage.setItem('lastTab', $(this).attr('href'));
  955. });
  956. if (lastTab) {
  957. $('[href="' + lastTab + '"]').tab('show');
  958. }
  959. /**
  960. * all options:
  961. * --------------
  962. width: '300px',
  963. height: '500px',
  964. size: '10px',
  965. position: 'left',
  966. color: '#ffcc00',
  967. alwaysVisible: true,
  968. distance: '20px',
  969. start: $('#child_image_element'),
  970. railVisible: true,
  971. railColor: '#222',
  972. railOpacity: 0.3,
  973. wheelStep: 10,
  974. allowPageScroll: false,
  975. disableFadeOut: false
  976. **/
  977. if ( typeof $.fn.slimScroll !== 'undefined' && myapp_config.thisDevice === 'desktop') {
  978. $('.custom-scroll:not(.disable-slimscroll) >:first-child').slimscroll({
  979. height: $(this).data('scrollHeight') || '100%',
  980. size: $(this).data('scrollSize') || '4px',
  981. position: $(this).data('scrollPosition') || 'right',
  982. color: $(this).data('scrollColor') || 'rgba(0,0,0,0.6)',
  983. alwaysVisible: $(this).data('scrollAlwaysVisible') || false,
  984. distance: $(this).data('scrollDistance') || '4px',
  985. railVisible: $(this).data('scrollRailVisible') || false,
  986. railColor: $(this).data('scrollRailColor') || '#fafafa',
  987. allowPageScroll: false,
  988. disableFadeOut: false
  989. });
  990. if (myapp_config.debugState)
  991. console.log("%c✔ SlimScroll plugin active", "color: #148f32");
  992. } else {
  993. console.log("WARN! $.fn.slimScroll not loaded or user is on desktop");
  994. myapp_config.root_.addClass("no-slimscroll");
  995. }
  996. /**
  997. * Activate listFilters
  998. * usage: <input id="inputID" data-listfilter="listFilter" />
  999. **/
  1000. if( typeof initApp.listFilter !== 'undefined' && $.isFunction(initApp.listFilter) && $('[data-listfilter]').length ) {
  1001. var inputID = $('[data-listfilter]').attr('id'),
  1002. listFilter = $('[data-listfilter]').attr("data-listfilter");
  1003. /* initApp.listFilter($('.list'), $('#intput-id')); */
  1004. initApp.listFilter(listFilter, '#' + inputID);
  1005. }
  1006. /**
  1007. * Start bootstrap tooltips
  1008. **/
  1009. if( typeof($.fn.tooltip) !== 'undefined' && $('[data-toggle="tooltip"]').length ){
  1010. $('[data-toggle="tooltip"]').tooltip(); /*{html: true}*/
  1011. } else {
  1012. console.log("OOPS! bs.tooltip is not loaded");
  1013. }
  1014. /**
  1015. * Start bootstrap popovers
  1016. **/
  1017. if( typeof($.fn.popover) !== 'undefined' && $('[data-toggle="popover"]').length ){
  1018. /* BS4 sanatize */
  1019. var myDefaultWhiteList = $.fn.tooltip.Constructor.Default.whiteList
  1020. /* init popover */
  1021. /* data-sanitize="false" was not working so had to add this globally */
  1022. /* DOC: https://getbootstrap.com/docs/4.3/getting-started/javascript/#sanitizer */
  1023. $('[data-toggle="popover"]').popover({sanitize:false}); /*{trigger: "focus"}*/
  1024. } /*else {
  1025. console.log("OOPS! bs.popover is not loaded");
  1026. console.log("this")
  1027. }*/
  1028. /*
  1029. * Disable popper.js's forced hardware accelaration styles
  1030. */
  1031. if( typeof($.fn.dropdown) !== 'undefined'){
  1032. Popper.Defaults.modifiers.computeStyle.gpuAcceleration = false;
  1033. } else {
  1034. console.log("OOPS! bs.popover is not loaded");
  1035. }
  1036. /**
  1037. * Dropdowns will not close on click
  1038. * doc: close dropdowns on click outside hit area
  1039. **/
  1040. $(document).on('click', '.dropdown-menu:not(.js-auto-close)', function (e) {
  1041. e.stopPropagation();
  1042. });
  1043. /**
  1044. * Waves effect (plugin has issues with IE9)
  1045. * DOC: http://fian.my.id/Waves/#start
  1046. **/
  1047. if (window.Waves && myapp_config.rippleEffect) {
  1048. Waves.attach('.nav-menu:not(.js-waves-off) a, .btn:not(.js-waves-off):not(.btn-switch), .js-waves-on', ['waves-themed']);
  1049. Waves.init();
  1050. if (myapp_config.debugState)
  1051. console.log("%c✔ Waves plugin active", "color: #148f32");
  1052. } else {
  1053. if (myapp_config.debugState)
  1054. console.log("%c✘ Waves plugin inactive! ", "color: #fd3995");
  1055. }
  1056. /**
  1057. * Action buttons
  1058. **/
  1059. myapp_config.root_
  1060. .on('click touchend', '[data-action]', function(e) {
  1061. var actiontype = $(this).data('action');
  1062. switch ( true ) {
  1063. /**
  1064. * toggle trigger
  1065. * Usage 1 (body): <a href="#" data-action="toggle" data-class="add-this-class-to-body">...</a>
  1066. * Usage 2 (target): <a href="#" data-action="toggle" data-class="add-this-class-to-target" data-target="target">...</a>
  1067. **/
  1068. case ( actiontype === 'toggle' ):
  1069. var target = $(this).attr('data-target') || myapp_config.root_,
  1070. dataClass = $(this).attr('data-class'),
  1071. inputFocus = $(this).attr('data-focus');
  1072. /* remove previous background image if alternate is selected */
  1073. if ( dataClass.indexOf('mod-bg-') !== -1 ) {
  1074. $(target).removeClass (function (index, css) {
  1075. return (css.match (/(^|\s)mod-bg-\S+/g) || []).join(' ');
  1076. });
  1077. }
  1078. /* trigger class change */
  1079. $(target).toggleClass( dataClass );
  1080. /* this allows us to add active class for dropdown toggle components */
  1081. if ( $(this).hasClass('dropdown-item') ) {
  1082. $(this).toggleClass('active');
  1083. }
  1084. /* focus input if available
  1085. FAQ: We had to put a delay timer to slow it down for chrome
  1086. */
  1087. if(inputFocus != undefined) {
  1088. setTimeout(function(){ $('#' + inputFocus).focus(); }, 200);
  1089. }
  1090. /* save settings */
  1091. if ( typeof classHolder != 'undefined' || classHolder != null ) {
  1092. /* NOTE: saveSettings function is located right after <body> tag */
  1093. initApp.checkNavigationOrientation();
  1094. initApp.saveSettings();
  1095. }
  1096. break;
  1097. /**
  1098. * toggle swap trigger
  1099. * Usage (target): <a href="#" data-action="toggle-swap" data-class=".add-this-class-to-target .another-class" data-target="#id">...</a>
  1100. **/
  1101. case ( actiontype === 'toggle-swap' ):
  1102. var target = $(this).attr('data-target'),
  1103. dataClass = $(this).attr('data-class');
  1104. /* trigger class change */
  1105. $(target).removeClass().addClass( dataClass );
  1106. break;
  1107. /**
  1108. * panel 'collapse' trigger
  1109. **/
  1110. case ( actiontype === 'panel-collapse' ):
  1111. var selectedPanel = $(this).closest('.panel');
  1112. selectedPanel.children('.panel-container').collapse('toggle')
  1113. .on('show.bs.collapse', function() {
  1114. selectedPanel.removeClass("panel-collapsed");
  1115. if (myapp_config.debugState)
  1116. console.log( "panel id:" + selectedPanel.attr('id') + " | action: uncollapsed" );
  1117. }).on('hidden.bs.collapse', function(){
  1118. selectedPanel.addClass("panel-collapsed");
  1119. if (myapp_config.debugState)
  1120. console.log( "panel id:" + selectedPanel.attr('id') + " | action: collapsed" );
  1121. });
  1122. /* return ID of panel */
  1123. //return selectedPanel.attr('id');
  1124. break;
  1125. /**
  1126. * panel 'fullscreen' trigger
  1127. **/
  1128. case ( actiontype === 'panel-fullscreen' ):
  1129. var selectedPanel = $(this).closest('.panel');
  1130. selectedPanel.toggleClass('panel-fullscreen');
  1131. myapp_config.root_.toggleClass('panel-fullscreen');
  1132. if (myapp_config.debugState)
  1133. console.log( "panel id:" + selectedPanel.attr('id') + " | action: fullscreen" );
  1134. /* return ID of panel */
  1135. //return selectedPanel.attr('id');
  1136. break;
  1137. /**
  1138. * panel 'close' trigger
  1139. **/
  1140. case ( actiontype === 'panel-close' ):
  1141. var selectedPanel = $(this).closest('.panel');
  1142. var killPanel = function (){
  1143. selectedPanel.fadeOut(500,function(){
  1144. /* remove panel */
  1145. $(this).remove();
  1146. if (myapp_config.debugState)
  1147. console.log( "panel id:" + selectedPanel.attr('id') + " | action: removed" );
  1148. });
  1149. };
  1150. if (typeof bootbox != 'undefined') {
  1151. initApp.playSound('media/sound', 'messagebox')
  1152. bootbox.confirm({
  1153. title: "<i class='fal fa-times-circle text-danger mr-2'></i> Do you wish to delete panel <span class='fw-500'>&nbsp;'" +selectedPanel.children('.panel-hdr').children('h2').text().trim()+ "'&nbsp;</span>?",
  1154. message: "<span><strong>Warning:</strong> This action cannot be undone!</span>",
  1155. centerVertical: true,
  1156. swapButtonOrder: true,
  1157. buttons: {
  1158. confirm: {
  1159. label: 'Yes',
  1160. className: 'btn-danger shadow-0'
  1161. },
  1162. cancel: {
  1163. label: 'No',
  1164. className: 'btn-default'
  1165. }
  1166. },
  1167. className: "modal-alert",
  1168. closeButton: false,
  1169. callback: function (result) {
  1170. if (result == true) {
  1171. killPanel();
  1172. }
  1173. }
  1174. });
  1175. } else {
  1176. if (confirm( 'Do you wish to delete panel ' + selectedPanel.children('.panel-hdr').children('h2').text().trim() + '?' )) {
  1177. killPanel();
  1178. }
  1179. }
  1180. break;
  1181. /**
  1182. * update header css, 'theme-update' trigger
  1183. * eg: data-action = "theme-update"
  1184. * data-theme = "css/cust-theme-1.css"
  1185. **/
  1186. case ( actiontype === 'theme-update' ):
  1187. if ( $(myapp_config.mythemeAnchor).length) {
  1188. $(myapp_config.mythemeAnchor).attr('href', $(this).attr('data-theme') );
  1189. } else {
  1190. var mytheme = $("<link>", {id: myapp_config.mythemeAnchor.replace('#', ''), "rel": "stylesheet", "href" : $(this).attr('data-theme') });
  1191. $('head').append(mytheme);
  1192. }
  1193. if ( $(this).attr('data-themesave') != undefined ) {
  1194. initApp.saveSettings();
  1195. }
  1196. break;
  1197. /**
  1198. * theme 'app-reset' trigger
  1199. **/
  1200. case ( actiontype === 'app-reset' ):
  1201. initApp.resetSettings();
  1202. break;
  1203. /**
  1204. * theme 'factory-reset' trigger
  1205. **/
  1206. case ( actiontype === 'factory-reset' ):
  1207. initApp.factoryReset();
  1208. break;
  1209. /**
  1210. * app print
  1211. * starts print priview for browser
  1212. **/
  1213. case ( actiontype === 'app-print' ):
  1214. window.print();
  1215. break;
  1216. /**
  1217. * ondemand
  1218. * load onDemand scripts
  1219. **/
  1220. case ( actiontype === 'app-loadscript' ):
  1221. var loadurl = $(this).attr('data-loadurl'),
  1222. loadfunction = $(this).attr('data-loadfunction');
  1223. initApp.loadScript(loadurl,loadfunction);
  1224. break;
  1225. /**
  1226. * app language selection
  1227. * lazyloads i18n plugin and activates selected language
  1228. **/
  1229. case ( actiontype === 'lang' ):
  1230. var applang = $(this).attr('data-lang').toString();
  1231. if (!$.i18n) {
  1232. //jQuery.getScript('http://url/to/the/script');
  1233. initApp.loadScript("js/i18n/i18n.js",
  1234. function activateLang () {
  1235. $.i18n.init({
  1236. resGetPath: 'media/data/__lng__.json',
  1237. load: 'unspecific',
  1238. fallbackLng: false,
  1239. lng: applang
  1240. }, function (t){
  1241. $('[data-i18n]').i18n();
  1242. });
  1243. }
  1244. );
  1245. } else {
  1246. i18n.setLng(applang, function(){
  1247. $('[data-i18n]').i18n();
  1248. $('[data-lang]').removeClass('active');
  1249. $(this).addClass('active');
  1250. });
  1251. }
  1252. break;
  1253. /**
  1254. * app 'fullscreen' trigger
  1255. **/
  1256. case ( actiontype === 'app-fullscreen' ):
  1257. /* NOTE: this may not work for all browsers if the browser security does not permit it
  1258. IE issues: http://stackoverflow.com/questions/33732805/fullscreen-not-working-in-ie */
  1259. if (!document.fullscreenElement && !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement ) {
  1260. if (document.documentElement.requestFullscreen) {
  1261. /* Standard browsers */
  1262. document.documentElement.requestFullscreen();
  1263. } else if (document.documentElement.msRequestFullscreen) {
  1264. /* Internet Explorer */
  1265. document.documentElement.msRequestFullscreen();
  1266. } else if (document.documentElement.mozRequestFullScreen) {
  1267. /* Firefox */
  1268. document.documentElement.mozRequestFullScreen();
  1269. } else if (document.documentElement.webkitRequestFullscreen) {
  1270. /* Chrome */
  1271. document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
  1272. }
  1273. if (myapp_config.debugState)
  1274. console.log( "app fullscreen toggle active" );
  1275. } else {
  1276. if (document.exitFullscreen) {
  1277. document.exitFullscreen();
  1278. } else if (document.msExitFullscreen) {
  1279. document.msExitFullscreen();
  1280. } else if (document.mozCancelFullScreen) {
  1281. document.mozCancelFullScreen();
  1282. } else if (document.webkitExitFullscreen) {
  1283. document.webkitExitFullscreen();
  1284. }
  1285. if (myapp_config.debugState)
  1286. console.log("%capp fullscreen toggle inactive! ", "color: #ed1c24");
  1287. }
  1288. break;
  1289. /**
  1290. * app 'playsound' trigger
  1291. * usage: data-action="playsound" data-soundpath="media/sound/" data-soundfile="filename" (no file extensions)
  1292. **/
  1293. case ( actiontype === 'playsound' ):
  1294. var path = $(this).attr('data-soundpath') || "media/sound/",
  1295. sound = $(this).attr('data-soundfile');
  1296. initApp.playSound(path,sound);
  1297. break;
  1298. }
  1299. /* hide tooltip if any present */
  1300. $(this).tooltip('hide');
  1301. if (myapp_config.debugState)
  1302. console.log("data-action clicked: " + actiontype);
  1303. /* stop default link action */
  1304. e.stopPropagation();
  1305. e.preventDefault();
  1306. });
  1307. /**
  1308. * Windows mobile 8 fix ~
  1309. * DOC: bootstrap related
  1310. **/
  1311. if (navigator.userAgent.match(/IEMobile\/10\.0/)) {
  1312. var msViewportStyle = document.createElement('style');
  1313. msViewportStyle.appendChild(
  1314. document.createTextNode(
  1315. '@-ms-viewport{width:auto!important}'
  1316. )
  1317. );
  1318. document.head.appendChild(msViewportStyle)
  1319. };
  1320. /**
  1321. * Display APP version
  1322. * DOC: only show this if debug state tree
  1323. **/
  1324. if (myapp_config.debugState)
  1325. console.log("%c✔ Finished app.init() v" + myapp_config.VERSION + '\n' + "---------------------------", "color: #148f32");
  1326. };
  1327. return app;
  1328. })({});
  1329. /*
  1330. "Night is a bag that bursts with the golden dust of dawn..."
  1331. Oh wow, you actually opened this file and read it all the way though! Congrats!
  1332. Please do drop me a line at @myplaneticket :)
  1333. */
  1334. /**
  1335. * Bind the throttled handler to the resize event.
  1336. * NOTE: Please do not change the order displayed (e.g. 1a, 1b, 2a, 2b...etc)
  1337. **/
  1338. $(window).resize(
  1339. $.throttle( myapp_config.throttleDelay, function (e) {
  1340. /**
  1341. * (1a) ADD CLASS WHEN BELOW CERTAIN WIDTH (MOBILE MENU)
  1342. * Description: tracks the page min-width of #CONTENT and NAV when navigation is resized.
  1343. * This is to counter bugs for minimum page width on many desktop and mobile devices.
  1344. **/
  1345. initApp.mobileCheckActivation();
  1346. /**
  1347. * (1b) CHECK NAVIGATION STATUS (IF HORIZONTAL OR VERTICAL)
  1348. * Description: fires an event to check for navigation orientation.
  1349. * Based on the condition, it will initliaze or destroy the slimscroll, or horizontal nav plugins
  1350. **/
  1351. initApp.checkNavigationOrientation();
  1352. /** -- insert your resize codes below this line -- **/
  1353. })
  1354. );
  1355. /**
  1356. * Bind the throttled handler to the scroll event
  1357. **/
  1358. $(window).scroll(
  1359. $.throttle( myapp_config.throttleDelay, function (e) {
  1360. /**
  1361. * FIX APP HEIGHT
  1362. * Compare the height of nav and content;
  1363. * If one is longer/shorter than the other, measure them to be equal.
  1364. * This event is only fired on desktop.
  1365. **/
  1366. /** -- insert your other scroll codes below this line -- **/
  1367. })
  1368. );
  1369. /**
  1370. * Initiate scroll events
  1371. **/
  1372. $(window).on('scroll', initApp.windowScrollEvents);
  1373. /**
  1374. * DOCUMENT LOADED EVENT
  1375. * DOC: Fire when DOM is ready
  1376. * Do not change order a, b, c, d...
  1377. **/
  1378. document.addEventListener('DOMContentLoaded', function() {
  1379. /**
  1380. * detect desktop or mobile
  1381. **/
  1382. initApp.addDeviceType();
  1383. /**
  1384. * detect Webkit Browser
  1385. **/
  1386. initApp.detectBrowserType();
  1387. /**
  1388. * a. check for mobile view width and add class .mobile-view-activated
  1389. **/
  1390. initApp.mobileCheckActivation();
  1391. /**
  1392. * b. build navigation
  1393. **/
  1394. initApp.buildNavigation(myapp_config.navHooks);
  1395. /**
  1396. * c. initialize nav filter
  1397. **/
  1398. initApp.listFilter(myapp_config.navHooks, myapp_config.navFilterInput, myapp_config.navAnchor);
  1399. /**
  1400. * d. run DOM misc functions
  1401. **/
  1402. initApp.domReadyMisc();
  1403. /**
  1404. * e. run app forms class detectors [parentClass,focusClass,disabledClass]
  1405. **/
  1406. initApp.appForms('.input-group', 'has-length', 'has-disabled');
  1407. });
  1408. /**
  1409. * Mobile orientation change events
  1410. * DOC: recalculates app height
  1411. **/
  1412. $( window ).on( "orientationchange", function( event ) {
  1413. /* reset any .CSS heights and force appHeight function to recalculate */
  1414. if (myapp_config.debugState)
  1415. console.log("orientationchange event");
  1416. });
  1417. /**
  1418. * Window load function
  1419. * DOC: window focus blur detection
  1420. **/
  1421. $(window).on("blur focus", function(e) {
  1422. var prevType = $(this).data("prevType");
  1423. /**
  1424. * reduce double fire issues
  1425. **/
  1426. if (prevType != e.type) {
  1427. switch (e.type) {
  1428. case "blur":
  1429. myapp_config.root_.toggleClass("blur")
  1430. if (myapp_config.debugState)
  1431. console.log("blur");
  1432. break;
  1433. case "focus":
  1434. myapp_config.root_.toggleClass("blur")
  1435. if (myapp_config.debugState)
  1436. console.log("focused");
  1437. break;
  1438. }
  1439. }
  1440. $(this).data("prevType", e.type);
  1441. })
  1442. var color = {
  1443. primary: {
  1444. _50: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-primary-50').css('color')) || '#ccbfdf',
  1445. _100: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-primary-100').css('color')) || '#beaed7',
  1446. _200: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-primary-200').css('color')) || '#b19dce',
  1447. _300: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-primary-300').css('color')) || '#a38cc6',
  1448. _400: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-primary-400').css('color')) || '#967bbd',
  1449. _500: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-primary-500').css('color')) || '#886ab5',
  1450. _600: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-primary-600').css('color')) || '#7a59ad',
  1451. _700: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-primary-700').css('color')) || '#6e4e9e',
  1452. _800: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-primary-800').css('color')) || '#62468d',
  1453. _900: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-primary-900').css('color')) || '#563d7c'
  1454. },
  1455. success: {
  1456. _50: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-success-50').css('color')) || '#7aece0',
  1457. _100: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-success-100').css('color')) || '#63e9db',
  1458. _200: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-success-200').css('color')) || '#4de5d5',
  1459. _300: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-success-300').css('color')) || '#37e2d0',
  1460. _400: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-success-400').css('color')) || '#21dfcb',
  1461. _500: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-success-500').css('color')) || '#1dc9b7',
  1462. _600: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-success-600').css('color')) || '#1ab3a3',
  1463. _700: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-success-700').css('color')) || '#179c8e',
  1464. _800: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-success-800').css('color')) || '#13867a',
  1465. _900: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-success-900').css('color')) || '#107066'
  1466. },
  1467. info: {
  1468. _50: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-info-50').css('color')) || '#9acffa',
  1469. _100: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-info-100').css('color')) || '#82c4f8',
  1470. _200: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-info-200').css('color')) || '#6ab8f7',
  1471. _300: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-info-300').css('color')) || '#51adf6',
  1472. _400: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-info-400').css('color')) || '#39a1f4',
  1473. _500: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-info-500').css('color')) || '#2196F3',
  1474. _600: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-info-600').css('color')) || '#0d8aee',
  1475. _700: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-info-700').css('color')) || '#0c7cd5',
  1476. _800: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-info-800').css('color')) || '#0a6ebd',
  1477. _900: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-info-900').css('color')) || '#0960a5'
  1478. },
  1479. warning: {
  1480. _50: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-warning-50').css('color')) || '#ffebc1',
  1481. _100: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-warning-100').css('color')) || '#ffe3a7',
  1482. _200: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-warning-200').css('color')) || '#ffdb8e',
  1483. _300: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-warning-300').css('color')) || '#ffd274',
  1484. _400: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-warning-400').css('color')) || '#ffca5b',
  1485. _500: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-warning-500').css('color')) || '#ffc241',
  1486. _600: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-warning-600').css('color')) || '#ffba28',
  1487. _700: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-warning-700').css('color')) || '#ffb20e',
  1488. _800: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-warning-800').css('color')) || '#f4a500',
  1489. _900: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-warning-900').css('color')) || '#da9400'
  1490. },
  1491. danger: {
  1492. _50: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-danger-50').css('color')) || '#feb7d9',
  1493. _100: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-danger-100').css('color')) || '#fe9ecb',
  1494. _200: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-danger-200').css('color')) || '#fe85be',
  1495. _300: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-danger-300').css('color')) || '#fe6bb0',
  1496. _400: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-danger-400').css('color')) || '#fd52a3',
  1497. _500: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-danger-500').css('color')) || '#fd3995',
  1498. _600: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-danger-600').css('color')) || '#fd2087',
  1499. _700: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-danger-700').css('color')) || '#fc077a',
  1500. _800: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-danger-800').css('color')) || '#e7026e',
  1501. _900: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-danger-900').css('color')) || '#ce0262'
  1502. },
  1503. fusion: {
  1504. _50: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-fusion-50').css('color')) || '#909090',
  1505. _100: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-fusion-100').css('color')) || '#838383',
  1506. _200: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-fusion-200').css('color')) || '#767676',
  1507. _300: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-fusion-300').css('color')) || '#696969',
  1508. _400: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-fusion-400').css('color')) || '#5d5d5d',
  1509. _500: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-fusion-500').css('color')) || '#505050',
  1510. _600: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-fusion-600').css('color')) || '#434343',
  1511. _700: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-fusion-700').css('color')) || '#363636',
  1512. _800: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-fusion-800').css('color')) || '#2a2a2a',
  1513. _900: rgb2hex(myapp_config.mythemeColorProfileID.find('.color-fusion-900').css('color')) || '#1d1d1d'
  1514. }
  1515. }
  1516. function autoFlashHeight(){
  1517. $(".dialog-sheet").height($(window).height()-58);
  1518. };