app.bundle.js 60 KB

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