if( !('ace' in window) ) window['ace'] = {} ace.config = { cookie_expiry : 604800, //1 week duration for saved settings cookie_path: '', storage_method: 2 //2 means use cookies, 1 means localstorage, 0 means localstorage if available otherwise cookies } if( !('vars' in window['ace']) ) window['ace'].vars = {} ace.vars['very_old_ie'] = !('queryselector' in document.documentelement); ace.settings = { is : function(item, status) { //such as ace.settings.is('navbar', 'fixed') return (ace.data.get('settings', item+'-'+status) == 1) }, exists : function(item, status) { return (ace.data.get('settings', item+'-'+status) !== null) }, set : function(item, status) { ace.data.set('settings', item+'-'+status, 1) }, unset : function(item, status) { ace.data.set('settings', item+'-'+status, -1) }, remove : function(item, status) { ace.data.remove('settings', item+'-'+status) }, navbar_fixed : function(navbar, fix , save, chain) { if(ace.vars['very_old_ie']) return false; var navbar = navbar || '#navbar'; if(typeof navbar === 'string') navbar = document.queryselector(navbar); if(!navbar) return false; fix = fix || false; save = save && true; if(!fix && chain !== false) { //unfix sidebar as well var sidebar = null; if( ace.settings.is('sidebar', 'fixed') || ((sidebar = document.getelementbyid('sidebar')) && ace.hasclass(sidebar , 'sidebar-fixed')) ) { ace.settings.sidebar_fixed(sidebar, false, save); } } if(fix) { if(!ace.hasclass(navbar , 'navbar-fixed-top')) ace.addclass(navbar , 'navbar-fixed-top'); if(save !== false) ace.settings.set('navbar', 'fixed'); } else { ace.removeclass(navbar , 'navbar-fixed-top'); if(save !== false) ace.settings.unset('navbar', 'fixed'); } try { document.getelementbyid('ace-settings-navbar').checked = fix; } catch(e) {} if(window.jquery) jquery(document).trigger('settings.ace', ['navbar_fixed' , fix , navbar]); }, sidebar_fixed : function(sidebar, fix , save, chain) { if(ace.vars['very_old_ie']) return false; var sidebar = sidebar || '#sidebar'; if(typeof sidebar === 'string') sidebar = document.queryselector(sidebar); if(!sidebar) return false; fix = fix || false; save = save && true; if(!fix && chain !== false) { //unfix breadcrumbs as well var breadcrumbs = null; if( ace.settings.is('breadcrumbs', 'fixed') || ((breadcrumbs = document.getelementbyid('breadcrumbs')) && ace.hasclass(breadcrumbs , 'breadcrumbs-fixed')) ) { ace.settings.breadcrumbs_fixed(breadcrumbs, false, save); } } if( fix && chain !== false && !ace.settings.is('navbar', 'fixed') ) { ace.settings.navbar_fixed(null, true, save); } if(fix) { if( !ace.hasclass(sidebar , 'sidebar-fixed') ) { ace.addclass(sidebar , 'sidebar-fixed'); var toggler = document.getelementbyid('menu-toggler'); if(toggler) ace.addclass(toggler , 'fixed'); } if(save !== false) ace.settings.set('sidebar', 'fixed'); } else { ace.removeclass(sidebar , 'sidebar-fixed'); var toggler = document.getelementbyid('menu-toggler'); if(toggler) ace.removeclass(toggler , 'fixed'); if(save !== false) ace.settings.unset('sidebar', 'fixed'); } try { document.getelementbyid('ace-settings-sidebar').checked = fix; } catch(e) {} if(window.jquery) jquery(document).trigger('settings.ace', ['sidebar_fixed' , fix , sidebar]); }, //fixed position breadcrumbs_fixed : function(breadcrumbs, fix , save, chain) { if(ace.vars['very_old_ie']) return false; var breadcrumbs = breadcrumbs || '#breadcrumbs'; if(typeof breadcrumbs === 'string') breadcrumbs = document.queryselector(breadcrumbs); if(!breadcrumbs) return false; fix = fix || false; save = save && true; if(fix && chain !== false && !ace.settings.is('sidebar', 'fixed')) { ace.settings.sidebar_fixed(null, true, save); } if(fix) { if(!ace.hasclass(breadcrumbs , 'breadcrumbs-fixed')) ace.addclass(breadcrumbs , 'breadcrumbs-fixed'); if(save !== false) ace.settings.set('breadcrumbs', 'fixed'); } else { ace.removeclass(breadcrumbs , 'breadcrumbs-fixed'); if(save !== false) ace.settings.unset('breadcrumbs', 'fixed'); } try { document.getelementbyid('ace-settings-breadcrumbs').checked = fix; } catch(e) {} if(window.jquery) jquery(document).trigger('settings.ace', ['breadcrumbs_fixed' , fix , breadcrumbs]); }, //fixed size main_container_fixed : function(main_container, inside , save) { if(ace.vars['very_old_ie']) return false; inside = inside || false; save = save && true; var main_container = main_container || '#main-container'; if(typeof main_container === 'string') main_container = document.queryselector(main_container); if(!main_container) return false; var navbar_container = document.getelementbyid('navbar-container'); if(inside) { if( !ace.hasclass(main_container , 'container') ) ace.addclass(main_container , 'container'); if( navbar_container && !ace.hasclass(navbar_container , 'container') ) ace.addclass(navbar_container , 'container'); if( save !== false ) ace.settings.set('main-container', 'fixed'); } else { ace.removeclass(main_container , 'container'); if(navbar_container) ace.removeclass(navbar_container , 'container'); if(save !== false) ace.settings.unset('main-container', 'fixed'); } try { document.getelementbyid('ace-settings-add-container').checked = inside; } catch(e) {} if(navigator.useragent.match(/webkit/i)) { //webkit has a problem redrawing and moving around the sidebar background in realtime //so we do this, to force redraw //there will be no problems with webkit if the ".container" class is statically put inside html code. var sidebar = document.getelementbyid('sidebar') ace.toggleclass(sidebar , 'menu-min') settimeout(function() { ace.toggleclass(sidebar , 'menu-min') } , 0) } if(window.jquery) jquery(document).trigger('settings.ace', ['main_container_fixed', inside, main_container]); }, sidebar_collapsed : function(sidebar, collapse , save) { if(ace.vars['very_old_ie']) return false; var sidebar = sidebar || '#sidebar'; if(typeof sidebar === 'string') sidebar = document.queryselector(sidebar); if(!sidebar) return false; collapse = collapse || false; if(collapse) { ace.addclass(sidebar , 'menu-min'); if(save !== false) ace.settings.set('sidebar', 'collapsed'); } else { ace.removeclass(sidebar , 'menu-min'); if(save !== false) ace.settings.unset('sidebar', 'collapsed'); } if(window.jquery) jquery(document).trigger('settings.ace', ['sidebar_collapsed' , collapse, sidebar]); if(!window.jquery) { var toggle_btn = document.queryselector('.sidebar-collapse[data-target="#'+(sidebar.getattribute('id')||'')+'"]'); if(!toggle_btn) toggle_btn = sidebar.queryselector('.sidebar-collapse'); if(!toggle_btn) return; var icon = toggle_btn.queryselector('[data-icon1][data-icon2]'), icon1, icon2; if(!icon) return; icon1 = icon.getattribute('data-icon1');//the icon for expanded state icon2 = icon.getattribute('data-icon2');//the icon for collapsed state if(collapse) { ace.removeclass(icon, icon1); ace.addclass(icon, icon2); } else { ace.removeclass(icon, icon2); ace.addclass(icon, icon1); } } } /** , select_skin : function(skin) { } */ } //check the status of something ace.settings.check = function(item, val) { if(! ace.settings.exists(item, val) ) return;//no such setting specified var status = ace.settings.is(item, val);//is breadcrumbs-fixed? or is sidebar-collapsed? etc var musthaveclass = { 'navbar-fixed' : 'navbar-fixed-top', 'sidebar-fixed' : 'sidebar-fixed', 'breadcrumbs-fixed' : 'breadcrumbs-fixed', 'sidebar-collapsed' : 'menu-min', 'main-container-fixed' : 'container' } //if an element doesn't have a specified class, but saved settings say it should, then add it //for example, sidebar isn't .fixed, but user fixed it on a previous page //or if an element has a specified class, but saved settings say it shouldn't, then remove it //for example, sidebar by default is minimized (.menu-min hard coded), but user expanded it and now shouldn't have 'menu-min' class var target = document.getelementbyid(item);//#navbar, #sidebar, #breadcrumbs if(status != ace.hasclass(target , musthaveclass[item+'-'+val])) { ace.settings[item.replace('-','_')+'_'+val](null, status);//call the relevant function to make the changes } } //save/retrieve data using localstorage or cookie //method == 1, use localstorage //method == 2, use cookies //method not specified, use localstorage if available, otherwise cookies ace.data_storage = function(method, undefined) { var prefix = 'ace_'; var storage = null; var type = 0; if((method == 1 || method === undefined) && 'localstorage' in window && window['localstorage'] !== null) { storage = ace.storage; type = 1; } else if(storage == null && (method == 2 || method === undefined) && 'cookie' in document && document['cookie'] !== null) { storage = ace.cookie; type = 2; } //var data = {} this.set = function(namespace, key, value, path, undefined) { if(!storage) return; if(value === undefined) {//no namespace here? value = key; key = namespace; if(value == null) storage.remove(prefix+key) else { if(type == 1) storage.set(prefix+key, value) else if(type == 2) storage.set(prefix+key, value, ace.config.cookie_expiry, path || ace.config.cookie_path) } } else { if(type == 1) {//localstorage if(value == null) storage.remove(prefix+namespace+'_'+key) else storage.set(prefix+namespace+'_'+key, value); } else if(type == 2) {//cookie var val = storage.get(prefix+namespace); var tmp = val ? json.parse(val) : {}; if(value == null) { delete tmp[key];//remove if(ace.sizeof(tmp) == 0) {//no other elements in this cookie, so delete it storage.remove(prefix+namespace); return; } } else { tmp[key] = value; } storage.set(prefix+namespace , json.stringify(tmp), ace.config.cookie_expiry, path || ace.config.cookie_path) } } } this.get = function(namespace, key, undefined) { if(!storage) return null; if(key === undefined) {//no namespace here? key = namespace; return storage.get(prefix+key); } else { if(type == 1) {//localstorage return storage.get(prefix+namespace+'_'+key); } else if(type == 2) {//cookie var val = storage.get(prefix+namespace); var tmp = val ? json.parse(val) : {}; return key in tmp ? tmp[key] : null; } } } this.remove = function(namespace, key, undefined) { if(!storage) return; if(key === undefined) { key = namespace this.set(key, null); } else { this.set(namespace, key, null); } } } //cookie storage ace.cookie = { // the following functions are from cookie.js class in tinymce, moxiecode, used under lgpl. /** * get a cookie. */ get : function(name) { var cookie = document.cookie, e, p = name + "=", b; if ( !cookie ) return; b = cookie.indexof("; " + p); if ( b == -1 ) { b = cookie.indexof(p); if ( b != 0 ) return null; } else { b += 2; } e = cookie.indexof(";", b); if ( e == -1 ) e = cookie.length; return decodeuricomponent( cookie.substring(b + p.length, e) ); }, /** * set a cookie. * * the 'expires' arg can be either a js date() object set to the expiration date (back-compat) * or the number of seconds until expiration */ set : function(name, value, expires, path, domain, secure) { var d = new date(); if ( typeof(expires) == 'object' && expires.togmtstring ) { expires = expires.togmtstring(); } else if ( parseint(expires, 10) ) { d.settime( d.gettime() + ( parseint(expires, 10) * 1000 ) ); // time must be in miliseconds expires = d.togmtstring(); } else { expires = ''; } document.cookie = name + "=" + encodeuricomponent(value) + ((expires) ? "; expires=" + expires : "") + ((path) ? "; path=" + path : "") + ((domain) ? "; domain=" + domain : "") + ((secure) ? "; secure" : ""); }, /** * remove a cookie. * * this is done by setting it to an empty value and setting the expiration time in the past. */ remove : function(name, path) { this.set(name, '', -1000, path); } }; //local storage ace.storage = { get: function(key) { return window['localstorage'].getitem(key); }, set: function(key, value) { window['localstorage'].setitem(key , value); }, remove: function(key) { window['localstorage'].removeitem(key); } }; //count the number of properties in an object //useful for getting the number of elements in an associative array ace.sizeof = function(obj) { var size = 0; for(var key in obj) if(obj.hasownproperty(key)) size++; return size; } //because jquery may not be loaded at this stage, we use our own toggleclass ace.hasclass = function(elem, classname) { return (" " + elem.classname + " ").indexof(" " + classname + " ") > -1; } ace.addclass = function(elem, classname) { if (!ace.hasclass(elem, classname)) { var currentclass = elem.classname; elem.classname = currentclass + (currentclass.length? " " : "") + classname; } } ace.removeclass = function(elem, classname) {ace.replaceclass(elem, classname);} ace.replaceclass = function(elem, classname, newclass) { var classtoremove = new regexp(("(^|\\s)" + classname + "(\\s|$)"), "i"); elem.classname = elem.classname.replace(classtoremove, function (match, p1, p2) { return newclass? (p1 + newclass + p2) : " "; }).replace(/^\s+|\s+$/g, ""); } ace.toggleclass = function(elem, classname) { if(ace.hasclass(elem, classname)) ace.removeclass(elem, classname); else ace.addclass(elem, classname); } ace.ishttmlelement = function(elem) { return window.htmlelement ? elem instanceof htmlelement : ('nodetype' in elem ? elem.nodetype == 1 : false); } //data_storage instance used inside ace.settings etc ace.data = new ace.data_storage(ace.config.storage_method);