github.com/apremalal/vamps-core@v1.0.1-0.20161221121535-d430b56ec174/server/webapps/app/base/plugins/jarviswidgets/jarvis.js (about) 1 /* ______________________________________ 2 ________| |_______ 3 \ | SmartAdmin WebApp | / 4 \ | Copyright © 2015 MyOrange | / 5 / |______________________________________| \ 6 /__________) (_________\ 7 8 * The above copyright notice and this permission notice shall be 9 * included in all copies or substantial portions of the Software. 10 * ======================================================================= 11 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 12 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 13 * MERCHANTABILITY, IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 14 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 15 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 16 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 * ======================================================================= 18 * original filename : app.js 19 * filesize : 62,499~ bytes 20 * author : Sunny (@bootstraphunt) 21 * email : info@myorange.ca 22 * legal notice : This script is part of a theme sold by 23 * https://wrapbootstrap.com/?ref=myorange 24 * 25 * ======================================================================= 26 * INDEX (Note: line numbers for index items may not be up to date): 27 * 28 * 1. APP CONFIGURATION..................................[ app.config.js ] 29 * 2. APP DOM REFERENCES.................................[ app.config.js ] 30 * 3. DETECT MOBILE DEVICES...................................[line: 149 ] 31 * 4. CUSTOM MENU PLUGIN......................................[line: 688 ] 32 * 5. ELEMENT EXIST OR NOT....................................[line: 778 ] 33 * 6. INITIALIZE FORMS........................................[line: 788 ] 34 * 6a. BOOTSTRAP SLIDER PLUGIN...........................[line: 794 ] 35 * 6b. SELECT2 PLUGIN....................................[line: 803 ] 36 * 6c. MASKING...........................................[line: 824 ] 37 * 6d. AUTOCOMPLETE......................................[line: 843 ] 38 * 6f. JQUERY UI DATE....................................[line: 862 ] 39 * 6g. AJAX BUTTON LOADING TEXT..........................[line: 884 ] 40 * 7. INITIALIZE CHARTS.......................................[line: 902 ] 41 * 7a. SPARKLINES........................................[line: 907 ] 42 * 7b. LINE CHART........................................[line: 1026] 43 * 7c. PIE CHART.........................................[line: 1077] 44 * 7d. BOX PLOT..........................................[line: 1100] 45 * 7e. BULLET............................................[line: 1145] 46 * 7f. DISCRETE..........................................[line: 1169] 47 * 7g. TRISTATE..........................................[line: 1195] 48 * 7h. COMPOSITE: BAR....................................[line: 1223] 49 * 7i. COMPOSITE: LINE...................................[line: 1259] 50 * 7j. EASY PIE CHARTS...................................[line: 1339] 51 * 8. INITIALIZE JARVIS WIDGETS...............................[line: 1379] 52 * 8a. SETUP DESKTOP WIDGET..............................[line: 1466] 53 * 8b. GOOGLE MAPS.......................................[line: 1478] 54 * 8c. LOAD SCRIPTS......................................[line: 1500] 55 * 8d. APP AJAX REQUEST SETUP............................[line: 1538] 56 * 9. CHECK TO SEE IF URL EXISTS..............................[line: 1614] 57 * 10.LOAD AJAX PAGES.........................................[line: 1669] 58 * 11.UPDATE BREADCRUMB.......................................[line: 1775] 59 * 12.PAGE SETUP..............................................[line: 1798] 60 * 13.POP OVER THEORY.........................................[line: 1852] 61 * 14.DELETE MODEL DATA ON HIDDEN.............................[line: 1991] 62 * 15.HELPFUL FUNCTIONS.......................................[line: 2027] 63 * 64 * ======================================================================= 65 * IMPORTANT: ALL CONFIG VARS IS NOW MOVED TO APP.CONFIG.JS 66 * ======================================================================= 67 * 68 * 69 * GLOBAL: interval array (to be used with jarviswidget in ajax and 70 * angular mode) to clear auto fetch interval 71 */ 72 $.intervalArr = []; 73 /* 74 * Calculate nav height 75 */ 76 var calc_navbar_height = function() { 77 var height = null; 78 79 if ($('#header').length) 80 height = $('#header').height(); 81 82 if (height === null) 83 height = $('<div id="header"></div>').height(); 84 85 if (height === null) 86 return 49; 87 // default 88 return height; 89 }, 90 91 navbar_height = calc_navbar_height, 92 /* 93 * APP DOM REFERENCES 94 * Description: Obj DOM reference, please try to avoid changing these 95 */ 96 shortcut_dropdown = $('#shortcut'), 97 98 bread_crumb = $('#ribbon ol.breadcrumb'), 99 /* 100 * Top menu on/off 101 */ 102 topmenu = false, 103 /* 104 * desktop or mobile 105 */ 106 thisDevice = null, 107 /* 108 * DETECT MOBILE DEVICES 109 * Description: Detects mobile device - if any of the listed device is 110 * detected a class is inserted to $.root_ and the variable thisDevice 111 * is decleard. (so far this is covering most hand held devices) 112 */ 113 ismobile = (/iphone|ipad|ipod|android|blackberry|mini|windows\sce|palm/i.test(navigator.userAgent.toLowerCase())), 114 /* 115 * JS ARRAY SCRIPT STORAGE 116 * Description: used with loadScript to store script path and file name 117 * so it will not load twice 118 */ 119 jsArray = {}, 120 /* 121 * App Initialize 122 * Description: Initializes the app with intApp(); 123 */ 124 initApp = (function(app) { 125 126 /* 127 * ADD DEVICE TYPE 128 * Detect if mobile or desktop 129 */ 130 app.addDeviceType = function() { 131 132 if (!ismobile) { 133 // Desktop 134 $.root_.addClass("desktop-detected"); 135 thisDevice = "desktop"; 136 return false; 137 } else { 138 // Mobile 139 $.root_.addClass("mobile-detected"); 140 thisDevice = "mobile"; 141 142 if (fastClick) { 143 // Removes the tap delay in idevices 144 // dependency: js/plugin/fastclick/fastclick.js 145 $.root_.addClass("needsclick"); 146 FastClick.attach(document.body); 147 return false; 148 } 149 150 } 151 152 }; 153 /* ~ END: ADD DEVICE TYPE */ 154 155 /* 156 * CHECK FOR MENU POSITION 157 * Scans localstroage for menu position (vertical or horizontal) 158 */ 159 app.menuPos = function() { 160 161 if ($.root_.hasClass("menu-on-top") || localStorage.getItem('sm-setmenu')=='top' ) { 162 topmenu = true; 163 $.root_.addClass("menu-on-top"); 164 } 165 }; 166 /* ~ END: CHECK MOBILE DEVICE */ 167 168 /* 169 * SMART ACTIONS 170 */ 171 app.SmartActions = function(){ 172 173 var smartActions = { 174 175 // LOGOUT MSG 176 userLogout: function($this){ 177 178 // ask verification 179 $.SmartMessageBox({ 180 title : "<i class='fa fa-sign-out txt-color-orangeDark'></i> Logout <span class='txt-color-orangeDark'><strong>" + $('#show-shortcut').text() + "</strong></span> ?", 181 content : $this.data('logout-msg') || "You can improve your security further after logging out by closing this opened browser", 182 buttons : '[No][Yes]' 183 184 }, function(ButtonPressed) { 185 if (ButtonPressed == "Yes") { 186 $.root_.addClass('animated fadeOutUp'); 187 setTimeout(logout, 1000); 188 } 189 }); 190 function logout() { 191 window.location = $this.attr('href'); 192 } 193 194 }, 195 196 // RESET WIDGETS 197 resetWidgets: function($this){ 198 199 $.SmartMessageBox({ 200 title : "<i class='fa fa-refresh' style='color:green'></i> Clear Local Storage", 201 content : $this.data('reset-msg') || "Would you like to RESET all your saved widgets and clear LocalStorage?1", 202 buttons : '[No][Yes]' 203 }, function(ButtonPressed) { 204 if (ButtonPressed == "Yes" && localStorage) { 205 localStorage.clear(); 206 location.reload(); 207 } 208 209 }); 210 }, 211 212 // LAUNCH FULLSCREEN 213 launchFullscreen: function(element){ 214 215 if (!$.root_.hasClass("full-screen")) { 216 217 $.root_.addClass("full-screen"); 218 219 if (element.requestFullscreen) { 220 element.requestFullscreen(); 221 } else if (element.mozRequestFullScreen) { 222 element.mozRequestFullScreen(); 223 } else if (element.webkitRequestFullscreen) { 224 element.webkitRequestFullscreen(); 225 } else if (element.msRequestFullscreen) { 226 element.msRequestFullscreen(); 227 } 228 229 } else { 230 231 $.root_.removeClass("full-screen"); 232 233 if (document.exitFullscreen) { 234 document.exitFullscreen(); 235 } else if (document.mozCancelFullScreen) { 236 document.mozCancelFullScreen(); 237 } else if (document.webkitExitFullscreen) { 238 document.webkitExitFullscreen(); 239 } 240 241 } 242 243 }, 244 245 // MINIFY MENU 246 minifyMenu: function($this){ 247 if (!$.root_.hasClass("menu-on-top")){ 248 $.root_.toggleClass("minified"); 249 $.root_.removeClass("hidden-menu"); 250 $('html').removeClass("hidden-menu-mobile-lock"); 251 $this.effect("highlight", {}, 500); 252 } 253 }, 254 255 // TOGGLE MENU 256 toggleMenu: function(){ 257 if (!$.root_.hasClass("menu-on-top")){ 258 $('html').toggleClass("hidden-menu-mobile-lock"); 259 $.root_.toggleClass("hidden-menu"); 260 $.root_.removeClass("minified"); 261 //} else if ( $.root_.hasClass("menu-on-top") && $.root_.hasClass("mobile-view-activated") ) { 262 // suggested fix from Christian Jäger 263 } else if ( $.root_.hasClass("menu-on-top") && $(window).width() < 979 ) { 264 $('html').toggleClass("hidden-menu-mobile-lock"); 265 $.root_.toggleClass("hidden-menu"); 266 $.root_.removeClass("minified"); 267 } 268 }, 269 270 // TOGGLE SHORTCUT 271 toggleShortcut: function(){ 272 273 if (shortcut_dropdown.is(":visible")) { 274 shortcut_buttons_hide(); 275 } else { 276 shortcut_buttons_show(); 277 } 278 279 // SHORT CUT (buttons that appear when clicked on user name) 280 shortcut_dropdown.find('a').click(function(e) { 281 e.preventDefault(); 282 window.location = $(this).attr('href'); 283 setTimeout(shortcut_buttons_hide, 300); 284 285 }); 286 287 // SHORTCUT buttons goes away if mouse is clicked outside of the area 288 $(document).mouseup(function(e) { 289 if (!shortcut_dropdown.is(e.target) && shortcut_dropdown.has(e.target).length === 0) { 290 shortcut_buttons_hide(); 291 } 292 }); 293 294 // SHORTCUT ANIMATE HIDE 295 function shortcut_buttons_hide() { 296 shortcut_dropdown.animate({ 297 height : "hide" 298 }, 300, "easeOutCirc"); 299 $.root_.removeClass('shortcut-on'); 300 301 } 302 303 // SHORTCUT ANIMATE SHOW 304 function shortcut_buttons_show() { 305 shortcut_dropdown.animate({ 306 height : "show" 307 }, 200, "easeOutCirc"); 308 $.root_.addClass('shortcut-on'); 309 } 310 311 } 312 313 }; 314 315 $.root_.on('click', '[data-action="userLogout"]', function(e) { 316 var $this = $(this); 317 smartActions.userLogout($this); 318 e.preventDefault(); 319 320 //clear memory reference 321 $this = null; 322 323 }); 324 325 /* 326 * BUTTON ACTIONS 327 */ 328 $.root_.on('click', '[data-action="resetWidgets"]', function(e) { 329 var $this = $(this); 330 smartActions.resetWidgets($this); 331 e.preventDefault(); 332 333 //clear memory reference 334 $this = null; 335 }); 336 337 $.root_.on('click', '[data-action="launchFullscreen"]', function(e) { 338 smartActions.launchFullscreen(document.documentElement); 339 e.preventDefault(); 340 }); 341 342 $.root_.on('click', '[data-action="minifyMenu"]', function(e) { 343 var $this = $(this); 344 smartActions.minifyMenu($this); 345 e.preventDefault(); 346 347 //clear memory reference 348 $this = null; 349 }); 350 351 $.root_.on('click', '[data-action="toggleMenu"]', function(e) { 352 smartActions.toggleMenu(); 353 e.preventDefault(); 354 }); 355 356 $.root_.on('click', '[data-action="toggleShortcut"]', function(e) { 357 smartActions.toggleShortcut(); 358 e.preventDefault(); 359 }); 360 361 }; 362 /* ~ END: SMART ACTIONS */ 363 364 /* 365 * ACTIVATE NAVIGATION 366 * Description: Activation will fail if top navigation is on 367 */ 368 app.leftNav = function(){ 369 370 // INITIALIZE LEFT NAV 371 if (!topmenu) { 372 if (!null) { 373 $('nav ul').jarvismenu({ 374 accordion : menu_accordion || true, 375 speed : menu_speed || true, 376 closedSign : '<em class="fa fa-plus-square-o"></em>', 377 openedSign : '<em class="fa fa-minus-square-o"></em>' 378 }); 379 } else { 380 alert("Error - menu anchor does not exist"); 381 } 382 } 383 384 }; 385 /* ~ END: ACTIVATE NAVIGATION */ 386 387 /* 388 * MISCELANEOUS DOM READY FUNCTIONS 389 * Description: fire with jQuery(document).ready... 390 */ 391 app.domReadyMisc = function() { 392 393 /* 394 * FIRE TOOLTIPS 395 */ 396 if ($("[rel=tooltip]").length) { 397 $("[rel=tooltip]").tooltip(); 398 } 399 400 // SHOW & HIDE MOBILE SEARCH FIELD 401 $('#search-mobile').click(function() { 402 $.root_.addClass('search-mobile'); 403 }); 404 405 $('#cancel-search-js').click(function() { 406 $.root_.removeClass('search-mobile'); 407 }); 408 409 // ACTIVITY 410 // ajax drop 411 $('#activity').click(function(e) { 412 var $this = $(this); 413 414 if ($this.find('.badge').hasClass('bg-color-red')) { 415 $this.find('.badge').removeClassPrefix('bg-color-'); 416 $this.find('.badge').text("0"); 417 } 418 419 if (!$this.next('.ajax-dropdown').is(':visible')) { 420 $this.next('.ajax-dropdown').fadeIn(150); 421 $this.addClass('active'); 422 } else { 423 $this.next('.ajax-dropdown').fadeOut(150); 424 $this.removeClass('active'); 425 } 426 427 var theUrlVal = $this.next('.ajax-dropdown').find('.btn-group > .active > input').attr('id'); 428 429 //clear memory reference 430 $this = null; 431 theUrlVal = null; 432 433 e.preventDefault(); 434 }); 435 436 $('input[name="activity"]').change(function() { 437 var $this = $(this); 438 439 url = $this.attr('id'); 440 container = $('.ajax-notifications'); 441 442 loadURL(url, container); 443 444 //clear memory reference 445 $this = null; 446 }); 447 448 // close dropdown if mouse is not inside the area of .ajax-dropdown 449 $(document).mouseup(function(e) { 450 if (!$('.ajax-dropdown').is(e.target) && $('.ajax-dropdown').has(e.target).length === 0) { 451 $('.ajax-dropdown').fadeOut(150); 452 $('.ajax-dropdown').prev().removeClass("active"); 453 } 454 }); 455 456 // loading animation (demo purpose only) 457 $('button[data-btn-loading]').on('click', function() { 458 var btn = $(this); 459 btn.button('loading'); 460 setTimeout(function() { 461 btn.button('reset'); 462 }, 3000); 463 }); 464 465 // NOTIFICATION IS PRESENT 466 // Change color of lable once notification button is clicked 467 468 $this = $('#activity > .badge'); 469 470 if (parseInt($this.text()) > 0) { 471 $this.addClass("bg-color-red bounceIn animated"); 472 473 //clear memory reference 474 $this = null; 475 } 476 477 478 }; 479 /* ~ END: MISCELANEOUS DOM */ 480 481 /* 482 * MISCELANEOUS DOM READY FUNCTIONS 483 * Description: fire with jQuery(document).ready... 484 */ 485 app.mobileCheckActivation = function(){ 486 487 if ($(window).width() < 979) { 488 $.root_.addClass('mobile-view-activated'); 489 $.root_.removeClass('minified'); 490 } else if ($.root_.hasClass('mobile-view-activated')) { 491 $.root_.removeClass('mobile-view-activated'); 492 } 493 494 if (debugState){ 495 console.log("mobileCheckActivation"); 496 } 497 498 } 499 /* ~ END: MISCELANEOUS DOM */ 500 501 return app; 502 503 })({}); 504 505 initApp.addDeviceType(); 506 initApp.menuPos(); 507 /* 508 * DOCUMENT LOADED EVENT 509 * Description: Fire when DOM is ready 510 */ 511 jQuery(document).ready(function() { 512 513 initApp.SmartActions(); 514 initApp.leftNav(); 515 initApp.domReadyMisc(); 516 517 }); 518 /* 519 * RESIZER WITH THROTTLE 520 * Source: http://benalman.com/code/projects/jquery-resize/examples/resize/ 521 */ 522 (function ($, window, undefined) { 523 524 var elems = $([]), 525 jq_resize = $.resize = $.extend($.resize, {}), 526 timeout_id, str_setTimeout = 'setTimeout', 527 str_resize = 'resize', 528 str_data = str_resize + '-special-event', 529 str_delay = 'delay', 530 str_throttle = 'throttleWindow'; 531 532 jq_resize[str_delay] = throttle_delay; 533 534 jq_resize[str_throttle] = true; 535 536 $.event.special[str_resize] = { 537 538 setup: function () { 539 if (!jq_resize[str_throttle] && this[str_setTimeout]) { 540 return false; 541 } 542 543 var elem = $(this); 544 elems = elems.add(elem); 545 try { 546 $.data(this, str_data, { 547 w: elem.width(), 548 h: elem.height() 549 }); 550 } catch (e) { 551 $.data(this, str_data, { 552 w: elem.width, // elem.width(); 553 h: elem.height // elem.height(); 554 }); 555 } 556 557 if (elems.length === 1) { 558 loopy(); 559 } 560 }, 561 teardown: function () { 562 if (!jq_resize[str_throttle] && this[str_setTimeout]) { 563 return false; 564 } 565 566 var elem = $(this); 567 elems = elems.not(elem); 568 elem.removeData(str_data); 569 if (!elems.length) { 570 clearTimeout(timeout_id); 571 } 572 }, 573 574 add: function (handleObj) { 575 if (!jq_resize[str_throttle] && this[str_setTimeout]) { 576 return false; 577 } 578 var old_handler; 579 580 function new_handler(e, w, h) { 581 var elem = $(this), 582 data = $.data(this, str_data); 583 //data.w = w !== undefined ? w : elem.width(); 584 //data.h = h !== undefined ? h : elem.height(); 585 // 586 //old_handler.apply(this, arguments); 587 } 588 if ($.isFunction(handleObj)) { 589 old_handler = handleObj; 590 return new_handler; 591 } else { 592 old_handler = handleObj.handler; 593 handleObj.handler = new_handler; 594 } 595 } 596 }; 597 598 function loopy() { 599 timeout_id = window[str_setTimeout](function () { 600 elems.each(function () { 601 var width; 602 var height; 603 604 var elem = $(this), 605 data = $.data(this, str_data); //width = elem.width(), height = elem.height(); 606 607 // Highcharts fix 608 try { 609 width = elem.width(); 610 } catch (e) { 611 width = elem.width; 612 } 613 614 try { 615 height = elem.height(); 616 } catch (e) { 617 height = elem.height; 618 } 619 //fixed bug 620 621 622 if (width !== data.w || height !== data.h) { 623 elem.trigger(str_resize, [data.w = width, data.h = height]); 624 } 625 626 }); 627 loopy(); 628 629 }, jq_resize[str_delay]); 630 631 } 632 633 })(jQuery, this); 634 /* 635 * ADD CLASS WHEN BELOW CERTAIN WIDTH (MOBILE MENU) 636 * Description: tracks the page min-width of #CONTENT and NAV when navigation is resized. 637 * This is to counter bugs for minimum page width on many desktop and mobile devices. 638 * Note: This script utilizes JSthrottle script so don't worry about memory/CPU usage 639 */ 640 $('#main').resize(function() { 641 642 initApp.mobileCheckActivation(); 643 644 }); 645 646 /* ~ END: NAV OR #LEFT-BAR RESIZE DETECT */ 647 648 /* 649 * DETECT IE VERSION 650 * Description: A short snippet for detecting versions of IE in JavaScript 651 * without resorting to user-agent sniffing 652 * RETURNS: 653 * If you're not in IE (or IE version is less than 5) then: 654 * //ie === undefined 655 * 656 * If you're in IE (>=5) then you can determine which version: 657 * // ie === 7; // IE7 658 * 659 * Thus, to detect IE: 660 * // if (ie) {} 661 * 662 * And to detect the version: 663 * ie === 6 // IE6 664 * ie > 7 // IE8, IE9 ... 665 * ie < 9 // Anything less than IE9 666 */ 667 // TODO: delete this function later on - no longer needed (?) 668 var ie = ( function() { 669 670 var undef, v = 3, div = document.createElement('div'), all = div.getElementsByTagName('i'); 671 672 while (div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->', all[0]); 673 674 return v > 4 ? v : undef; 675 676 }()); 677 /* ~ END: DETECT IE VERSION */ 678 679 /* 680 * CUSTOM MENU PLUGIN 681 */ 682 $.fn.extend({ 683 684 //pass the options variable to the function 685 jarvismenu : function(options) { 686 687 var defaults = { 688 accordion : 'true', 689 speed : 200, 690 closedSign : '[+]', 691 openedSign : '[-]' 692 }, 693 694 // Extend our default options with those provided. 695 opts = $.extend(defaults, options), 696 //Assign current element to variable, in this case is UL element 697 $this = $(this); 698 699 //add a mark [+] to a multilevel menu 700 $this.find("li").each(function() { 701 if ($(this).find("ul").size() !== 0) { 702 //add the multilevel sign next to the link 703 $(this).find("a:first").append("<b class='collapse-sign'>" + opts.closedSign + "</b>"); 704 705 //avoid jumping to the top of the page when the href is an # 706 if ($(this).find("a:first").attr('href') == "#") { 707 $(this).find("a:first").click(function() { 708 return false; 709 }); 710 } 711 } 712 }); 713 714 //open active level 715 $this.find("li.active").each(function() { 716 $(this).parents("ul").slideDown(opts.speed); 717 $(this).parents("ul").parent("li").find("b:first").html(opts.openedSign); 718 $(this).parents("ul").parent("li").addClass("open"); 719 }); 720 721 $this.find("li a").click(function() { 722 723 if ($(this).parent().find("ul").size() !== 0) { 724 725 if (opts.accordion) { 726 //Do nothing when the list is open 727 if (!$(this).parent().find("ul").is(':visible')) { 728 parents = $(this).parent().parents("ul"); 729 visible = $this.find("ul:visible"); 730 visible.each(function(visibleIndex) { 731 var close = true; 732 parents.each(function(parentIndex) { 733 if (parents[parentIndex] == visible[visibleIndex]) { 734 close = false; 735 return false; 736 } 737 }); 738 if (close) { 739 if ($(this).parent().find("ul") != visible[visibleIndex]) { 740 $(visible[visibleIndex]).slideUp(opts.speed, function() { 741 $(this).parent("li").find("b:first").html(opts.closedSign); 742 $(this).parent("li").removeClass("open"); 743 }); 744 745 } 746 } 747 }); 748 } 749 }// end if 750 if ($(this).parent().find("ul:first").is(":visible") && !$(this).parent().find("ul:first").hasClass("active")) { 751 $(this).parent().find("ul:first").slideUp(opts.speed, function() { 752 $(this).parent("li").removeClass("open"); 753 $(this).parent("li").find("b:first").delay(opts.speed).html(opts.closedSign); 754 }); 755 756 } else { 757 $(this).parent().find("ul:first").slideDown(opts.speed, function() { 758 /*$(this).effect("highlight", {color : '#616161'}, 500); - disabled due to CPU clocking on phones*/ 759 $(this).parent("li").addClass("open"); 760 $(this).parent("li").find("b:first").delay(opts.speed).html(opts.openedSign); 761 }); 762 } // end else 763 } // end if 764 }); 765 } // end function 766 }); 767 /* ~ END: CUSTOM MENU PLUGIN */ 768 769 /* 770 * ELEMENT EXIST OR NOT 771 * Description: returns true or false 772 * Usage: $('#myDiv').doesExist(); 773 */ 774 jQuery.fn.doesExist = function() { 775 return jQuery(this).length > 0; 776 }; 777 /* ~ END: ELEMENT EXIST OR NOT */ 778 779 /* 780 * INITIALIZE FORMS 781 * Description: Select2, Masking, Datepicker, Autocomplete 782 */ 783 function runAllForms() { 784 785 /* 786 * BOOTSTRAP SLIDER PLUGIN 787 * Usage: 788 * Dependency: js/plugin/bootstrap-slider 789 */ 790 if ($.fn.slider) { 791 $('.slider').slider(); 792 } 793 794 /* 795 * SELECT2 PLUGIN 796 * Usage: 797 * Dependency: js/plugin/select2/ 798 */ 799 if ($.fn.select2) { 800 $('select.select2').each(function() { 801 var $this = $(this), 802 width = $this.attr('data-select-width') || '100%'; 803 //, _showSearchInput = $this.attr('data-select-search') === 'true'; 804 $this.select2({ 805 //showSearchInput : _showSearchInput, 806 allowClear : true, 807 width : width 808 }); 809 810 //clear memory reference 811 $this = null; 812 }); 813 } 814 815 /* 816 * MASKING 817 * Dependency: js/plugin/masked-input/ 818 */ 819 if ($.fn.mask) { 820 $('[data-mask]').each(function() { 821 822 var $this = $(this), 823 mask = $this.attr('data-mask') || 'error...', mask_placeholder = $this.attr('data-mask-placeholder') || 'X'; 824 825 $this.mask(mask, { 826 placeholder : mask_placeholder 827 }); 828 829 //clear memory reference 830 $this = null; 831 }); 832 } 833 834 /* 835 * AUTOCOMPLETE 836 * Dependency: js/jqui 837 */ 838 if ($.fn.autocomplete) { 839 $('[data-autocomplete]').each(function() { 840 841 var $this = $(this), 842 availableTags = $this.data('autocomplete') || ["The", "Quick", "Brown", "Fox", "Jumps", "Over", "Three", "Lazy", "Dogs"]; 843 844 $this.autocomplete({ 845 source : availableTags 846 }); 847 848 //clear memory reference 849 $this = null; 850 }); 851 } 852 853 /* 854 * JQUERY UI DATE 855 * Dependency: js/libs/jquery-ui-1.10.3.min.js 856 * Usage: <input class="datepicker" /> 857 */ 858 if ($.fn.datepicker) { 859 $('.datepicker').each(function() { 860 861 var $this = $(this), 862 dataDateFormat = $this.attr('data-dateformat') || 'dd.mm.yy'; 863 864 $this.datepicker({ 865 dateFormat : dataDateFormat, 866 prevText : '<i class="fa fa-chevron-left"></i>', 867 nextText : '<i class="fa fa-chevron-right"></i>', 868 }); 869 870 //clear memory reference 871 $this = null; 872 }); 873 } 874 875 /* 876 * AJAX BUTTON LOADING TEXT 877 * Usage: <button type="button" data-loading-text="Loading..." class="btn btn-xs btn-default ajax-refresh"> .. </button> 878 */ 879 $('button[data-loading-text]').on('click', function() { 880 var btn = $(this); 881 btn.button('loading'); 882 setTimeout(function() { 883 btn.button('reset'); 884 //clear memory reference 885 btn = null; 886 }, 3000); 887 888 }); 889 890 } 891 /* ~ END: INITIALIZE FORMS */ 892 893 /* 894 * INITIALIZE CHARTS 895 * Description: Sparklines, PieCharts 896 */ 897 function runAllCharts() { 898 /* 899 * SPARKLINES 900 * DEPENDENCY: js/plugins/sparkline/jquery.sparkline.min.js 901 * See usage example below... 902 */ 903 904 /* Usage: 905 * <div class="sparkline-line txt-color-blue" data-fill-color="transparent" data-sparkline-height="26px"> 906 * 5,6,7,9,9,5,9,6,5,6,6,7,7,6,7,8,9,7 907 * </div> 908 */ 909 910 if ($.fn.sparkline) { 911 912 // variable declearations: 913 914 var barColor, 915 sparklineHeight, 916 sparklineBarWidth, 917 sparklineBarSpacing, 918 sparklineNegBarColor, 919 sparklineStackedColor, 920 thisLineColor, 921 thisLineWidth, 922 thisFill, 923 thisSpotColor, 924 thisMinSpotColor, 925 thisMaxSpotColor, 926 thishighlightSpotColor, 927 thisHighlightLineColor, 928 thisSpotRadius, 929 pieColors, 930 pieWidthHeight, 931 pieBorderColor, 932 pieOffset, 933 thisBoxWidth, 934 thisBoxHeight, 935 thisBoxRaw, 936 thisBoxTarget, 937 thisBoxMin, 938 thisBoxMax, 939 thisShowOutlier, 940 thisIQR, 941 thisBoxSpotRadius, 942 thisBoxLineColor, 943 thisBoxFillColor, 944 thisBoxWhisColor, 945 thisBoxOutlineColor, 946 thisBoxOutlineFill, 947 thisBoxMedianColor, 948 thisBoxTargetColor, 949 thisBulletHeight, 950 thisBulletWidth, 951 thisBulletColor, 952 thisBulletPerformanceColor, 953 thisBulletRangeColors, 954 thisDiscreteHeight, 955 thisDiscreteWidth, 956 thisDiscreteLineColor, 957 thisDiscreteLineHeight, 958 thisDiscreteThrushold, 959 thisDiscreteThrusholdColor, 960 thisTristateHeight, 961 thisTristatePosBarColor, 962 thisTristateNegBarColor, 963 thisTristateZeroBarColor, 964 thisTristateBarWidth, 965 thisTristateBarSpacing, 966 thisZeroAxis, 967 thisBarColor, 968 sparklineWidth, 969 sparklineValue, 970 sparklineValueSpots1, 971 sparklineValueSpots2, 972 thisLineWidth1, 973 thisLineWidth2, 974 thisLineColor1, 975 thisLineColor2, 976 thisSpotRadius1, 977 thisSpotRadius2, 978 thisMinSpotColor1, 979 thisMaxSpotColor1, 980 thisMinSpotColor2, 981 thisMaxSpotColor2, 982 thishighlightSpotColor1, 983 thisHighlightLineColor1, 984 thishighlightSpotColor2, 985 thisFillColor1, 986 thisFillColor2; 987 988 $('.sparkline:not(:has(>canvas))').each(function() { 989 var $this = $(this), 990 sparklineType = $this.data('sparkline-type') || 'bar'; 991 992 // BAR CHART 993 if (sparklineType == 'bar') { 994 995 barColor = $this.data('sparkline-bar-color') || $this.css('color') || '#0000f0'; 996 sparklineHeight = $this.data('sparkline-height') || '26px'; 997 sparklineBarWidth = $this.data('sparkline-barwidth') || 5; 998 sparklineBarSpacing = $this.data('sparkline-barspacing') || 2; 999 sparklineNegBarColor = $this.data('sparkline-negbar-color') || '#A90329'; 1000 sparklineStackedColor = $this.data('sparkline-barstacked-color') || ["#A90329", "#0099c6", "#98AA56", "#da532c", "#4490B1", "#6E9461", "#990099", "#B4CAD3"]; 1001 1002 $this.sparkline('html', { 1003 barColor : barColor, 1004 type : sparklineType, 1005 height : sparklineHeight, 1006 barWidth : sparklineBarWidth, 1007 barSpacing : sparklineBarSpacing, 1008 stackedBarColor : sparklineStackedColor, 1009 negBarColor : sparklineNegBarColor, 1010 zeroAxis : 'false' 1011 }); 1012 1013 $this = null; 1014 1015 } 1016 1017 // LINE CHART 1018 if (sparklineType == 'line') { 1019 1020 sparklineHeight = $this.data('sparkline-height') || '20px'; 1021 sparklineWidth = $this.data('sparkline-width') || '90px'; 1022 thisLineColor = $this.data('sparkline-line-color') || $this.css('color') || '#0000f0'; 1023 thisLineWidth = $this.data('sparkline-line-width') || 1; 1024 thisFill = $this.data('fill-color') || '#c0d0f0'; 1025 thisSpotColor = $this.data('sparkline-spot-color') || '#f08000'; 1026 thisMinSpotColor = $this.data('sparkline-minspot-color') || '#ed1c24'; 1027 thisMaxSpotColor = $this.data('sparkline-maxspot-color') || '#f08000'; 1028 thishighlightSpotColor = $this.data('sparkline-highlightspot-color') || '#50f050'; 1029 thisHighlightLineColor = $this.data('sparkline-highlightline-color') || 'f02020'; 1030 thisSpotRadius = $this.data('sparkline-spotradius') || 1.5; 1031 thisChartMinYRange = $this.data('sparkline-min-y') || 'undefined'; 1032 thisChartMaxYRange = $this.data('sparkline-max-y') || 'undefined'; 1033 thisChartMinXRange = $this.data('sparkline-min-x') || 'undefined'; 1034 thisChartMaxXRange = $this.data('sparkline-max-x') || 'undefined'; 1035 thisMinNormValue = $this.data('min-val') || 'undefined'; 1036 thisMaxNormValue = $this.data('max-val') || 'undefined'; 1037 thisNormColor = $this.data('norm-color') || '#c0c0c0'; 1038 thisDrawNormalOnTop = $this.data('draw-normal') || false; 1039 1040 $this.sparkline('html', { 1041 type : 'line', 1042 width : sparklineWidth, 1043 height : sparklineHeight, 1044 lineWidth : thisLineWidth, 1045 lineColor : thisLineColor, 1046 fillColor : thisFill, 1047 spotColor : thisSpotColor, 1048 minSpotColor : thisMinSpotColor, 1049 maxSpotColor : thisMaxSpotColor, 1050 highlightSpotColor : thishighlightSpotColor, 1051 highlightLineColor : thisHighlightLineColor, 1052 spotRadius : thisSpotRadius, 1053 chartRangeMin : thisChartMinYRange, 1054 chartRangeMax : thisChartMaxYRange, 1055 chartRangeMinX : thisChartMinXRange, 1056 chartRangeMaxX : thisChartMaxXRange, 1057 normalRangeMin : thisMinNormValue, 1058 normalRangeMax : thisMaxNormValue, 1059 normalRangeColor : thisNormColor, 1060 drawNormalOnTop : thisDrawNormalOnTop 1061 1062 }); 1063 1064 $this = null; 1065 1066 } 1067 1068 // PIE CHART 1069 if (sparklineType == 'pie') { 1070 1071 pieColors = $this.data('sparkline-piecolor') || ["#B4CAD3", "#4490B1", "#98AA56", "#da532c","#6E9461", "#0099c6", "#990099", "#717D8A"]; 1072 pieWidthHeight = $this.data('sparkline-piesize') || 90; 1073 pieBorderColor = $this.data('border-color') || '#45494C'; 1074 pieOffset = $this.data('sparkline-offset') || 0; 1075 1076 $this.sparkline('html', { 1077 type : 'pie', 1078 width : pieWidthHeight, 1079 height : pieWidthHeight, 1080 tooltipFormat : '<span style="color: {{color}}">●</span> ({{percent.1}}%)', 1081 sliceColors : pieColors, 1082 borderWidth : 1, 1083 offset : pieOffset, 1084 borderColor : pieBorderColor 1085 }); 1086 1087 $this = null; 1088 1089 } 1090 1091 // BOX PLOT 1092 if (sparklineType == 'box') { 1093 1094 thisBoxWidth = $this.data('sparkline-width') || 'auto'; 1095 thisBoxHeight = $this.data('sparkline-height') || 'auto'; 1096 thisBoxRaw = $this.data('sparkline-boxraw') || false; 1097 thisBoxTarget = $this.data('sparkline-targetval') || 'undefined'; 1098 thisBoxMin = $this.data('sparkline-min') || 'undefined'; 1099 thisBoxMax = $this.data('sparkline-max') || 'undefined'; 1100 thisShowOutlier = $this.data('sparkline-showoutlier') || true; 1101 thisIQR = $this.data('sparkline-outlier-iqr') || 1.5; 1102 thisBoxSpotRadius = $this.data('sparkline-spotradius') || 1.5; 1103 thisBoxLineColor = $this.css('color') || '#000000'; 1104 thisBoxFillColor = $this.data('fill-color') || '#c0d0f0'; 1105 thisBoxWhisColor = $this.data('sparkline-whis-color') || '#000000'; 1106 thisBoxOutlineColor = $this.data('sparkline-outline-color') || '#303030'; 1107 thisBoxOutlineFill = $this.data('sparkline-outlinefill-color') || '#f0f0f0'; 1108 thisBoxMedianColor = $this.data('sparkline-outlinemedian-color') || '#f00000'; 1109 thisBoxTargetColor = $this.data('sparkline-outlinetarget-color') || '#40a020'; 1110 1111 $this.sparkline('html', { 1112 type : 'box', 1113 width : thisBoxWidth, 1114 height : thisBoxHeight, 1115 raw : thisBoxRaw, 1116 target : thisBoxTarget, 1117 minValue : thisBoxMin, 1118 maxValue : thisBoxMax, 1119 showOutliers : thisShowOutlier, 1120 outlierIQR : thisIQR, 1121 spotRadius : thisBoxSpotRadius, 1122 boxLineColor : thisBoxLineColor, 1123 boxFillColor : thisBoxFillColor, 1124 whiskerColor : thisBoxWhisColor, 1125 outlierLineColor : thisBoxOutlineColor, 1126 outlierFillColor : thisBoxOutlineFill, 1127 medianColor : thisBoxMedianColor, 1128 targetColor : thisBoxTargetColor 1129 1130 }); 1131 1132 $this = null; 1133 1134 } 1135 1136 // BULLET 1137 if (sparklineType == 'bullet') { 1138 1139 var thisBulletHeight = $this.data('sparkline-height') || 'auto'; 1140 thisBulletWidth = $this.data('sparkline-width') || 2; 1141 thisBulletColor = $this.data('sparkline-bullet-color') || '#ed1c24'; 1142 thisBulletPerformanceColor = $this.data('sparkline-performance-color') || '#3030f0'; 1143 thisBulletRangeColors = $this.data('sparkline-bulletrange-color') || ["#d3dafe", "#a8b6ff", "#7f94ff"]; 1144 1145 $this.sparkline('html', { 1146 1147 type : 'bullet', 1148 height : thisBulletHeight, 1149 targetWidth : thisBulletWidth, 1150 targetColor : thisBulletColor, 1151 performanceColor : thisBulletPerformanceColor, 1152 rangeColors : thisBulletRangeColors 1153 1154 }); 1155 1156 $this = null; 1157 1158 } 1159 1160 // DISCRETE 1161 if (sparklineType == 'discrete') { 1162 1163 thisDiscreteHeight = $this.data('sparkline-height') || 26; 1164 thisDiscreteWidth = $this.data('sparkline-width') || 50; 1165 thisDiscreteLineColor = $this.css('color'); 1166 thisDiscreteLineHeight = $this.data('sparkline-line-height') || 5; 1167 thisDiscreteThrushold = $this.data('sparkline-threshold') || 'undefined'; 1168 thisDiscreteThrusholdColor = $this.data('sparkline-threshold-color') || '#ed1c24'; 1169 1170 $this.sparkline('html', { 1171 1172 type : 'discrete', 1173 width : thisDiscreteWidth, 1174 height : thisDiscreteHeight, 1175 lineColor : thisDiscreteLineColor, 1176 lineHeight : thisDiscreteLineHeight, 1177 thresholdValue : thisDiscreteThrushold, 1178 thresholdColor : thisDiscreteThrusholdColor 1179 1180 }); 1181 1182 $this = null; 1183 1184 } 1185 1186 // TRISTATE 1187 if (sparklineType == 'tristate') { 1188 1189 thisTristateHeight = $this.data('sparkline-height') || 26; 1190 thisTristatePosBarColor = $this.data('sparkline-posbar-color') || '#60f060'; 1191 thisTristateNegBarColor = $this.data('sparkline-negbar-color') || '#f04040'; 1192 thisTristateZeroBarColor = $this.data('sparkline-zerobar-color') || '#909090'; 1193 thisTristateBarWidth = $this.data('sparkline-barwidth') || 5; 1194 thisTristateBarSpacing = $this.data('sparkline-barspacing') || 2; 1195 thisZeroAxis = $this.data('sparkline-zeroaxis') || false; 1196 1197 $this.sparkline('html', { 1198 1199 type : 'tristate', 1200 height : thisTristateHeight, 1201 posBarColor : thisBarColor, 1202 negBarColor : thisTristateNegBarColor, 1203 zeroBarColor : thisTristateZeroBarColor, 1204 barWidth : thisTristateBarWidth, 1205 barSpacing : thisTristateBarSpacing, 1206 zeroAxis : thisZeroAxis 1207 1208 }); 1209 1210 $this = null; 1211 1212 } 1213 1214 //COMPOSITE: BAR 1215 if (sparklineType == 'compositebar') { 1216 1217 sparklineHeight = $this.data('sparkline-height') || '20px'; 1218 sparklineWidth = $this.data('sparkline-width') || '100%'; 1219 sparklineBarWidth = $this.data('sparkline-barwidth') || 3; 1220 thisLineWidth = $this.data('sparkline-line-width') || 1; 1221 thisLineColor = $this.data('data-sparkline-linecolor') || '#ed1c24'; 1222 thisBarColor = $this.data('data-sparkline-barcolor') || '#333333'; 1223 1224 $this.sparkline($this.data('sparkline-bar-val'), { 1225 1226 type : 'bar', 1227 width : sparklineWidth, 1228 height : sparklineHeight, 1229 barColor : thisBarColor, 1230 barWidth : sparklineBarWidth 1231 //barSpacing: 5 1232 1233 }); 1234 1235 $this.sparkline($this.data('sparkline-line-val'), { 1236 1237 width : sparklineWidth, 1238 height : sparklineHeight, 1239 lineColor : thisLineColor, 1240 lineWidth : thisLineWidth, 1241 composite : true, 1242 fillColor : false 1243 1244 }); 1245 1246 $this = null; 1247 1248 } 1249 1250 //COMPOSITE: LINE 1251 if (sparklineType == 'compositeline') { 1252 1253 sparklineHeight = $this.data('sparkline-height') || '20px'; 1254 sparklineWidth = $this.data('sparkline-width') || '90px'; 1255 sparklineValue = $this.data('sparkline-bar-val'); 1256 sparklineValueSpots1 = $this.data('sparkline-bar-val-spots-top') || null; 1257 sparklineValueSpots2 = $this.data('sparkline-bar-val-spots-bottom') || null; 1258 thisLineWidth1 = $this.data('sparkline-line-width-top') || 1; 1259 thisLineWidth2 = $this.data('sparkline-line-width-bottom') || 1; 1260 thisLineColor1 = $this.data('sparkline-color-top') || '#333333'; 1261 thisLineColor2 = $this.data('sparkline-color-bottom') || '#ed1c24'; 1262 thisSpotRadius1 = $this.data('sparkline-spotradius-top') || 1.5; 1263 thisSpotRadius2 = $this.data('sparkline-spotradius-bottom') || thisSpotRadius1; 1264 thisSpotColor = $this.data('sparkline-spot-color') || '#f08000'; 1265 thisMinSpotColor1 = $this.data('sparkline-minspot-color-top') || '#ed1c24'; 1266 thisMaxSpotColor1 = $this.data('sparkline-maxspot-color-top') || '#f08000'; 1267 thisMinSpotColor2 = $this.data('sparkline-minspot-color-bottom') || thisMinSpotColor1; 1268 thisMaxSpotColor2 = $this.data('sparkline-maxspot-color-bottom') || thisMaxSpotColor1; 1269 thishighlightSpotColor1 = $this.data('sparkline-highlightspot-color-top') || '#50f050'; 1270 thisHighlightLineColor1 = $this.data('sparkline-highlightline-color-top') || '#f02020'; 1271 thishighlightSpotColor2 = $this.data('sparkline-highlightspot-color-bottom') || 1272 thishighlightSpotColor1; 1273 thisHighlightLineColor2 = $this.data('sparkline-highlightline-color-bottom') || 1274 thisHighlightLineColor1; 1275 thisFillColor1 = $this.data('sparkline-fillcolor-top') || 'transparent'; 1276 thisFillColor2 = $this.data('sparkline-fillcolor-bottom') || 'transparent'; 1277 1278 $this.sparkline(sparklineValue, { 1279 1280 type : 'line', 1281 spotRadius : thisSpotRadius1, 1282 1283 spotColor : thisSpotColor, 1284 minSpotColor : thisMinSpotColor1, 1285 maxSpotColor : thisMaxSpotColor1, 1286 highlightSpotColor : thishighlightSpotColor1, 1287 highlightLineColor : thisHighlightLineColor1, 1288 1289 valueSpots : sparklineValueSpots1, 1290 1291 lineWidth : thisLineWidth1, 1292 width : sparklineWidth, 1293 height : sparklineHeight, 1294 lineColor : thisLineColor1, 1295 fillColor : thisFillColor1 1296 1297 }); 1298 1299 $this.sparkline($this.data('sparkline-line-val'), { 1300 1301 type : 'line', 1302 spotRadius : thisSpotRadius2, 1303 1304 spotColor : thisSpotColor, 1305 minSpotColor : thisMinSpotColor2, 1306 maxSpotColor : thisMaxSpotColor2, 1307 highlightSpotColor : thishighlightSpotColor2, 1308 highlightLineColor : thisHighlightLineColor2, 1309 1310 valueSpots : sparklineValueSpots2, 1311 1312 lineWidth : thisLineWidth2, 1313 width : sparklineWidth, 1314 height : sparklineHeight, 1315 lineColor : thisLineColor2, 1316 composite : true, 1317 fillColor : thisFillColor2 1318 1319 }); 1320 1321 $this = null; 1322 1323 } 1324 1325 }); 1326 1327 }// end if 1328 1329 /* 1330 * EASY PIE CHARTS 1331 * DEPENDENCY: js/plugins/easy-pie-chart/jquery.easy-pie-chart.min.js 1332 * Usage: <div class="easy-pie-chart txt-color-orangeDark" data-pie-percent="33" data-pie-size="72" data-size="72"> 1333 * <span class="percent percent-sign">35</span> 1334 * </div> 1335 */ 1336 1337 if ($.fn.easyPieChart) { 1338 1339 $('.easy-pie-chart').each(function() { 1340 var $this = $(this), 1341 barColor = $this.css('color') || $this.data('pie-color'), 1342 trackColor = $this.data('pie-track-color') || 'rgba(0,0,0,0.04)', 1343 size = parseInt($this.data('pie-size')) || 25; 1344 1345 $this.easyPieChart({ 1346 1347 barColor : barColor, 1348 trackColor : trackColor, 1349 scaleColor : false, 1350 lineCap : 'butt', 1351 lineWidth : parseInt(size / 8.5), 1352 animate : 1500, 1353 rotate : -90, 1354 size : size, 1355 onStep: function(from, to, percent) { 1356 $(this.el).find('.percent').text(Math.round(percent)); 1357 } 1358 1359 }); 1360 1361 $this = null; 1362 }); 1363 1364 } // end if 1365 1366 } 1367 /* ~ END: INITIALIZE CHARTS */ 1368 1369 /* 1370 * INITIALIZE JARVIS WIDGETS 1371 * Setup Desktop Widgets 1372 */ 1373 function setup_widgets_desktop() { 1374 1375 if ($.fn.jarvisWidgets && enableJarvisWidgets) { 1376 1377 $('#widget-grid').jarvisWidgets({ 1378 1379 grid : 'article', 1380 widgets : '.jarviswidget', 1381 localStorage : localStorageJarvisWidgets, 1382 deleteSettingsKey : '#deletesettingskey-options', 1383 settingsKeyLabel : 'Reset settings?', 1384 deletePositionKey : '#deletepositionkey-options', 1385 positionKeyLabel : 'Reset position?', 1386 sortable : sortableJarvisWidgets, 1387 buttonsHidden : false, 1388 // toggle button 1389 toggleButton : true, 1390 toggleClass : 'fa fa-minus | fa fa-plus', 1391 toggleSpeed : 200, 1392 onToggle : function() { 1393 }, 1394 // delete btn 1395 deleteButton : true, 1396 deleteMsg:'Warning: This action cannot be undone!', 1397 deleteClass : 'fa fa-times', 1398 deleteSpeed : 200, 1399 onDelete : function() { 1400 }, 1401 // edit btn 1402 editButton : true, 1403 editPlaceholder : '.jarviswidget-editbox', 1404 editClass : 'fa fa-cog | fa fa-save', 1405 editSpeed : 200, 1406 onEdit : function() { 1407 }, 1408 // color button 1409 colorButton : true, 1410 // full screen 1411 fullscreenButton : true, 1412 fullscreenClass : 'fa fa-expand | fa fa-compress', 1413 fullscreenDiff : 3, 1414 onFullscreen : function() { 1415 }, 1416 // custom btn 1417 customButton : false, 1418 customClass : 'folder-10 | next-10', 1419 customStart : function() { 1420 alert('Hello you, this is a custom button...'); 1421 }, 1422 customEnd : function() { 1423 alert('bye, till next time...'); 1424 }, 1425 // order 1426 buttonOrder : '%refresh% %custom% %edit% %toggle% %fullscreen% %delete%', 1427 opacity : 1.0, 1428 dragHandle : '> header', 1429 placeholderClass : 'jarviswidget-placeholder', 1430 indicator : true, 1431 indicatorTime : 600, 1432 ajax : true, 1433 timestampPlaceholder : '.jarviswidget-timestamp', 1434 timestampFormat : 'Last update: %m%/%d%/%y% %h%:%i%:%s%', 1435 refreshButton : true, 1436 refreshButtonClass : 'fa fa-refresh', 1437 labelError : 'Sorry but there was a error:', 1438 labelUpdated : 'Last Update:', 1439 labelRefresh : 'Refresh', 1440 labelDelete : 'Delete widget:', 1441 afterLoad : function() { 1442 }, 1443 rtl : false, // best not to toggle this! 1444 onChange : function() { 1445 1446 }, 1447 onSave : function() { 1448 1449 }, 1450 ajaxnav : $.navAsAjax // declears how the localstorage should be saved (HTML or AJAX Version) 1451 1452 }); 1453 1454 } 1455 1456 } 1457 /* 1458 * SETUP DESKTOP WIDGET 1459 */ 1460 function setup_widgets_mobile() { 1461 1462 if (enableMobileWidgets && enableJarvisWidgets) { 1463 setup_widgets_desktop(); 1464 } 1465 1466 } 1467 /* ~ END: INITIALIZE JARVIS WIDGETS */ 1468 1469 /* 1470 * GOOGLE MAPS 1471 * description: Append google maps to head dynamically (only execute for ajax version) 1472 * Loads at the begining for ajax pages 1473 */ 1474 if ($.navAsAjax || $(".google_maps")){ 1475 var gMapsLoaded = false; 1476 window.gMapsCallback = function() { 1477 gMapsLoaded = true; 1478 $(window).trigger('gMapsLoaded'); 1479 }; 1480 window.loadGoogleMaps = function() { 1481 if (gMapsLoaded) 1482 return window.gMapsCallback(); 1483 var script_tag = document.createElement('script'); 1484 script_tag.setAttribute("type", "text/javascript"); 1485 script_tag.setAttribute("src", "http://maps.google.com/maps/api/js?sensor=false&callback=gMapsCallback"); 1486 (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag); 1487 }; 1488 } 1489 /* ~ END: GOOGLE MAPS */ 1490 1491 /* 1492 * LOAD SCRIPTS 1493 * Usage: 1494 * Define function = myPrettyCode ()... 1495 * loadScript("js/my_lovely_script.js", myPrettyCode); 1496 */ 1497 function loadScript(scriptName, callback) { 1498 1499 if (!jsArray[scriptName]) { 1500 jsArray[scriptName] = true; 1501 1502 // adding the script tag to the head as suggested before 1503 var body = document.getElementsByTagName('body')[0], 1504 script = document.createElement('script'); 1505 script.type = 'text/javascript'; 1506 script.src = scriptName; 1507 1508 // then bind the event to the callback function 1509 // there are several events for cross browser compatibility 1510 script.onload = callback; 1511 1512 // fire the loading 1513 body.appendChild(script); 1514 1515 // clear DOM reference 1516 //body = null; 1517 //script = null; 1518 1519 } else if (callback) { 1520 // changed else to else if(callback) 1521 if (debugState){ 1522 root.root.console.log("This script was already loaded %c: " + scriptName, debugStyle_warning); 1523 } 1524 //execute function 1525 callback(); 1526 } 1527 1528 } 1529 /* ~ END: LOAD SCRIPTS */ 1530 1531 /* 1532 * APP AJAX REQUEST SETUP 1533 * Description: Executes and fetches all ajax requests also 1534 * updates naivgation elements to active 1535 */ 1536 if($.navAsAjax) { 1537 // fire this on page load if nav exists 1538 if ($('nav').length) { 1539 checkURL(); 1540 } 1541 1542 $(document).on('click', 'nav a[href!="#"]', function(e) { 1543 e.preventDefault(); 1544 var $this = $(e.currentTarget); 1545 1546 // if parent is not active then get hash, or else page is assumed to be loaded 1547 if (!$this.parent().hasClass("active") && !$this.attr('target')) { 1548 1549 // update window with hash 1550 // you could also do here: thisDevice === "mobile" - and save a little more memory 1551 1552 if ($.root_.hasClass('mobile-view-activated')) { 1553 $.root_.removeClass('hidden-menu'); 1554 $('html').removeClass("hidden-menu-mobile-lock"); 1555 window.setTimeout(function() { 1556 if (window.location.search) { 1557 window.location.href = 1558 window.location.href.replace(window.location.search, '') 1559 .replace(window.location.hash, '') + '#' + $this.attr('href'); 1560 } else { 1561 window.location.hash = $this.attr('href'); 1562 } 1563 }, 150); 1564 // it may not need this delay... 1565 } else { 1566 if (window.location.search) { 1567 window.location.href = 1568 window.location.href.replace(window.location.search, '') 1569 .replace(window.location.hash, '') + '#' + $this.attr('href'); 1570 } else { 1571 window.location.hash = $this.attr('href'); 1572 } 1573 } 1574 1575 // clear DOM reference 1576 // $this = null; 1577 } 1578 1579 }); 1580 1581 // fire links with targets on different window 1582 $(document).on('click', 'nav a[target="_blank"]', function(e) { 1583 e.preventDefault(); 1584 var $this = $(e.currentTarget); 1585 1586 window.open($this.attr('href')); 1587 }); 1588 1589 // fire links with targets on same window 1590 $(document).on('click', 'nav a[target="_top"]', function(e) { 1591 e.preventDefault(); 1592 var $this = $(e.currentTarget); 1593 1594 window.location = ($this.attr('href')); 1595 }); 1596 1597 // all links with hash tags are ignored 1598 $(document).on('click', 'nav a[href="#"]', function(e) { 1599 e.preventDefault(); 1600 }); 1601 1602 // DO on hash change 1603 $(window).on('hashchange', function() { 1604 checkURL(); 1605 }); 1606 } 1607 /* 1608 * CHECK TO SEE IF URL EXISTS 1609 */ 1610 function checkURL() { 1611 1612 //get the url by removing the hash 1613 //var url = location.hash.replace(/^#/, ''); 1614 var url = location.href.split('#').splice(1).join('#'); 1615 //BEGIN: IE11 Work Around 1616 if (!url) { 1617 1618 try { 1619 var documentUrl = window.document.URL; 1620 if (documentUrl) { 1621 if (documentUrl.indexOf('#', 0) > 0 && documentUrl.indexOf('#', 0) < (documentUrl.length + 1)) { 1622 url = documentUrl.substring(documentUrl.indexOf('#', 0) + 1); 1623 1624 } 1625 1626 } 1627 1628 } catch (err) {} 1629 } 1630 //END: IE11 Work Around 1631 1632 container = $('#content'); 1633 // Do this if url exists (for page refresh, etc...) 1634 if (url) { 1635 // remove all active class 1636 $('nav li.active').removeClass("active"); 1637 // match the url and add the active class 1638 $('nav li:has(a[href="' + url + '"])').addClass("active"); 1639 var title = ($('nav a[href="' + url + '"]').attr('title')); 1640 1641 // change page title from global var 1642 document.title = (title || document.title); 1643 1644 // debugState 1645 if (debugState){ 1646 root.console.log("Page title: %c " + document.title, debugStyle_green); 1647 } 1648 1649 // parse url to jquery 1650 loadURL(url + location.search, container); 1651 1652 } else { 1653 1654 // grab the first URL from nav 1655 var $this = $('nav > ul > li:first-child > a[href!="#"]'); 1656 1657 //update hash 1658 window.location.hash = $this.attr('href'); 1659 1660 //clear dom reference 1661 $this = null; 1662 1663 } 1664 1665 } 1666 /* 1667 * LOAD AJAX PAGES 1668 */ 1669 function loadURL(url, container) { 1670 1671 // debugState 1672 if (debugState){ 1673 root.root.console.log("Loading URL: %c" + url, debugStyle); 1674 } 1675 1676 $.ajax({ 1677 type : "GET", 1678 url : url, 1679 dataType : 'html', 1680 cache : true, // (warning: setting it to false will cause a timestamp and will call the request twice) 1681 beforeSend : function() { 1682 1683 //IE11 bug fix for googlemaps (delete all google map instances) 1684 //check if the page is ajax = true, has google map class and the container is #content 1685 if ($.navAsAjax && $(".google_maps")[0] && (container[0] == $("#content")[0]) ) { 1686 1687 // target gmaps if any on page 1688 var collection = $(".google_maps"), 1689 i = 0; 1690 // run for each map 1691 collection.each(function() { 1692 i ++; 1693 // get map id from class elements 1694 var divDealerMap = document.getElementById(this.id); 1695 1696 if(i == collection.length + 1) { 1697 // "callback" 1698 } else { 1699 // destroy every map found 1700 if (divDealerMap) divDealerMap.parentNode.removeChild(divDealerMap); 1701 1702 // debugState 1703 if (debugState){ 1704 root.console.log("Destroying maps.........%c" + this.id, debugStyle_warning); 1705 } 1706 } 1707 }); 1708 1709 // debugState 1710 if (debugState){ 1711 root.console.log("✔ Google map instances nuked!!!"); 1712 } 1713 1714 } //end fix 1715 1716 // destroy all datatable instances 1717 if ( $.navAsAjax && $('.dataTables_wrapper')[0] && (container[0] == $("#content")[0]) ) { 1718 1719 var tables = $.fn.dataTable.fnTables(true); 1720 $(tables).each(function () { 1721 1722 if($(this).find('.details-control').length != 0) { 1723 $(this).find('*').addBack().off().remove(); 1724 $(this).dataTable().fnDestroy(); 1725 } else { 1726 $(this).dataTable().fnDestroy(); 1727 } 1728 1729 }); 1730 1731 // debugState 1732 if (debugState){ 1733 root.console.log("✔ Datatable instances nuked!!!"); 1734 } 1735 } 1736 // end destroy 1737 1738 // pop intervals (destroys jarviswidget related intervals) 1739 if ( $.navAsAjax && $.intervalArr.length > 0 && (container[0] == $("#content")[0]) && enableJarvisWidgets ) { 1740 1741 while($.intervalArr.length > 0) 1742 clearInterval($.intervalArr.pop()); 1743 // debugState 1744 if (debugState){ 1745 root.console.log("✔ All JarvisWidget intervals cleared"); 1746 } 1747 1748 } 1749 // end pop intervals 1750 1751 // destroy all widget instances 1752 if ( $.navAsAjax && (container[0] == $("#content")[0]) && enableJarvisWidgets && $("#widget-grid")[0] ) { 1753 1754 $("#widget-grid").jarvisWidgets('destroy'); 1755 // debugState 1756 if (debugState){ 1757 root.console.log("✔ JarvisWidgets destroyed"); 1758 } 1759 1760 } 1761 // end destroy all widgets 1762 1763 // cluster destroy: destroy other instances that could be on the page 1764 // this runs a script in the current loaded page before fetching the new page 1765 if ( $.navAsAjax && (container[0] == $("#content")[0]) ) { 1766 1767 /* 1768 * The following elements should be removed, if they have been created: 1769 * 1770 * colorList 1771 * icon 1772 * picker 1773 * inline 1774 * And unbind events from elements: 1775 * 1776 * icon 1777 * picker 1778 * inline 1779 * especially $(document).on('mousedown') 1780 * It will be much easier to add namespace to plugin events and then unbind using selected namespace. 1781 * 1782 * See also: 1783 * 1784 * http://f6design.com/journal/2012/05/06/a-jquery-plugin-boilerplate/ 1785 * http://keith-wood.name/pluginFramework.html 1786 */ 1787 1788 // this function is below the pagefunction for all pages that has instances 1789 1790 if (typeof pagedestroy == 'function') { 1791 1792 try { 1793 pagedestroy(); 1794 1795 if (debugState){ 1796 root.console.log("✔ Pagedestroy()"); 1797 } 1798 } 1799 catch(err) { 1800 pagedestroy = undefined; 1801 1802 if (debugState){ 1803 root.console.log("! Pagedestroy() Catch Error"); 1804 } 1805 } 1806 1807 } 1808 1809 // destroy all inline charts 1810 1811 if ( $.fn.sparkline && $("#content .sparkline")[0] ) { 1812 $("#content .sparkline").sparkline( 'destroy' ); 1813 1814 if (debugState){ 1815 root.console.log("✔ Sparkline Charts destroyed!"); 1816 } 1817 } 1818 1819 if ( $.fn.easyPieChart && $("#content .easy-pie-chart")[0] ) { 1820 $("#content .easy-pie-chart").easyPieChart( 'destroy' ); 1821 1822 if (debugState){ 1823 root.console.log("✔ EasyPieChart Charts destroyed!"); 1824 } 1825 } 1826 1827 1828 1829 // end destory all inline charts 1830 1831 // destroy form controls: Datepicker, select2, autocomplete, mask, bootstrap slider 1832 1833 if ( $.fn.select2 && $("#content select.select2")[0] ) { 1834 $("#content select.select2").select2('destroy'); 1835 1836 if (debugState){ 1837 root.console.log("✔ Select2 destroyed!"); 1838 } 1839 } 1840 1841 if ( $.fn.mask && $('#content [data-mask]')[0] ) { 1842 $('#content [data-mask]').unmask(); 1843 1844 if (debugState){ 1845 root.console.log("✔ Input Mask destroyed!"); 1846 } 1847 } 1848 1849 if ( $.fn.datepicker && $('#content .datepicker')[0] ) { 1850 $('#content .datepicker').off(); 1851 $('#content .datepicker').remove(); 1852 1853 if (debugState){ 1854 root.console.log("✔ Datepicker destroyed!"); 1855 } 1856 } 1857 1858 if ( $.fn.slider && $('#content .slider')[0] ) { 1859 $('#content .slider').off(); 1860 $('#content .slider').remove(); 1861 1862 if (debugState){ 1863 root.console.log("✔ Bootstrap Slider destroyed!"); 1864 } 1865 } 1866 1867 // end destroy form controls 1868 1869 1870 } 1871 // end cluster destroy 1872 1873 // empty container and var to start garbage collection (frees memory) 1874 pagefunction = null; 1875 container.removeData().html(""); 1876 1877 // place cog 1878 container.html('<h1 class="ajax-loading-animation"><i class="fa fa-cog fa-spin"></i> Loading...</h1>'); 1879 1880 // Only draw breadcrumb if it is main content material 1881 if (container[0] == $("#content")[0]) { 1882 1883 // clear everything else except these key DOM elements 1884 // we do this because sometime plugins will leave dynamic elements behind 1885 $('body').find('> *').filter(':not(' + ignore_key_elms + ')').empty().remove(); 1886 1887 // draw breadcrumb 1888 drawBreadCrumb(); 1889 1890 // scroll up 1891 $("html").animate({ 1892 scrollTop : 0 1893 }, "fast"); 1894 } 1895 // end if 1896 }, 1897 success : function(data) { 1898 1899 // dump data to container 1900 container.css({ 1901 opacity : '0.0' 1902 }).html(data).delay(50).animate({ 1903 opacity : '1.0' 1904 }, 300); 1905 1906 // clear data var 1907 data = null; 1908 container = null; 1909 }, 1910 error : function(xhr, status, thrownError, error) { 1911 container.html('<h4 class="ajax-loading-error"><i class="fa fa-warning txt-color-orangeDark"></i> Error requesting <span class="txt-color-red">' + url + '</span>: ' + xhr.status + ' <span style="text-transform: capitalize;">' + thrownError + '</span></h4>'); 1912 }, 1913 async : true 1914 }); 1915 1916 } 1917 /* 1918 * UPDATE BREADCRUMB 1919 */ 1920 function drawBreadCrumb(opt_breadCrumbs) { 1921 var a = $("nav li.active > a"), 1922 b = a.length; 1923 1924 bread_crumb.empty(), 1925 bread_crumb.append($("<li>Home</li>")), a.each(function() { 1926 bread_crumb.append($("<li></li>").html($.trim($(this).clone().children(".badge").remove().end().text()))), --b || (document.title = bread_crumb.find("li:last-child").text()) 1927 }); 1928 1929 // Push breadcrumb manually -> drawBreadCrumb(["Users", "John Doe"]); 1930 // Credits: Philip Whitt | philip.whitt@sbcglobal.net 1931 if (opt_breadCrumbs != undefined) { 1932 $.each(opt_breadCrumbs, function(index, value) { 1933 bread_crumb.append($("<li></li>").html(value)); 1934 document.title = bread_crumb.find("li:last-child").text(); 1935 }); 1936 } 1937 } 1938 /* ~ END: APP AJAX REQUEST SETUP */ 1939 1940 /* 1941 * PAGE SETUP 1942 * Description: fire certain scripts that run through the page 1943 * to check for form elements, tooltip activation, popovers, etc... 1944 */ 1945 function pageSetUp() { 1946 if (thisDevice === "desktop"){ 1947 // is desktop 1948 1949 // activate tooltips 1950 $("[rel=tooltip], [data-rel=tooltip]").tooltip(); 1951 1952 // activate popovers 1953 $("[rel=popover], [data-rel=popover]").popover(); 1954 1955 // activate popovers with hover states 1956 $("[rel=popover-hover], [data-rel=popover-hover]").popover({ 1957 trigger : "hover" 1958 }); 1959 1960 // setup widgets 1961 setup_widgets_desktop(); 1962 1963 // activate inline charts 1964 runAllCharts(); 1965 1966 // run form elements 1967 runAllForms(); 1968 1969 } else { 1970 1971 // is mobile 1972 1973 // activate popovers 1974 $("[rel=popover], [data-rel=popover]").popover(); 1975 1976 // activate popovers with hover states 1977 $("[rel=popover-hover], [data-rel=popover-hover]").popover({ 1978 trigger : "hover" 1979 }); 1980 1981 // activate inline charts 1982 runAllCharts(); 1983 1984 // setup widgets 1985 setup_widgets_mobile(); 1986 1987 // run form elements 1988 runAllForms(); 1989 1990 } 1991 1992 } 1993 /* ~ END: PAGE SETUP */ 1994 1995 /* 1996 * ONE POP OVER THEORY 1997 * Keep only 1 active popover per trigger - also check and hide active popover if user clicks on document 1998 */ 1999 $('body').on('click', function(e) { 2000 $('[rel="popover"], [data-rel="popover"]').each(function() { 2001 //the 'is' for buttons that trigger popups 2002 //the 'has' for icons within a button that triggers a popup 2003 if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) { 2004 $(this).popover('hide'); 2005 } 2006 }); 2007 }); 2008 /* ~ END: ONE POP OVER THEORY */ 2009 2010 /* 2011 * DELETE MODEL DATA ON HIDDEN 2012 * Clears the model data once it is hidden, this way you do not create duplicated data on multiple modals 2013 */ 2014 $('body').on('hidden.bs.modal', '.modal', function () { 2015 $(this).removeData('bs.modal'); 2016 }); 2017 /* ~ END: DELETE MODEL DATA ON HIDDEN */ 2018 2019 /* 2020 * HELPFUL FUNCTIONS 2021 * We have included some functions below that can be resued on various occasions 2022 * 2023 * Get param value 2024 * example: alert( getParam( 'param' ) ); 2025 */ 2026 function getParam(name) { 2027 name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]"); 2028 var regexS = "[\\?&]" + name + "=([^&#]*)"; 2029 var regex = new RegExp(regexS); 2030 var results = regex.exec(window.location.href); 2031 if (results == null) 2032 return ""; 2033 else 2034 return results[1]; 2035 } 2036 /* ~ END: HELPFUL FUNCTIONS */