ace.js 100 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302
  1. /*!
  2. * Ace v1.4.0
  3. */
  4. if (typeof jQuery === 'undefined') { throw new Error('Ace\'s JavaScript requires jQuery') }
  5. /**
  6. Required. Ace's Basic File to Initiliaze Different Parts and Some Variables.
  7. */
  8. //some basic variables
  9. (function(undefined) {
  10. if( !('ace' in window) ) window['ace'] = {}
  11. if( !('helper' in window['ace']) ) window['ace'].helper = {}
  12. if( !('vars' in window['ace']) ) window['ace'].vars = {}
  13. window['ace'].vars['icon'] = ' ace-icon ';
  14. window['ace'].vars['.icon'] = '.ace-icon';
  15. ace.vars['touch'] = ('ontouchstart' in window);//(('ontouchstart' in document.documentElement) || (window.DocumentTouch && document instanceof DocumentTouch));
  16. //sometimes the only good way to work around browser's pecularities is to detect them using user-agents
  17. //though it's not accurate
  18. var agent = navigator.userAgent
  19. ace.vars['webkit'] = !!agent.match(/AppleWebKit/i)
  20. ace.vars['safari'] = !!agent.match(/Safari/i) && !agent.match(/Chrome/i);
  21. ace.vars['android'] = ace.vars['safari'] && !!agent.match(/Android/i)
  22. ace.vars['ios_safari'] = !!agent.match(/OS ([4-9])(_\d)+ like Mac OS X/i) && !agent.match(/CriOS/i)
  23. ace.vars['ie'] = window.navigator.msPointerEnabled || (document.all && document.querySelector);//8-11
  24. ace.vars['old_ie'] = document.all && !document.addEventListener;//8 and below
  25. ace.vars['very_old_ie'] = document.all && !document.querySelector;//7 and below
  26. ace.vars['firefox'] = 'MozAppearance' in document.documentElement.style;
  27. ace.vars['non_auto_fixed'] = ace.vars['android'] || ace.vars['ios_safari'];
  28. })();
  29. (function($ , undefined) {
  30. //sometimes we try to use 'tap' event instead of 'click' if jquery mobile plugin is available
  31. ace['click_event'] = ace.vars['touch'] && $.fn.tap ? 'tap' : 'click';
  32. })(jQuery);
  33. //document ready function
  34. jQuery(function($) {
  35. basics();
  36. enableSidebar();
  37. enableDemoAjax();
  38. handleScrollbars();
  39. dropdownAutoPos();
  40. navbarHelpers();
  41. sidebarTooltips();
  42. scrollTopBtn();
  43. someBrowserFix();
  44. bsCollapseToggle();
  45. smallDeviceDropdowns();
  46. ////////////////////////////
  47. function basics() {
  48. // for android and ios we don't use "top:auto" when breadcrumbs is fixed
  49. if(ace.vars['non_auto_fixed']) {
  50. $('body').addClass('mob-safari');
  51. }
  52. ace.vars['transition'] = !!$.support.transition.end
  53. }
  54. function enableSidebar() {
  55. //initiate sidebar function
  56. var $sidebar = $('.sidebar');
  57. if($.fn.ace_sidebar) $sidebar.ace_sidebar();
  58. if($.fn.ace_sidebar_scroll) $sidebar.ace_sidebar_scroll({
  59. //for other options please see documentation
  60. 'include_toggle': false || ace.vars['safari'] || ace.vars['ios_safari'] //true = include toggle button in the scrollbars
  61. });
  62. if($.fn.ace_sidebar_hover) $sidebar.ace_sidebar_hover({
  63. 'sub_hover_delay': 750,
  64. 'sub_scroll_style': 'no-track scroll-thin scroll-margin scroll-visible'
  65. });
  66. }
  67. //Load content via ajax
  68. function enableDemoAjax() {
  69. if(!$.fn.ace_ajax) return;
  70. if(window.Pace) {
  71. window.paceOptions = {
  72. ajax: true,
  73. document: true,
  74. eventLag: false // disabled
  75. //elements: {selectors: ['.page-content-area']}
  76. }
  77. }
  78. var demo_ajax_options = {
  79. 'close_active': true,
  80. 'default_url': 'page/index',//default hash
  81. 'content_url': function(hash) {
  82. //***NOTE***
  83. //this is for Ace demo only, you should change it to return a valid URL
  84. //please refer to documentation for more info
  85. if( !hash.match(/^page\//) ) return false;
  86. var path = document.location.pathname;
  87. //for example in Ace HTML demo version we convert /ajax/index.html#page/gallery to > /ajax/content/gallery.html and load it
  88. if(path.match(/(\/ajax\/)(index\.html)?/))
  89. return path.replace(/(\/ajax\/)(index\.html)?/, '/ajax/content/'+hash.replace(/^page\//, '')+'.html') ;
  90. //for example in Ace PHP demo version we convert "ajax.php#page/dashboard" to "ajax.php?page=dashboard" and load it
  91. return path + "?" + hash.replace(/\//, "=");
  92. }
  93. }
  94. //for IE9 and below we exclude PACE loader (using conditional IE comments)
  95. //for other browsers we use the following extra ajax loader options
  96. if(window.Pace) {
  97. demo_ajax_options['loading_overlay'] = 'body';//the opaque overlay is applied to 'body'
  98. }
  99. //initiate ajax loading on this element( which is .page-content-area[data-ajax-content=true] in Ace's demo)
  100. $('[data-ajax-content=true]').ace_ajax(demo_ajax_options)
  101. //if general error happens and ajax is working, let's stop loading icon & PACE
  102. $(window).on('error.ace_ajax', function() {
  103. $('[data-ajax-content=true]').each(function() {
  104. var $this = $(this);
  105. if( $this.ace_ajax('working') ) {
  106. if(window.Pace && Pace.running) Pace.stop();
  107. $this.ace_ajax('stopLoading', true);
  108. }
  109. })
  110. })
  111. }
  112. /////////////////////////////
  113. function handleScrollbars() {
  114. //add scrollbars for navbar dropdowns
  115. var has_scroll = !!$.fn.ace_scroll;
  116. if(has_scroll) $('.dropdown-content').ace_scroll({reset: false, mouseWheelLock: true})
  117. //reset scrolls bars on window resize
  118. if(has_scroll && !ace.vars['old_ie']) {//IE has an issue with widget fullscreen on ajax?!!!
  119. $(window).on('resize.reset_scroll', function() {
  120. $('.ace-scroll:not(.scroll-disabled)').not(':hidden').ace_scroll('reset');
  121. });
  122. if(has_scroll) $(document).on('settings.ace.reset_scroll', function(e, name) {
  123. if(name == 'sidebar_collapsed') $('.ace-scroll:not(.scroll-disabled)').not(':hidden').ace_scroll('reset');
  124. });
  125. }
  126. }
  127. function dropdownAutoPos() {
  128. //change a dropdown to "dropup" depending on its position
  129. $(document).on('click.dropdown.pos', '.dropdown-toggle[data-position="auto"]', function() {
  130. var offset = $(this).offset();
  131. var parent = $(this.parentNode);
  132. if ( parseInt(offset.top + $(this).height()) + 50
  133. >
  134. (ace.helper.scrollTop() + ace.helper.winHeight() - parent.find('.dropdown-menu').eq(0).height())
  135. ) parent.addClass('dropup');
  136. else parent.removeClass('dropup');
  137. });
  138. }
  139. function navbarHelpers() {
  140. //prevent dropdowns from hiding when a from is clicked
  141. /**$(document).on('click', '.dropdown-navbar form', function(e){
  142. e.stopPropagation();
  143. });*/
  144. //disable navbar icon animation upon click
  145. $('.ace-nav [class*="icon-animated-"]').closest('a').one('click', function(){
  146. var icon = $(this).find('[class*="icon-animated-"]').eq(0);
  147. var $match = icon.attr('class').match(/icon\-animated\-([\d\w]+)/);
  148. icon.removeClass($match[0]);
  149. });
  150. //prevent dropdowns from hiding when a tab is selected
  151. $(document).on('click', '.dropdown-navbar .nav-tabs', function(e){
  152. e.stopPropagation();
  153. var $this , href
  154. var that = e.target
  155. if( ($this = $(e.target).closest('[data-toggle=tab]')) && $this.length > 0) {
  156. $this.tab('show');
  157. e.preventDefault();
  158. $(window).triggerHandler('resize.navbar.dropdown')
  159. }
  160. });
  161. }
  162. function sidebarTooltips() {
  163. //tooltip in sidebar items
  164. $('.sidebar .nav-list .badge[title],.sidebar .nav-list .badge[title]').each(function() {
  165. var tooltip_class = $(this).attr('class').match(/tooltip\-(?:\w+)/);
  166. tooltip_class = tooltip_class ? tooltip_class[0] : 'tooltip-error';
  167. $(this).tooltip({
  168. 'placement': function (context, source) {
  169. var offset = $(source).offset();
  170. if( parseInt(offset.left) < parseInt(document.body.scrollWidth / 2) ) return 'right';
  171. return 'left';
  172. },
  173. container: 'body',
  174. template: '<div class="tooltip '+tooltip_class+'"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
  175. });
  176. });
  177. //or something like this if items are dynamically inserted
  178. /**
  179. $('.sidebar').tooltip({
  180. 'placement': function (context, source) {
  181. var offset = $(source).offset();
  182. if( parseInt(offset.left) < parseInt(document.body.scrollWidth / 2) ) return 'right';
  183. return 'left';
  184. },
  185. selector: '.nav-list .badge[title],.nav-list .label[title]',
  186. container: 'body',
  187. template: '<div class="tooltip tooltip-error"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
  188. });
  189. */
  190. }
  191. function scrollTopBtn() {
  192. //the scroll to top button
  193. var scroll_btn = $('.btn-scroll-up');
  194. if(scroll_btn.length > 0) {
  195. var is_visible = false;
  196. $(window).on('scroll.scroll_btn', function() {
  197. var scroll = ace.helper.scrollTop();
  198. var h = ace.helper.winHeight();
  199. var body_sH = document.body.scrollHeight;
  200. if(scroll > parseInt(h / 4) || (scroll > 0 && body_sH >= h && h + scroll >= body_sH - 1)) {//|| for smaller pages, when reached end of page
  201. if(!is_visible) {
  202. scroll_btn.addClass('display');
  203. is_visible = true;
  204. }
  205. } else {
  206. if(is_visible) {
  207. scroll_btn.removeClass('display');
  208. is_visible = false;
  209. }
  210. }
  211. }).triggerHandler('scroll.scroll_btn');
  212. scroll_btn.on(ace.click_event, function(){
  213. var duration = Math.min(500, Math.max(100, parseInt(ace.helper.scrollTop() / 3)));
  214. $('html,body').animate({scrollTop: 0}, duration);
  215. return false;
  216. });
  217. }
  218. }
  219. function someBrowserFix() {
  220. //chrome and webkit have a problem here when resizing from 479px to more
  221. //we should force them redraw the navbar!
  222. if( ace.vars['webkit'] ) {
  223. var ace_nav = $('.ace-nav').get(0);
  224. if( ace_nav ) $(window).on('resize.webkit_fix' , function(){
  225. ace.helper.redraw(ace_nav);
  226. });
  227. }
  228. //fix an issue with ios safari, when an element is fixed and an input receives focus
  229. if(ace.vars['ios_safari']) {
  230. $(document).on('ace.settings.ios_fix', function(e, event_name, event_val) {
  231. if(event_name != 'navbar_fixed') return;
  232. $(document).off('focus.ios_fix blur.ios_fix', 'input,textarea,.wysiwyg-editor');
  233. if(event_val == true) {
  234. $(document).on('focus.ios_fix', 'input,textarea,.wysiwyg-editor', function() {
  235. $(window).on('scroll.ios_fix', function() {
  236. var navbar = $('#navbar').get(0);
  237. if(navbar) ace.helper.redraw(navbar);
  238. });
  239. }).on('blur.ios_fix', 'input,textarea,.wysiwyg-editor', function() {
  240. $(window).off('scroll.ios_fix');
  241. })
  242. }
  243. }).triggerHandler('ace.settings.ios_fix', ['navbar_fixed', $('#navbar').css('position') == 'fixed']);
  244. }
  245. }
  246. function bsCollapseToggle() {
  247. //bootstrap collapse component icon toggle
  248. $(document).on('hide.bs.collapse show.bs.collapse', function (ev) {
  249. var panel_id = ev.target.getAttribute('id')
  250. var panel = $('a[href*="#'+ panel_id+'"]');
  251. if(panel.length == 0) panel = $('a[data-target*="#'+ panel_id+'"]');
  252. if(panel.length == 0) return;
  253. panel.find(ace.vars['.icon']).each(function(){
  254. var $icon = $(this)
  255. var $match
  256. var $icon_down = null
  257. var $icon_up = null
  258. if( ($icon_down = $icon.attr('data-icon-show')) ) {
  259. $icon_up = $icon.attr('data-icon-hide')
  260. }
  261. else if( $match = $icon.attr('class').match(/fa\-(.*)\-(up|down)/) ) {
  262. $icon_down = 'fa-'+$match[1]+'-down'
  263. $icon_up = 'fa-'+$match[1]+'-up'
  264. }
  265. if($icon_down) {
  266. if(ev.type == 'show') $icon.removeClass($icon_down).addClass($icon_up)
  267. else $icon.removeClass($icon_up).addClass($icon_down)
  268. return false;//ignore other icons that match, one is enough
  269. }
  270. });
  271. })
  272. }
  273. //in small devices display navbar dropdowns like modal boxes
  274. function smallDeviceDropdowns() {
  275. if(ace.vars['old_ie']) return;
  276. $('.ace-nav > li')
  277. .on('shown.bs.dropdown.navbar', function(e) {
  278. adjustNavbarDropdown.call(this);
  279. })
  280. .on('hidden.bs.dropdown.navbar', function(e) {
  281. $(window).off('resize.navbar.dropdown');
  282. resetNavbarDropdown.call(this);
  283. })
  284. function adjustNavbarDropdown() {
  285. var $sub = $(this).find('> .dropdown-menu');
  286. if( $sub.css('position') == 'fixed' ) {
  287. var win_width = parseInt($(window).width());
  288. var offset_w = win_width > 320 ? 60 : (win_width > 240 ? 40 : 30);
  289. var avail_width = parseInt(win_width) - offset_w;
  290. var avail_height = parseInt($(window).height()) - 30;
  291. var width = parseInt(Math.min(avail_width , 320));
  292. //we set 'width' here for text wrappings and spacings to take effect before calculating scrollHeight
  293. $sub.css('width', width);
  294. var tabbed = false;
  295. var extra_parts = 0;
  296. var dropdown_content = $sub.find('.tab-pane.active .dropdown-content.ace-scroll');
  297. if(dropdown_content.length == 0) dropdown_content = $sub.find('.dropdown-content.ace-scroll');
  298. else tabbed = true;
  299. var parent_menu = dropdown_content.closest('.dropdown-menu');
  300. var scrollHeight = $sub[0].scrollHeight;
  301. if(dropdown_content.length == 1) {
  302. //sometimes there's no scroll-content, for example in detached scrollbars
  303. var content = dropdown_content.find('.scroll-content')[0];
  304. if(content) {
  305. scrollHeight = content.scrollHeight;
  306. }
  307. extra_parts += parent_menu.find('.dropdown-header').outerHeight();
  308. extra_parts += parent_menu.find('.dropdown-footer').outerHeight();
  309. var tab_content = parent_menu.closest('.tab-content');
  310. if( tab_content.length != 0 ) {
  311. extra_parts += tab_content.siblings('.nav-tabs').eq(0).height();
  312. }
  313. }
  314. var height = parseInt(Math.min(avail_height , 480, scrollHeight + extra_parts));
  315. var left = parseInt(Math.abs((avail_width + offset_w - width)/2));
  316. var top = parseInt(Math.abs((avail_height + 30 - height)/2));
  317. var zindex = parseInt($sub.css('z-index')) || 0;
  318. $sub.css({'height': height, 'left': left, 'right': 'auto', 'top': top - (!tabbed ? 1 : 3)});
  319. if(dropdown_content.length == 1) {
  320. if(!ace.vars['touch']) {
  321. dropdown_content.ace_scroll('update', {size: height - extra_parts}).ace_scroll('enable').ace_scroll('reset');
  322. }
  323. else {
  324. dropdown_content
  325. .ace_scroll('disable').css('max-height', height - extra_parts).addClass('overflow-scroll');
  326. }
  327. }
  328. $sub.css('height', height + (!tabbed ? 2 : 7));//for bottom border adjustment and tab content paddings
  329. if($sub.hasClass('user-menu')) {
  330. $sub.css('height', '');//because of user-info hiding/showing at different widths, which changes above 'scrollHeight', so we remove it!
  331. //user menu is re-positioned in small widths
  332. //but we need to re-position again in small heights as well (modal mode)
  333. var user_info = $(this).find('.user-info');
  334. if(user_info.length == 1 && user_info.css('position') == 'fixed') {
  335. user_info.css({'left': left, 'right': 'auto', 'top': top, 'width': width - 2, 'max-width': width - 2, 'z-index': zindex + 1});
  336. }
  337. else user_info.css({'left': '', 'right': '', 'top': '', 'width': '', 'max-width': '', 'z-index': ''});
  338. }
  339. //dropdown's z-index is limited by parent .navbar's z-index (which doesn't make sense because dropdowns are fixed!)
  340. //so for example when in 'content-slider' page, fixed modal toggle buttons go above are dropdowns
  341. //so we increase navbar's z-index to fix this!
  342. $(this).closest('.navbar.navbar-fixed-top').css('z-index', zindex);
  343. }
  344. else {
  345. if($sub.length != 0) resetNavbarDropdown.call(this, $sub);
  346. }
  347. var self = this;
  348. $(window)
  349. .off('resize.navbar.dropdown')
  350. .one('resize.navbar.dropdown', function() {
  351. $(self).triggerHandler('shown.bs.dropdown.navbar');
  352. })
  353. }
  354. //reset scrollbars and user menu
  355. function resetNavbarDropdown($sub) {
  356. $sub = $sub || $(this).find('> .dropdown-menu');
  357. if($sub.length > 0) {
  358. $sub
  359. .css({'width': '', 'height': '', 'left': '', 'right': '', 'top': ''})
  360. .find('.dropdown-content').each(function() {
  361. if(ace.vars['touch']) {
  362. $(this).css('max-height', '').removeClass('overflow-scroll');
  363. }
  364. var size = parseInt($(this).attr('data-size') || 0) || $.fn.ace_scroll.defaults.size;
  365. $(this).ace_scroll('update', {size: size}).ace_scroll('enable').ace_scroll('reset');
  366. })
  367. if( $sub.hasClass('user-menu') ) {
  368. var user_info =
  369. $(this).find('.user-info')
  370. .css({'left': '', 'right': '', 'top': '', 'width': '', 'max-width': '', 'z-index': ''});
  371. }
  372. }
  373. $(this).closest('.navbar').css('z-index', '');
  374. }
  375. }
  376. });//jQuery document ready
  377. //some ace helper functions
  378. (function($$ , undefined) {//$$ is ace.helper
  379. $$.unCamelCase = function(str) {
  380. return str.replace(/([a-z])([A-Z])/g, function(match, c1, c2){ return c1+'-'+c2.toLowerCase() })
  381. }
  382. $$.strToVal = function(str) {
  383. var res = str.match(/^(?:(true)|(false)|(null)|(\-?[\d]+(?:\.[\d]+)?)|(\[.*\]|\{.*\}))$/i);
  384. var val = str;
  385. if(res) {
  386. if(res[1]) val = true;
  387. else if(res[2]) val = false;
  388. else if(res[3]) val = null;
  389. else if(res[4]) val = parseFloat(str);
  390. else if(res[5]) {
  391. try { val = JSON.parse(str) }
  392. catch (err) {}
  393. }
  394. }
  395. return val;
  396. }
  397. $$.getAttrSettings = function(el, attr_list, prefix) {
  398. var list_type = attr_list instanceof Array ? 1 : 2;
  399. //attr_list can be Array or Object(key/value)
  400. var prefix = prefix ? prefix.replace(/([^\-])$/ , '$1-') : '';
  401. prefix = 'data-' + prefix;
  402. var settings = {}
  403. for(var li in attr_list) if(attr_list.hasOwnProperty(li)) {
  404. var name = list_type == 1 ? attr_list[li] : li;
  405. var attr_val, attr_name = $$.unCamelCase(name.replace(/[^A-Za-z0-9]{1,}/g , '-')).toLowerCase()
  406. if( ! ((attr_val = el.getAttribute(prefix + attr_name)) ) ) continue;
  407. settings[name] = $$.strToVal(attr_val);
  408. }
  409. return settings;
  410. }
  411. $$.scrollTop = function() {
  412. return document.scrollTop || document.documentElement.scrollTop || document.body.scrollTop
  413. }
  414. $$.winHeight = function() {
  415. return window.innerHeight || document.documentElement.clientHeight;
  416. }
  417. $$.redraw = function(elem, force) {
  418. var saved_val = elem.style['display'];
  419. elem.style.display = 'none';
  420. elem.offsetHeight;
  421. if(force !== true) {
  422. elem.style.display = saved_val;
  423. }
  424. else {
  425. //force redraw for example in old IE
  426. setTimeout(function() {
  427. elem.style.display = saved_val;
  428. }, 10);
  429. }
  430. }
  431. })(ace.helper);;/**
  432. <b>Load content via Ajax </b>. For more information please refer to documentation #basics/ajax
  433. */
  434. (function($ , undefined) {
  435. var ajax_loaded_scripts = {}
  436. function AceAjax(contentArea, settings) {
  437. var $contentArea = $(contentArea);
  438. var self = this;
  439. $contentArea.attr('data-ajax-content', 'true');
  440. //get a list of 'data-*' attributes that override 'defaults' and 'settings'
  441. var attrib_values = ace.helper.getAttrSettings(contentArea, $.fn.ace_ajax.defaults);
  442. this.settings = $.extend({}, $.fn.ace_ajax.defaults, settings, attrib_values);
  443. var working = false;
  444. var $overlay = $();//empty set
  445. this.force_reload = false;//set jQuery ajax's cache option to 'false' to reload content
  446. this.loadUrl = function(hash, cache) {
  447. var url = false;
  448. hash = hash.replace(/^(\#\!)?\#/, '');
  449. this.force_reload = (cache === false)
  450. if(typeof this.settings.content_url === 'function') url = this.settings.content_url(hash);
  451. if(typeof url === 'string') this.getUrl(url, hash, false);
  452. }
  453. this.loadAddr = function(url, hash, cache) {
  454. this.force_reload = (cache === false);
  455. this.getUrl(url, hash, false);
  456. }
  457. this.getUrl = function(url, hash, manual_trigger) {
  458. if(working) {
  459. return;
  460. }
  461. var event
  462. $contentArea.trigger(event = $.Event('ajaxloadstart'), {url: url, hash: hash})
  463. if (event.isDefaultPrevented()) return;
  464. self.startLoading();
  465. $.ajax({
  466. 'url': url,
  467. 'cache': !this.force_reload
  468. })
  469. .error(function() {
  470. $contentArea.trigger('ajaxloaderror', {url: url, hash: hash});
  471. self.stopLoading(true);
  472. })
  473. .done(function(result) {
  474. $contentArea.trigger('ajaxloaddone', {url: url, hash: hash});
  475. var link_element = null, link_text = '';;
  476. if(typeof self.settings.update_active === 'function') {
  477. link_element = self.settings.update_active.call(null, hash, url);
  478. }
  479. else if(self.settings.update_active === true && hash) {
  480. link_element = $('a[data-url="'+hash+'"]');
  481. if(link_element.length > 0) {
  482. var nav = link_element.closest('.nav');
  483. if(nav.length > 0) {
  484. nav.find('.active').each(function(){
  485. var $class = 'active';
  486. if( $(this).hasClass('hover') || self.settings.close_active ) $class += ' open';
  487. $(this).removeClass($class);
  488. if(self.settings.close_active) {
  489. $(this).find(' > .submenu').css('display', '');
  490. }
  491. })
  492. var active_li = link_element.closest('li').addClass('active').parents('.nav li').addClass('active open');
  493. nav.closest('.sidebar[data-sidebar-scroll=true]').each(function() {
  494. var $this = $(this);
  495. $this.ace_sidebar_scroll('reset');
  496. if(manual_trigger) $this.ace_sidebar_scroll('scroll_to_active');//first time only
  497. })
  498. }
  499. }
  500. }
  501. /////////
  502. if(typeof self.settings.update_breadcrumbs === 'function') {
  503. link_text = self.settings.update_breadcrumbs.call(null, hash, url, link_element);
  504. }
  505. else if(self.settings.update_breadcrumbs === true && link_element != null && link_element.length > 0) {
  506. link_text = updateBreadcrumbs(link_element);
  507. }
  508. /////////
  509. //convert "title" and "link" tags to "div" tags for later processing
  510. result = String(result)
  511. .replace(/<(title|link)([\s\>])/gi,'<div class="hidden ajax-append-$1"$2')
  512. .replace(/<\/(title|link)\>/gi,'</div>')
  513. $overlay.addClass('content-loaded').detach();
  514. $contentArea.empty().html(result);
  515. $(self.settings.loading_overlay || $contentArea).append($overlay);
  516. //remove previous stylesheets inserted via ajax
  517. setTimeout(function() {
  518. $('head').find('link.ace-ajax-stylesheet').remove();
  519. var main_selectors = ['link.ace-main-stylesheet', 'link#main-ace-style', 'link[href*="/ace.min.css"]', 'link[href*="/ace.css"]']
  520. var ace_style = [];
  521. for(var m = 0; m < main_selectors.length; m++) {
  522. ace_style = $('head').find(main_selectors[m]).first();
  523. if(ace_style.length > 0) break;
  524. }
  525. $contentArea.find('.ajax-append-link').each(function(e) {
  526. var $link = $(this);
  527. if ( $link.attr('href') ) {
  528. var new_link = jQuery('<link />', {type : 'text/css', rel: 'stylesheet', 'class': 'ace-ajax-stylesheet'})
  529. if( ace_style.length > 0 ) new_link.insertBefore(ace_style);
  530. else new_link.appendTo('head');
  531. new_link.attr('href', $link.attr('href'));//we set "href" after insertion, for IE to work
  532. }
  533. $link.remove();
  534. })
  535. }, 10);
  536. //////////////////////
  537. if(typeof self.settings.update_title === 'function') {
  538. self.settings.update_title.call(null, hash, url, link_text);
  539. }
  540. else if(self.settings.update_title === true) {
  541. updateTitle(link_text);
  542. }
  543. if( !manual_trigger ) {
  544. $('html,body').animate({scrollTop: 0}, 250);
  545. }
  546. //////////////////////
  547. $contentArea.trigger('ajaxloadcomplete', {url: url, hash: hash});
  548. //////////////////////
  549. self.stopLoading();
  550. })
  551. }
  552. ///////////////////////
  553. var fixPos = false;
  554. var loadTimer = null;
  555. this.startLoading = function() {
  556. if(working) return;
  557. working = true;
  558. if(!this.settings.loading_overlay && $contentArea.css('position') == 'static') {
  559. $contentArea.css('position', 'relative');//for correct icon positioning
  560. fixPos = true;
  561. }
  562. $overlay.remove();
  563. $overlay = $('<div class="ajax-loading-overlay"><i class="ajax-loading-icon '+(this.settings.loading_icon || '')+'"></i> '+this.settings.loading_text+'</div>')
  564. if(this.settings.loading_overlay == 'body') $('body').append($overlay.addClass('ajax-overlay-body'));
  565. else if(this.settings.loading_overlay) $(this.settings.loading_overlay).append($overlay);
  566. else $contentArea.append($overlay);
  567. if(this.settings.max_load_wait !== false)
  568. loadTimer = setTimeout(function() {
  569. loadTimer = null;
  570. if(!working) return;
  571. var event
  572. $contentArea.trigger(event = $.Event('ajaxloadlong'))
  573. if (event.isDefaultPrevented()) return;
  574. self.stopLoading(true);
  575. }, this.settings.max_load_wait * 1000);
  576. }
  577. this.stopLoading = function(stopNow) {
  578. if(stopNow === true) {
  579. working = false;
  580. $overlay.remove();
  581. if(fixPos) {
  582. $contentArea.css('position', '');//restore previous 'position' value
  583. fixPos = false;
  584. }
  585. if(loadTimer != null) {
  586. clearTimeout(loadTimer);
  587. loadTimer = null;
  588. }
  589. }
  590. else {
  591. $overlay.addClass('almost-loaded');
  592. $contentArea.one('ajaxscriptsloaded.inner_call', function() {
  593. self.stopLoading(true);
  594. /**
  595. if(window.Pace && Pace.running == true) {
  596. Pace.off('done');
  597. Pace.once('done', function() { self.stopLoading(true) })
  598. }
  599. else self.stopLoading(true);
  600. */
  601. })
  602. }
  603. }
  604. this.working = function() {
  605. return working;
  606. }
  607. ///////////////////////
  608. function updateBreadcrumbs(link_element) {
  609. var link_text = '';
  610. //update breadcrumbs
  611. var breadcrumbs = $('.breadcrumb');
  612. if(breadcrumbs.length > 0 && breadcrumbs.is(':visible')) {
  613. breadcrumbs.find('> li:not(:first-child)').remove();
  614. var i = 0;
  615. link_element.parents('.nav li').each(function() {
  616. var link = $(this).find('> a');
  617. var link_clone = link.clone();
  618. link_clone.find('i,.fa,.glyphicon,.ace-icon,.menu-icon,.badge,.label').remove();
  619. var text = link_clone.text();
  620. link_clone.remove();
  621. var href = link.attr('href');
  622. if(i == 0) {
  623. var li = $('<li class="active"></li>').appendTo(breadcrumbs);
  624. li.text(text);
  625. link_text = text;
  626. }
  627. else {
  628. var li = $('<li><a /></li>').insertAfter(breadcrumbs.find('> li:first-child'));
  629. li.find('a').attr('href', href).text(text);
  630. }
  631. i++;
  632. })
  633. }
  634. return link_text;
  635. }
  636. function updateTitle(link_text) {
  637. var $title = $contentArea.find('.ajax-append-title');
  638. if($title.length > 0) {
  639. document.title = $title.text();
  640. $title.remove();
  641. }
  642. else if(link_text.length > 0) {
  643. var extra = $.trim(String(document.title).replace(/^(.*)[\-]/, ''));//for example like " - Ace Admin"
  644. if(extra) extra = ' - ' + extra;
  645. link_text = $.trim(link_text) + extra;
  646. }
  647. }
  648. this.loadScripts = function(scripts, callback) {
  649. $.ajaxPrefilter('script', function(opts) {opts.cache = true});
  650. setTimeout(function() {
  651. //let's keep a list of loaded scripts so that we don't load them more than once!
  652. function finishLoading() {
  653. if(typeof callback === 'function') callback();
  654. $('.btn-group[data-toggle="buttons"] > .btn').button();
  655. $contentArea.trigger('ajaxscriptsloaded');
  656. }
  657. //var deferreds = [];
  658. var deferred_count = 0;//deferreds count
  659. var resolved = 0;
  660. for(var i = 0; i < scripts.length; i++) if(scripts[i]) {
  661. (function() {
  662. var script_name = "js-"+scripts[i].replace(/[^\w\d\-]/g, '-').replace(/\-\-/g, '-');
  663. if( ajax_loaded_scripts[script_name] !== true ) deferred_count++;
  664. })()
  665. }
  666. function nextScript(index) {
  667. index += 1;
  668. if(index < scripts.length) loadScript(index);
  669. else {
  670. finishLoading();
  671. }
  672. }
  673. function loadScript(index) {
  674. index = index || 0;
  675. if(!scripts[index]) {//could be null sometimes
  676. return nextScript(index);
  677. }
  678. var script_name = "js-"+scripts[index].replace(/[^\w\d\-]/g, '-').replace(/\-\-/g, '-');
  679. //only load scripts that are not loaded yet!
  680. if( ajax_loaded_scripts[script_name] !== true ) {
  681. $.getScript(scripts[index])
  682. .done(function() {
  683. ajax_loaded_scripts[script_name] = true;
  684. })
  685. //.fail(function() {
  686. //})
  687. .complete(function() {
  688. resolved++;
  689. if(resolved >= deferred_count && working) {
  690. finishLoading();
  691. }
  692. else {
  693. nextScript(index);
  694. }
  695. })
  696. }
  697. else {//script previoisly loaded
  698. nextScript(index);
  699. }
  700. }
  701. if (deferred_count > 0) {
  702. loadScript();
  703. }
  704. else {
  705. finishLoading();
  706. }
  707. }, 10)
  708. }
  709. /////////////////
  710. $(window)
  711. .off('hashchange.ace_ajax')
  712. .on('hashchange.ace_ajax', function(e, manual_trigger) {
  713. var hash = $.trim(window.location.hash);
  714. if(!hash || hash.length == 0) return;
  715. self.loadUrl(hash);
  716. }).trigger('hashchange.ace_ajax', [true]);
  717. var hash = $.trim(window.location.hash);
  718. if(!hash && this.settings.default_url) window.location.hash = this.settings.default_url;
  719. }//AceAjax
  720. $.fn.aceAjax = $.fn.ace_ajax = function (option, value, value2, value3) {
  721. var method_call;
  722. var $set = this.each(function () {
  723. var $this = $(this);
  724. var data = $this.data('ace_ajax');
  725. var options = typeof option === 'object' && option;
  726. if (!data) $this.data('ace_ajax', (data = new AceAjax(this, options)));
  727. if (typeof option === 'string' && typeof data[option] === 'function') {
  728. if(value3 != undefined) method_call = data[option](value, value2, value3);
  729. else if(value2 != undefined) method_call = data[option](value, value2);
  730. else method_call = data[option](value);
  731. }
  732. });
  733. return (method_call === undefined) ? $set : method_call;
  734. }
  735. $.fn.aceAjax.defaults = $.fn.ace_ajax.defaults = {
  736. content_url: false,
  737. default_url: false,
  738. loading_icon: 'fa fa-spin fa-spinner fa-2x orange',
  739. loading_text: '',
  740. loading_overlay: null,
  741. update_breadcrumbs: true,
  742. update_title: true,
  743. update_active: true,
  744. close_active: false,
  745. max_load_wait: false
  746. }
  747. })(window.jQuery);
  748. ;/**
  749. <b>Custom drag event for touch devices</b> used in scrollbars.
  750. For better touch event handling and extra options a more advanced solution such as <u>Hammer.js</u> is recommended.
  751. */
  752. //based on but not dependent on jQuery mobile
  753. /*
  754. * jQuery Mobile v1.3.2
  755. * http://jquerymobile.com
  756. *
  757. * Copyright 2010, 2013 jQuery Foundation, Inc. and other contributors
  758. * Released under the MIT license.
  759. * http://jquery.org/license
  760. *
  761. */
  762. (function($ , undefined) {
  763. if(!ace.vars['touch']) return;
  764. var touchStartEvent = "touchstart MSPointerDown pointerdown",// : "mousedown",
  765. touchStopEvent = "touchend touchcancel MSPointerUp MSPointerCancel pointerup pointercancel",// : "mouseup",
  766. touchMoveEvent = "touchmove MSPointerMove MSPointerHover pointermove";// : "mousemove";
  767. $.event.special.ace_drag = {
  768. setup: function() {
  769. var min_threshold = 0;
  770. var $this = $(this);
  771. $this.on(touchStartEvent, function(event) {
  772. var data = event.originalEvent.touches ?
  773. event.originalEvent.touches[ 0 ] :
  774. event,
  775. start = {
  776. //time: Date.now(),
  777. coords: [ data.pageX, data.pageY ],
  778. origin: $(event.target)
  779. },
  780. stop;
  781. //start.origin.trigger({'type' : 'ace_dragStart', 'start':(start || [-1,-1])});
  782. var direction = false, dx = 0, dy = 0;
  783. function moveHandler(event) {
  784. if (!start) {
  785. return;
  786. }
  787. var data = event.originalEvent.touches ?
  788. event.originalEvent.touches[ 0 ] :
  789. event;
  790. stop = {
  791. coords: [ data.pageX, data.pageY ]
  792. };
  793. // prevent scrolling
  794. //if ( Math.abs(start.coords[1] - stop.coords[1]) > 0 || Math.abs(start.coords[0] - stop.coords[01]) > 0 ) {
  795. //event.preventDefault();
  796. //}
  797. if (start && stop) {
  798. dx = 0;
  799. dy = 0;
  800. direction =
  801. (
  802. Math.abs(dy = start.coords[ 1 ] - stop.coords[ 1 ]) > min_threshold
  803. &&
  804. Math.abs(dx = start.coords[ 0 ] - stop.coords[ 0 ]) <= Math.abs(dy)
  805. )
  806. ?
  807. (dy > 0 ? 'up' : 'down')
  808. :
  809. (
  810. Math.abs(dx = start.coords[ 0 ] - stop.coords[ 0 ]) > min_threshold
  811. &&
  812. Math.abs( dy ) <= Math.abs(dx)
  813. )
  814. ?
  815. (dx > 0 ? 'left' : 'right')
  816. :
  817. false;
  818. if( direction !== false ) {
  819. var retval = {cancel: false}
  820. start.origin.trigger({
  821. 'type': 'ace_drag',
  822. //'start': start.coords,
  823. //'stop': stop.coords,
  824. 'direction': direction,
  825. 'dx': dx,
  826. 'dy': dy,
  827. 'retval': retval
  828. })
  829. // prevent document scrolling unless retval.cancel == true
  830. if( retval.cancel == false ) event.preventDefault();
  831. }
  832. }
  833. start.coords[0] = stop.coords[0];
  834. start.coords[1] = stop.coords[1];
  835. }
  836. $this
  837. .on(touchMoveEvent, moveHandler)
  838. .one(touchStopEvent, function(event) {
  839. $this.off(touchMoveEvent, moveHandler);
  840. //start.origin.trigger({'type' : 'ace_dragEnd', 'stop':(stop || [-1,-1])});
  841. start = stop = undefined;
  842. });
  843. });
  844. }
  845. }
  846. })(window.jQuery);;/**
  847. <b>Sidebar functions</b>. Collapsing/expanding, toggling mobile view menu and other sidebar functions.
  848. */
  849. (function($ , undefined) {
  850. var sidebar_count = 0;
  851. function Sidebar(sidebar, settings) {
  852. var self = this;
  853. this.$sidebar = $(sidebar);
  854. this.$sidebar.attr('data-sidebar', 'true');
  855. if( !this.$sidebar.attr('id') ) this.$sidebar.attr( 'id' , 'id-sidebar-'+(++sidebar_count) )
  856. //get a list of 'data-*' attributes that override 'defaults' and 'settings'
  857. var attrib_values = ace.helper.getAttrSettings(sidebar, $.fn.ace_sidebar.defaults, 'sidebar-');
  858. this.settings = $.extend({}, $.fn.ace_sidebar.defaults, settings, attrib_values);
  859. //some vars
  860. this.minimized = false;//will be initiated later
  861. this.collapsible = false;//...
  862. this.horizontal = false;//...
  863. this.mobile_view = false;//
  864. this.vars = function() {
  865. return {'minimized': this.minimized, 'collapsible': this.collapsible, 'horizontal': this.horizontal, 'mobile_view': this.mobile_view}
  866. }
  867. this.get = function(name) {
  868. if(this.hasOwnProperty(name)) return this[name];
  869. }
  870. this.set = function(name, value) {
  871. if(this.hasOwnProperty(name)) this[name] = value;
  872. }
  873. this.ref = function() {
  874. //return a reference to self
  875. return this;
  876. }
  877. var toggleIcon = function(minimized) {
  878. var icon = $(this).find(ace.vars['.icon']), icon1, icon2;
  879. if(icon.length > 0) {
  880. icon1 = icon.attr('data-icon1');//the icon for expanded state
  881. icon2 = icon.attr('data-icon2');//the icon for collapsed state
  882. if(minimized !== undefined) {
  883. if(minimized) icon.removeClass(icon1).addClass(icon2);
  884. else icon.removeClass(icon2).addClass(icon1);
  885. }
  886. else {
  887. icon.toggleClass(icon1).toggleClass(icon2);
  888. }
  889. }
  890. }
  891. var findToggleBtn = function() {
  892. var toggle_btn = self.$sidebar.find('.sidebar-collapse');
  893. if(toggle_btn.length == 0) toggle_btn = $('.sidebar-collapse[data-target="#'+(self.$sidebar.attr('id')||'')+'"]');
  894. if(toggle_btn.length != 0) toggle_btn = toggle_btn[0];
  895. else toggle_btn = null;
  896. return toggle_btn;
  897. }
  898. //collapse/expand button
  899. this.toggleMenu = function(toggle_btn, save) {
  900. if(this.collapsible) return;
  901. //var minimized = this.$sidebar.hasClass('menu-min');
  902. this.minimized = !this.minimized;
  903. try {
  904. //toggle_btn can also be a param to indicate saving to cookie or not?! if toggle_btn === false, it won't be saved
  905. ace.settings.sidebar_collapsed(sidebar, this.minimized, !(toggle_btn === false || save === false));//@ ace-extra.js
  906. } catch(e) {
  907. if(this.minimized)
  908. this.$sidebar.addClass('menu-min');
  909. else this.$sidebar.removeClass('menu-min');
  910. }
  911. if( !toggle_btn ) {
  912. toggle_btn = findToggleBtn();
  913. }
  914. if(toggle_btn) {
  915. toggleIcon.call(toggle_btn, this.minimized);
  916. }
  917. //force redraw for ie8
  918. if(ace.vars['old_ie']) ace.helper.redraw(sidebar);
  919. }
  920. this.collapse = function(toggle_btn, save) {
  921. if(this.collapsible) return;
  922. this.minimized = false;
  923. this.toggleMenu(toggle_btn, save);
  924. }
  925. this.expand = function(toggle_btn, save) {
  926. if(this.collapsible) return;
  927. this.minimized = true;
  928. this.toggleMenu(toggle_btn, save);
  929. }
  930. //collapse/expand in 2nd mobile style
  931. this.toggleResponsive = function(toggle_btn) {
  932. if(!this.mobile_view || this.mobile_style != 3) return;
  933. if( this.$sidebar.hasClass('menu-min') ) {
  934. //remove menu-min because it interferes with responsive-max
  935. this.$sidebar.removeClass('menu-min');
  936. var btn = findToggleBtn();
  937. if(btn) toggleIcon.call(btn);
  938. }
  939. this.minimized = !this.$sidebar.hasClass('responsive-min');
  940. this.$sidebar.toggleClass('responsive-min responsive-max');
  941. if( !toggle_btn ) {
  942. toggle_btn = this.$sidebar.find('.sidebar-expand');
  943. if(toggle_btn.length == 0) toggle_btn = $('.sidebar-expand[data-target="#'+(this.$sidebar.attr('id')||'')+'"]');
  944. if(toggle_btn.length != 0) toggle_btn = toggle_btn[0];
  945. else toggle_btn = null;
  946. }
  947. if(toggle_btn) {
  948. var icon = $(toggle_btn).find(ace.vars['.icon']), icon1, icon2;
  949. if(icon.length > 0) {
  950. icon1 = icon.attr('data-icon1');//the icon for expanded state
  951. icon2 = icon.attr('data-icon2');//the icon for collapsed state
  952. icon.toggleClass(icon1).toggleClass(icon2);
  953. }
  954. }
  955. $(document).triggerHandler('settings.ace', ['sidebar_collapsed' , this.minimized]);
  956. }
  957. //some helper functions
  958. this.is_collapsible = function() {
  959. var toggle
  960. return (this.$sidebar.hasClass('navbar-collapse'))
  961. && ((toggle = $('.navbar-toggle[data-target="#'+(this.$sidebar.attr('id')||'')+'"]').get(0)) != null)
  962. && toggle.scrollHeight > 0
  963. //sidebar is collapsible and collapse button is visible?
  964. }
  965. this.is_mobile_view = function() {
  966. var toggle
  967. return ((toggle = $('.menu-toggler[data-target="#'+(this.$sidebar.attr('id')||'')+'"]').get(0)) != null)
  968. && toggle.scrollHeight > 0
  969. }
  970. //toggling submenu
  971. this.$sidebar.on(ace.click_event+'.ace.submenu', '.nav-list', function (ev) {
  972. var nav_list = this;
  973. //check to see if we have clicked on an element which is inside a .dropdown-toggle element?!
  974. //if so, it means we should toggle a submenu
  975. var link_element = $(ev.target).closest('a');
  976. if(!link_element || link_element.length == 0) return;//return if not clicked inside a link element
  977. var minimized = self.minimized && !self.collapsible;
  978. //if .sidebar is .navbar-collapse and in small device mode, then let minimized be uneffective
  979. if( !link_element.hasClass('dropdown-toggle') ) {//it doesn't have a submenu return
  980. //just one thing before we return
  981. //if sidebar is collapsed(minimized) and we click on a first level menu item
  982. //and the click is on the icon, not on the menu text then let's cancel event and cancel navigation
  983. //Good for touch devices, that when the icon is tapped to see the menu text, navigation is cancelled
  984. //navigation is only done when menu text is tapped
  985. if( ace.click_event == 'tap'
  986. &&
  987. minimized
  988. &&
  989. link_element.get(0).parentNode.parentNode == nav_list )//only level-1 links
  990. {
  991. var text = link_element.find('.menu-text').get(0);
  992. if( text != null && ev.target != text && !$.contains(text , ev.target) ) {//not clicking on the text or its children
  993. ev.preventDefault();
  994. return false;
  995. }
  996. }
  997. //ios safari only has a bit of a problem not navigating to link address when scrolling down
  998. //specify data-link attribute to ignore this
  999. if(ace.vars['ios_safari'] && link_element.attr('data-link') !== 'false') {
  1000. //only ios safari has a bit of a problem not navigating to link address when scrolling down
  1001. //please see issues section in documentation
  1002. document.location = link_element.attr('href');
  1003. ev.preventDefault();
  1004. return false;
  1005. }
  1006. return;
  1007. }
  1008. ev.preventDefault();
  1009. var sub = link_element.siblings('.submenu').get(0);
  1010. if(!sub) return false;
  1011. var $sub = $(sub);
  1012. var height_change = 0;//the amount of height change in .nav-list
  1013. var parent_ul = sub.parentNode.parentNode;
  1014. if
  1015. (
  1016. ( minimized && parent_ul == nav_list )
  1017. ||
  1018. ( ( $sub.parent().hasClass('hover') && $sub.css('position') == 'absolute' ) && !self.collapsible )
  1019. )
  1020. {
  1021. return false;
  1022. }
  1023. var sub_hidden = (sub.scrollHeight == 0)
  1024. //if not open and visible, let's open it and make it visible
  1025. if( sub_hidden ) {//being shown now
  1026. $(parent_ul).find('> .open > .submenu').each(function() {
  1027. //close all other open submenus except for the active one
  1028. if(this != sub && !$(this.parentNode).hasClass('active')) {
  1029. height_change -= this.scrollHeight;
  1030. self.hide(this, self.settings.duration, false);
  1031. }
  1032. })
  1033. }
  1034. if( sub_hidden ) {//being shown now
  1035. self.show(sub, self.settings.duration);
  1036. //if a submenu is being shown and another one previously started to hide, then we may need to update/hide scrollbars
  1037. //but if no previous submenu is being hidden, then no need to check if we need to hide the scrollbars in advance
  1038. if(height_change != 0) height_change += sub.scrollHeight;//we need new updated 'scrollHeight' here
  1039. } else {
  1040. self.hide(sub, self.settings.duration);
  1041. height_change -= sub.scrollHeight;
  1042. //== -1 means submenu is being hidden
  1043. }
  1044. //hide scrollbars if content is going to be small enough that scrollbars is not needed anymore
  1045. //do this almost before submenu hiding begins
  1046. //but when minimized submenu's toggle should have no effect
  1047. if (height_change != 0) {
  1048. if(self.$sidebar.attr('data-sidebar-scroll') == 'true' && !self.minimized)
  1049. self.$sidebar.ace_sidebar_scroll('prehide', height_change)
  1050. }
  1051. return false;
  1052. })
  1053. var submenu_working = false;
  1054. this.show = function(sub, $duration, shouldWait) {
  1055. //'shouldWait' indicates whether to wait for previous transition (submenu toggle) to be complete or not?
  1056. shouldWait = (shouldWait !== false);
  1057. if(shouldWait && submenu_working) return false;
  1058. var $sub = $(sub);
  1059. var event;
  1060. $sub.trigger(event = $.Event('show.ace.submenu'))
  1061. if (event.isDefaultPrevented()) {
  1062. return false;
  1063. }
  1064. if(shouldWait) submenu_working = true;
  1065. $duration = $duration || this.settings.duration;
  1066. $sub.css({
  1067. height: 0,
  1068. overflow: 'hidden',
  1069. display: 'block'
  1070. })
  1071. .removeClass('nav-hide').addClass('nav-show')//only for window < @grid-float-breakpoint and .navbar-collapse.menu-min
  1072. .parent().addClass('open');
  1073. sub.scrollTop = 0;//this is for submenu_hover when sidebar is minimized and a submenu is scrollTop'ed using scrollbars ...
  1074. if( $duration > 0 ) {
  1075. $sub.css({height: sub.scrollHeight,
  1076. 'transition-property': 'height',
  1077. 'transition-duration': ($duration/1000)+'s'})
  1078. }
  1079. var complete = function(ev, trigger) {
  1080. ev && ev.stopPropagation();
  1081. $sub
  1082. .css({'transition-property': '', 'transition-duration': '', overflow:'', height: ''})
  1083. //if(ace.vars['webkit']) ace.helper.redraw(sub);//little Chrome issue, force redraw ;)
  1084. if(trigger !== false) $sub.trigger($.Event('shown.ace.submenu'))
  1085. if(shouldWait) submenu_working = false;
  1086. }
  1087. if( $duration > 0 && !!$.support.transition.end ) {
  1088. $sub.one($.support.transition.end, complete);
  1089. }
  1090. else complete();
  1091. //there is sometimes a glitch, so maybe retry
  1092. if(ace.vars['android']) {
  1093. setTimeout(function() {
  1094. complete(null, false);
  1095. ace.helper.redraw(sub);
  1096. }, $duration + 20);
  1097. }
  1098. return true;
  1099. }
  1100. this.hide = function(sub, $duration, shouldWait) {
  1101. //'shouldWait' indicates whether to wait for previous transition (submenu toggle) to be complete or not?
  1102. shouldWait = (shouldWait !== false);
  1103. if(shouldWait && submenu_working) return false;
  1104. var $sub = $(sub);
  1105. var event;
  1106. $sub.trigger(event = $.Event('hide.ace.submenu'))
  1107. if (event.isDefaultPrevented()) {
  1108. return false;
  1109. }
  1110. if(shouldWait) submenu_working = true;
  1111. $duration = $duration || this.settings.duration;
  1112. $sub.css({
  1113. height: sub.scrollHeight,
  1114. overflow: 'hidden',
  1115. display: 'block'
  1116. })
  1117. .parent().removeClass('open');
  1118. sub.offsetHeight;
  1119. //forces the "sub" to re-consider the new 'height' before transition
  1120. if( $duration > 0 ) {
  1121. $sub.css({'height': 0,
  1122. 'transition-property': 'height',
  1123. 'transition-duration': ($duration/1000)+'s'});
  1124. }
  1125. var complete = function(ev, trigger) {
  1126. ev && ev.stopPropagation();
  1127. $sub
  1128. .css({display: 'none', overflow:'', height: '', 'transition-property': '', 'transition-duration': ''})
  1129. .removeClass('nav-show').addClass('nav-hide')//only for window < @grid-float-breakpoint and .navbar-collapse.menu-min
  1130. if(trigger !== false) $sub.trigger($.Event('hidden.ace.submenu'))
  1131. if(shouldWait) submenu_working = false;
  1132. }
  1133. if( $duration > 0 && !!$.support.transition.end ) {
  1134. $sub.one($.support.transition.end, complete);
  1135. }
  1136. else complete();
  1137. //there is sometimes a glitch, so maybe retry
  1138. if(ace.vars['android']) {
  1139. setTimeout(function() {
  1140. complete(null, false);
  1141. ace.helper.redraw(sub);
  1142. }, $duration + 20);
  1143. }
  1144. return true;
  1145. }
  1146. this.toggle = function(sub, $duration) {
  1147. $duration = $duration || self.settings.duration;
  1148. if( sub.scrollHeight == 0 ) {//if an element is hidden scrollHeight becomes 0
  1149. if( this.show(sub, $duration) ) return 1;
  1150. } else {
  1151. if( this.hide(sub, $duration) ) return -1;
  1152. }
  1153. return 0;
  1154. }
  1155. //sidebar vars
  1156. var minimized_menu_class = 'menu-min';
  1157. var responsive_min_class = 'responsive-min';
  1158. var horizontal_menu_class = 'h-sidebar';
  1159. var sidebar_mobile_style = function() {
  1160. //differnet mobile menu styles
  1161. this.mobile_style = 1;//default responsive mode with toggle button inside navbar
  1162. if(this.$sidebar.hasClass('responsive') && !$('.menu-toggler[data-target="#'+this.$sidebar.attr('id')+'"]').hasClass('navbar-toggle')) this.mobile_style = 2;//toggle button behind sidebar
  1163. else if(this.$sidebar.hasClass(responsive_min_class)) this.mobile_style = 3;//minimized menu
  1164. else if(this.$sidebar.hasClass('navbar-collapse')) this.mobile_style = 4;//collapsible (bootstrap style)
  1165. }
  1166. sidebar_mobile_style.call(self);
  1167. function update_vars() {
  1168. this.mobile_view = this.mobile_style < 4 && this.is_mobile_view();
  1169. this.collapsible = !this.mobile_view && this.is_collapsible();
  1170. this.minimized =
  1171. (!this.collapsible && this.$sidebar.hasClass(minimized_menu_class))
  1172. ||
  1173. (this.mobile_style == 3 && this.mobile_view && this.$sidebar.hasClass(responsive_min_class))
  1174. this.horizontal = !(this.mobile_view || this.collapsible) && this.$sidebar.hasClass(horizontal_menu_class)
  1175. }
  1176. //update some basic variables
  1177. $(window).on('resize.sidebar.vars' , function(){
  1178. update_vars.call(self);
  1179. }).triggerHandler('resize.sidebar.vars')
  1180. }//end of Sidebar
  1181. //sidebar events
  1182. //menu-toggler
  1183. $(document)
  1184. .on(ace.click_event+'.ace.menu', '.menu-toggler', function(e){
  1185. var btn = $(this);
  1186. var sidebar = $(btn.attr('data-target'));
  1187. if(sidebar.length == 0) return;
  1188. e.preventDefault();
  1189. sidebar.toggleClass('display');
  1190. btn.toggleClass('display');
  1191. var click_event = ace.click_event+'.ace.autohide';
  1192. var auto_hide = sidebar.attr('data-auto-hide') === 'true';
  1193. if( btn.hasClass('display') ) {
  1194. //hide menu if clicked outside of it!
  1195. if(auto_hide) {
  1196. $(document).on(click_event, function(ev) {
  1197. if( sidebar.get(0) == ev.target || $.contains(sidebar.get(0), ev.target) ) {
  1198. ev.stopPropagation();
  1199. return;
  1200. }
  1201. sidebar.removeClass('display');
  1202. btn.removeClass('display');
  1203. $(document).off(click_event);
  1204. })
  1205. }
  1206. if(sidebar.attr('data-sidebar-scroll') == 'true') sidebar.ace_sidebar_scroll('reset');
  1207. }
  1208. else {
  1209. if(auto_hide) $(document).off(click_event);
  1210. }
  1211. return false;
  1212. })
  1213. //sidebar collapse/expand button
  1214. .on(ace.click_event+'.ace.menu', '.sidebar-collapse', function(e){
  1215. var target = $(this).attr('data-target'), $sidebar = null;
  1216. if(target) $sidebar = $(target);
  1217. if($sidebar == null || $sidebar.length == 0) $sidebar = $(this).closest('.sidebar');
  1218. if($sidebar.length == 0) return;
  1219. e.preventDefault();
  1220. $sidebar.ace_sidebar('toggleMenu', this);
  1221. })
  1222. //this button is used in `mobile_style = 3` responsive menu style to expand minimized sidebar
  1223. .on(ace.click_event+'.ace.menu', '.sidebar-expand', function(e){
  1224. var target = $(this).attr('data-target'), $sidebar = null;
  1225. if(target) $sidebar = $(target);
  1226. if($sidebar == null || $sidebar.length == 0) $sidebar = $(this).closest('.sidebar');
  1227. if($sidebar.length == 0) return;
  1228. var btn = this;
  1229. e.preventDefault();
  1230. $sidebar.ace_sidebar('toggleResponsive', this);
  1231. var click_event = ace.click_event+'.ace.autohide';
  1232. if($sidebar.attr('data-auto-hide') === 'true') {
  1233. if( $sidebar.hasClass('responsive-max') ) {
  1234. $(document).on(click_event, function(ev) {
  1235. if( $sidebar.get(0) == ev.target || $.contains($sidebar.get(0), ev.target) ) {
  1236. ev.stopPropagation();
  1237. return;
  1238. }
  1239. $sidebar.ace_sidebar('toggleResponsive', btn);
  1240. $(document).off(click_event);
  1241. })
  1242. }
  1243. else {
  1244. $(document).off(click_event);
  1245. }
  1246. }
  1247. })
  1248. $.fn.ace_sidebar = function (option, value) {
  1249. var method_call;
  1250. var $set = this.each(function () {
  1251. var $this = $(this);
  1252. var data = $this.data('ace_sidebar');
  1253. var options = typeof option === 'object' && option;
  1254. if (!data) $this.data('ace_sidebar', (data = new Sidebar(this, options)));
  1255. if (typeof option === 'string' && typeof data[option] === 'function') {
  1256. if(value instanceof Array) method_call = data[option].apply(data, value);
  1257. else method_call = data[option](value);
  1258. }
  1259. });
  1260. return (method_call === undefined) ? $set : method_call;
  1261. };
  1262. $.fn.ace_sidebar.defaults = {
  1263. 'duration': 300
  1264. }
  1265. })(window.jQuery);
  1266. ;/**
  1267. <b>Scrollbars for sidebar</b>. This approach can <span class="text-danger">only</span> be used on <u>fixed</u> sidebar.
  1268. It doesn't use <u>"overflow:hidden"</u> CSS property and therefore can be used with <u>.hover</u> submenus and minimized sidebar.
  1269. Except when in mobile view and menu toggle button is not in the navbar.
  1270. */
  1271. (function($ , undefined) {
  1272. //if( !$.fn.ace_scroll ) return;
  1273. var old_safari = ace.vars['safari'] && navigator.userAgent.match(/version\/[1-5]/i)
  1274. //NOTE
  1275. //Safari on windows has not been updated for a long time.
  1276. //And it has a problem when sidebar is fixed & scrollable and there is a CSS3 animation inside page content.
  1277. //Very probably windows users of safari have migrated to another browser by now!
  1278. var is_element_pos =
  1279. 'getComputedStyle' in window ?
  1280. //el.offsetHeight is used to force redraw and recalculate 'el.style.position' esp. for webkit!
  1281. function(el, pos) { el.offsetHeight; return window.getComputedStyle(el).position == pos }
  1282. :
  1283. function(el, pos) { el.offsetHeight; return $(el).css('position') == pos }
  1284. function Sidebar_Scroll(sidebar , settings) {
  1285. var self = this;
  1286. var $window = $(window);
  1287. var $sidebar = $(sidebar),
  1288. $nav = $sidebar.find('.nav-list'),
  1289. $toggle = $sidebar.find('.sidebar-toggle').eq(0),
  1290. $shortcuts = $sidebar.find('.sidebar-shortcuts').eq(0);
  1291. var nav = $nav.get(0);
  1292. if(!nav) return;
  1293. var attrib_values = ace.helper.getAttrSettings(sidebar, $.fn.ace_sidebar_scroll.defaults);
  1294. this.settings = $.extend({}, $.fn.ace_sidebar_scroll.defaults, settings, attrib_values);
  1295. var scroll_to_active = self.settings.scroll_to_active;
  1296. var ace_sidebar = $sidebar.ace_sidebar('ref');
  1297. $sidebar.attr('data-sidebar-scroll', 'true');
  1298. var scroll_div = null,
  1299. scroll_content = null,
  1300. scroll_content_div = null,
  1301. bar = null,
  1302. track = null,
  1303. ace_scroll = null;
  1304. this.is_scrolling = false;
  1305. var _initiated = false;
  1306. this.sidebar_fixed = is_element_pos(sidebar, 'fixed');
  1307. var $avail_height, $content_height;
  1308. var available_height = function() {
  1309. //available window space
  1310. var offset = $nav.parent().offset();//because `$nav.offset()` considers the "scrolled top" amount as well
  1311. if(self.sidebar_fixed) offset.top -= ace.helper.scrollTop();
  1312. return $window.innerHeight() - offset.top - ( self.settings.include_toggle ? 0 : $toggle.outerHeight() );
  1313. }
  1314. var content_height = function() {
  1315. return nav.clientHeight;//we don't use nav.scrollHeight here, because hover submenus are considered in calculating scrollHeight despite position=absolute!
  1316. }
  1317. var initiate = function(on_page_load) {
  1318. if( _initiated ) return;
  1319. if( !self.sidebar_fixed ) return;//eligible??
  1320. //return if we want scrollbars only on "fixed" sidebar and sidebar is not "fixed" yet!
  1321. //initiate once
  1322. $nav.wrap('<div class="nav-wrap-up pos-rel" />');
  1323. $nav.after('<div><div></div></div>');
  1324. $nav.wrap('<div class="nav-wrap" />');
  1325. if(!self.settings.include_toggle) $toggle.css({'z-index': 1});
  1326. if(!self.settings.include_shortcuts) $shortcuts.css({'z-index': 99});
  1327. scroll_div = $nav.parent().next()
  1328. .ace_scroll({
  1329. size: available_height(),
  1330. //reset: true,
  1331. mouseWheelLock: true,
  1332. hoverReset: false,
  1333. dragEvent: true,
  1334. styleClass: self.settings.scroll_style,
  1335. touchDrag: false//disable touch drag event on scrollbars, we'll add a custom one later
  1336. })
  1337. .closest('.ace-scroll').addClass('nav-scroll');
  1338. ace_scroll = scroll_div.data('ace_scroll');
  1339. scroll_content = scroll_div.find('.scroll-content').eq(0);
  1340. scroll_content_div = scroll_content.find(' > div').eq(0);
  1341. track = $(ace_scroll.get_track());
  1342. bar = track.find('.scroll-bar').eq(0);
  1343. if(self.settings.include_shortcuts && $shortcuts.length != 0) {
  1344. $nav.parent().prepend($shortcuts).wrapInner('<div />');
  1345. $nav = $nav.parent();
  1346. }
  1347. if(self.settings.include_toggle && $toggle.length != 0) {
  1348. $nav.append($toggle);
  1349. $nav.closest('.nav-wrap').addClass('nav-wrap-t');//it just helps to remove toggle button's top border and restore li:last-child's bottom border
  1350. }
  1351. $nav.css({position: 'relative'});
  1352. if( self.settings.scroll_outside == true ) scroll_div.addClass('scrollout');
  1353. nav = $nav.get(0);
  1354. nav.style.top = 0;
  1355. scroll_content.on('scroll.nav', function() {
  1356. nav.style.top = (-1 * this.scrollTop) + 'px';
  1357. });
  1358. //mousewheel library available?
  1359. $nav.on(!!$.event.special.mousewheel ? 'mousewheel.ace_scroll' : 'mousewheel.ace_scroll DOMMouseScroll.ace_scroll', function(event){
  1360. if( !self.is_scrolling || !ace_scroll.is_active() ) {
  1361. return !self.settings.lock_anyway;
  1362. }
  1363. //transfer $nav's mousewheel event to scrollbars
  1364. return scroll_div.trigger(event);
  1365. });
  1366. $nav.on('mouseenter.ace_scroll', function() {
  1367. track.addClass('scroll-hover');
  1368. }).on('mouseleave.ace_scroll', function() {
  1369. track.removeClass('scroll-hover');
  1370. });
  1371. /**
  1372. $(document.body).on('touchmove.nav', function(event) {
  1373. if( self.is_scrolling && $.contains(sidebar, event.target) ) {
  1374. event.preventDefault();
  1375. return false;
  1376. }
  1377. })
  1378. */
  1379. //you can also use swipe event in a similar way //swipe.nav
  1380. var content = scroll_content.get(0);
  1381. $nav.on('ace_drag.nav', function(event) {
  1382. if( !self.is_scrolling || !ace_scroll.is_active() ) {
  1383. event.retval.cancel = true;
  1384. return;
  1385. }
  1386. //if submenu hover is being scrolled let's cancel sidebar scroll!
  1387. if( $(event.target).closest('.can-scroll').length != 0 ) {
  1388. event.retval.cancel = true;
  1389. return;
  1390. }
  1391. if(event.direction == 'up' || event.direction == 'down') {
  1392. ace_scroll.move_bar(true);
  1393. var distance = event.dy;
  1394. distance = parseInt(Math.min($avail_height, distance))
  1395. if(Math.abs(distance) > 2) distance = distance * 2;
  1396. if(distance != 0) {
  1397. content.scrollTop = content.scrollTop + distance;
  1398. nav.style.top = (-1 * content.scrollTop) + 'px';
  1399. }
  1400. }
  1401. });
  1402. //for drag only
  1403. if(self.settings.smooth_scroll) {
  1404. $nav
  1405. .on('touchstart.nav MSPointerDown.nav pointerdown.nav', function(event) {
  1406. $nav.css('transition-property', 'none');
  1407. bar.css('transition-property', 'none');
  1408. })
  1409. .on('touchend.nav touchcancel.nav MSPointerUp.nav MSPointerCancel.nav pointerup.nav pointercancel.nav', function(event) {
  1410. $nav.css('transition-property', 'top');
  1411. bar.css('transition-property', 'top');
  1412. });
  1413. }
  1414. if(old_safari && !self.settings.include_toggle) {
  1415. var toggle = $toggle.get(0);
  1416. if(toggle) scroll_content.on('scroll.safari', function() {
  1417. ace.helper.redraw(toggle);
  1418. });
  1419. }
  1420. _initiated = true;
  1421. //if the active item is not visible, scroll down so that it becomes visible
  1422. //only the first time, on page load
  1423. if(on_page_load == true) {
  1424. self.reset();//try resetting at first
  1425. if( scroll_to_active ) {
  1426. self.scroll_to_active();
  1427. }
  1428. scroll_to_active = false;
  1429. }
  1430. if( typeof self.settings.smooth_scroll === 'number' && self.settings.smooth_scroll > 0) {
  1431. $nav.css({'transition-property': 'top', 'transition-duration': (self.settings.smooth_scroll / 1000).toFixed(2)+'s'})
  1432. bar.css({'transition-property': 'top', 'transition-duration': (self.settings.smooth_scroll / 1500).toFixed(2)+'s'})
  1433. scroll_div
  1434. .on('drag.start', function(e) {
  1435. e.stopPropagation();
  1436. $nav.css('transition-property', 'none')
  1437. })
  1438. .on('drag.end', function(e) {
  1439. e.stopPropagation();
  1440. $nav.css('transition-property', 'top')
  1441. });
  1442. }
  1443. if(ace.vars['android']) {
  1444. //force hide address bar, because its changes don't trigger window resize and become kinda ugly
  1445. var val = ace.helper.scrollTop();
  1446. if(val < 2) {
  1447. window.scrollTo( val, 0 );
  1448. setTimeout( function() {
  1449. self.reset();
  1450. }, 20 );
  1451. }
  1452. var last_height = ace.helper.winHeight() , new_height;
  1453. $(window).on('scroll.ace_scroll', function() {
  1454. if(self.is_scrolling && ace_scroll.is_active()) {
  1455. new_height = ace.helper.winHeight();
  1456. if(new_height != last_height) {
  1457. last_height = new_height;
  1458. self.reset();
  1459. }
  1460. }
  1461. });
  1462. }
  1463. }
  1464. this.scroll_to_active = function() {
  1465. if( !ace_scroll || !ace_scroll.is_active() ) return;
  1466. try {
  1467. //sometimes there's no active item or not 'offsetTop' property
  1468. var $active;
  1469. var vars = ace_sidebar['vars']()
  1470. var nav_list = $sidebar.find('.nav-list')
  1471. if(vars['minimized'] && !vars['collapsible']) {
  1472. $active = nav_list.find('> .active')
  1473. }
  1474. else {
  1475. $active = $nav.find('> .active.hover')
  1476. if($active.length == 0) $active = $nav.find('.active:not(.open)')
  1477. }
  1478. var top = $active.outerHeight();
  1479. nav_list = nav_list.get(0);
  1480. var active = $active.get(0);
  1481. while(active != nav_list) {
  1482. top += active.offsetTop;
  1483. active = active.parentNode;
  1484. }
  1485. var scroll_amount = top - scroll_div.height();
  1486. if(scroll_amount > 0) {
  1487. nav.style.top = -scroll_amount + 'px';
  1488. scroll_content.scrollTop(scroll_amount);
  1489. }
  1490. }catch(e){}
  1491. }
  1492. this.reset = function(recalc) {
  1493. if(recalc === true) {
  1494. this.sidebar_fixed = is_element_pos(sidebar, 'fixed');
  1495. }
  1496. if( !this.sidebar_fixed ) {
  1497. this.disable();
  1498. return;//eligible??
  1499. }
  1500. //return if we want scrollbars only on "fixed" sidebar and sidebar is not "fixed" yet!
  1501. if( !_initiated ) initiate();
  1502. //initiate scrollbars if not yet
  1503. var vars = ace_sidebar['vars']();
  1504. //enable if:
  1505. //menu is not collapsible mode (responsive navbar-collapse mode which has default browser scrollbar)
  1506. //menu is not horizontal or horizontal but mobile view (which is not navbar-collapse)
  1507. //and available height is less than nav's height
  1508. var enable_scroll = !vars['collapsible'] && !vars['horizontal']
  1509. && ($avail_height = available_height()) < ($content_height = nav.clientHeight);
  1510. //we don't use nav.scrollHeight here, because hover submenus are considered in calculating scrollHeight despite position=absolute!
  1511. this.is_scrolling = true;
  1512. if( enable_scroll ) {
  1513. scroll_content_div.css({height: $content_height, width: 8});
  1514. scroll_div.prev().css({'max-height' : $avail_height})
  1515. ace_scroll.update({size: $avail_height})
  1516. ace_scroll.enable();
  1517. ace_scroll.reset();
  1518. }
  1519. if( !enable_scroll || !ace_scroll.is_active() ) {
  1520. if(this.is_scrolling) this.disable();
  1521. }
  1522. else {
  1523. $sidebar.addClass('sidebar-scroll');
  1524. }
  1525. //return this.is_scrolling;
  1526. }
  1527. this.disable = function() {
  1528. this.is_scrolling = false;
  1529. if(scroll_div) {
  1530. scroll_div.css({'height' : '', 'max-height' : ''});
  1531. scroll_content_div.css({height: '', width: ''});//otherwise it will have height and takes up some space even when invisible
  1532. scroll_div.prev().css({'max-height' : ''})
  1533. ace_scroll.disable();
  1534. }
  1535. if(parseInt(nav.style.top) < 0 && self.settings.smooth_scroll && $.support.transition.end) {
  1536. $nav.one($.support.transition.end, function() {
  1537. $sidebar.removeClass('sidebar-scroll');
  1538. $nav.off('.trans');
  1539. });
  1540. } else {
  1541. $sidebar.removeClass('sidebar-scroll');
  1542. }
  1543. nav.style.top = 0;
  1544. }
  1545. this.prehide = function(height_change) {
  1546. if(!this.is_scrolling || ace_sidebar.get('minimized')) return;//when minimized submenu's toggle should have no effect
  1547. if(content_height() + height_change < available_height()) {
  1548. this.disable();
  1549. }
  1550. else if(height_change < 0) {
  1551. //if content height is decreasing
  1552. //let's move nav down while a submenu is being hidden
  1553. var scroll_top = scroll_content.scrollTop() + height_change
  1554. if(scroll_top < 0) return;
  1555. nav.style.top = (-1 * scroll_top) + 'px';
  1556. }
  1557. }
  1558. this._reset = function(recalc) {
  1559. if(recalc === true) {
  1560. this.sidebar_fixed = is_element_pos(sidebar, 'fixed');
  1561. }
  1562. if(ace.vars['webkit'])
  1563. setTimeout(function() { self.reset() } , 0);
  1564. else this.reset();
  1565. }
  1566. this.set_hover = function() {
  1567. if(track) track.addClass('scroll-hover');
  1568. }
  1569. this.get = function(name) {
  1570. if(this.hasOwnProperty(name)) return this[name];
  1571. }
  1572. this.set = function(name, value) {
  1573. if(this.hasOwnProperty(name)) this[name] = value;
  1574. }
  1575. this.ref = function() {
  1576. //return a reference to self
  1577. return this;
  1578. }
  1579. this.updateStyle = function(styleClass) {
  1580. if(ace_scroll == null) return;
  1581. ace_scroll.update({styleClass: styleClass});
  1582. }
  1583. //change scrollbar size after a submenu is hidden/shown
  1584. //but don't change if sidebar is minimized
  1585. $sidebar.on('hidden.ace.submenu.sidebar_scroll shown.ace.submenu.sidebar_scroll', '.submenu', function(e) {
  1586. e.stopPropagation();
  1587. if( !ace_sidebar.get('minimized') ) {
  1588. //webkit has a little bit of a glitch!!!
  1589. self._reset();
  1590. if( e.type == 'shown' ) self.set_hover();
  1591. }
  1592. });
  1593. initiate(true);//true = on_page_load
  1594. }
  1595. //reset on document and window changes
  1596. $(document).on('settings.ace.sidebar_scroll', function(ev, event_name, event_val){
  1597. $('.sidebar[data-sidebar-scroll=true]').each(function() {
  1598. var $this = $(this);
  1599. var sidebar_scroll = $this.ace_sidebar_scroll('ref');
  1600. if( event_name == 'sidebar_collapsed' && is_element_pos(this, 'fixed') ) {
  1601. if( $this.attr('data-sidebar-hover') == 'true' ) $this.ace_sidebar_hover('reset');
  1602. sidebar_scroll._reset();
  1603. }
  1604. else if( event_name === 'sidebar_fixed' || event_name === 'navbar_fixed' ) {
  1605. var is_scrolling = sidebar_scroll.get('is_scrolling');
  1606. var sidebar_fixed = is_element_pos(this, 'fixed')
  1607. sidebar_scroll.set('sidebar_fixed', sidebar_fixed);
  1608. if(sidebar_fixed && !is_scrolling) {
  1609. sidebar_scroll._reset();
  1610. }
  1611. else if( !sidebar_fixed ) {
  1612. sidebar_scroll.disable();
  1613. }
  1614. }
  1615. });
  1616. });
  1617. $(window).on('resize.ace.sidebar_scroll', function(){
  1618. $('.sidebar[data-sidebar-scroll=true]').each(function() {
  1619. var $this = $(this);
  1620. if( $this.attr('data-sidebar-hover') == 'true' ) $this.ace_sidebar_hover('reset');
  1621. /////////////
  1622. var sidebar_scroll = $(this).ace_sidebar_scroll('ref');
  1623. var sidebar_fixed = is_element_pos(this, 'fixed')
  1624. sidebar_scroll.set('sidebar_fixed', sidebar_fixed);
  1625. sidebar_scroll._reset();
  1626. });
  1627. })
  1628. /////////////////////////////////////////////
  1629. if(!$.fn.ace_sidebar_scroll) {
  1630. $.fn.ace_sidebar_scroll = function (option, value) {
  1631. var method_call;
  1632. var $set = this.each(function () {
  1633. var $this = $(this);
  1634. var data = $this.data('ace_sidebar_scroll');
  1635. var options = typeof option === 'object' && option;
  1636. if (!data) $this.data('ace_sidebar_scroll', (data = new Sidebar_Scroll(this, options)));
  1637. if (typeof option === 'string' && typeof data[option] === 'function') {
  1638. method_call = data[option](value);
  1639. }
  1640. });
  1641. return (method_call === undefined) ? $set : method_call;
  1642. }
  1643. $.fn.ace_sidebar_scroll.defaults = {
  1644. 'scroll_to_active': true,
  1645. 'include_shortcuts': true,
  1646. 'include_toggle': false,
  1647. 'smooth_scroll': 150,
  1648. 'scroll_outside': false,
  1649. 'scroll_style': '',
  1650. 'lock_anyway': false
  1651. }
  1652. }
  1653. })(window.jQuery);;/**
  1654. <b>Submenu hover adjustment</b>. Automatically move up a submenu to fit into screen when some part of it goes beneath window.
  1655. Pass a "true" value as an argument and submenu will have native browser scrollbars when necessary.
  1656. */
  1657. (function($ , undefined) {
  1658. if( ace.vars['very_old_ie'] ) return;
  1659. //ignore IE7 & below
  1660. var hasTouch = ace.vars['touch'];
  1661. var nativeScroll = ace.vars['old_ie'] || hasTouch;
  1662. var is_element_pos =
  1663. 'getComputedStyle' in window ?
  1664. //el.offsetHeight is used to force redraw and recalculate 'el.style.position' esp. for webkit!
  1665. function(el, pos) { el.offsetHeight; return window.getComputedStyle(el).position == pos }
  1666. :
  1667. function(el, pos) { el.offsetHeight; return $(el).css('position') == pos }
  1668. $(window).on('resize.sidebar.ace_hover', function() {
  1669. $('.sidebar[data-sidebar-hover=true]').ace_sidebar_hover('update_vars').ace_sidebar_hover('reset');
  1670. })
  1671. $(document).on('settings.ace.ace_hover', function(e, event_name, event_val) {
  1672. if(event_name == 'sidebar_collapsed') $('.sidebar[data-sidebar-hover=true]').ace_sidebar_hover('reset');
  1673. else if(event_name == 'navbar_fixed') $('.sidebar[data-sidebar-hover=true]').ace_sidebar_hover('update_vars');
  1674. })
  1675. var sidebars = [];
  1676. function Sidebar_Hover(sidebar , settings) {
  1677. var self = this, that = this;
  1678. var attrib_values = ace.helper.getAttrSettings(sidebar, $.fn.ace_sidebar_hover.defaults);
  1679. this.settings = $.extend({}, $.fn.ace_sidebar_hover.defaults, settings, attrib_values);
  1680. var $sidebar = $(sidebar), nav_list = $sidebar.find('.nav-list').get(0);
  1681. $sidebar.attr('data-sidebar-hover', 'true');
  1682. sidebars.push($sidebar);
  1683. var sidebar_vars = {};
  1684. var old_ie = ace.vars['old_ie'];
  1685. var scroll_right = false;
  1686. //scroll style class
  1687. if(hasTouch) self.settings.sub_hover_delay = parseInt(Math.max(self.settings.sub_hover_delay, 2500));//for touch device, delay is at least 2.5sec
  1688. var $window = $(window);
  1689. //navbar used for adding extra offset from top when adjusting submenu
  1690. var $navbar = $('.navbar').eq(0);
  1691. var navbar_fixed = $navbar.css('position') == 'fixed';
  1692. this.update_vars = function() {
  1693. navbar_fixed = $navbar.css('position') == 'fixed';
  1694. }
  1695. self.dirty = false;
  1696. //on window resize or sidebar expand/collapse a previously "pulled up" submenu should be reset back to its default position
  1697. //for example if "pulled up" in "responsive-min" mode, in "fullmode" should not remain "pulled up"
  1698. this.reset = function() {
  1699. if( self.dirty == false ) return;
  1700. self.dirty = false;//so don't reset is not called multiple times in a row!
  1701. $sidebar.find('.submenu').each(function() {
  1702. var $sub = $(this), li = $sub.parent();
  1703. $sub.css({'top': '', 'bottom': '', 'max-height': ''});
  1704. if($sub.hasClass('ace-scroll')) {
  1705. $sub.ace_scroll('disable');
  1706. }
  1707. else {
  1708. $sub.removeClass('sub-scroll');
  1709. }
  1710. if( is_element_pos(this, 'absolute') ) $sub.addClass('can-scroll');
  1711. else $sub.removeClass('can-scroll');
  1712. li.removeClass('pull_up').find('.menu-text:first').css('margin-top', '');
  1713. })
  1714. $sidebar.find('.hover-show').removeClass('hover-show hover-shown hover-flip');
  1715. }
  1716. this.updateStyle = function(newStyle) {
  1717. sub_scroll_style = newStyle;
  1718. $sidebar.find('.submenu.ace-scroll').ace_scroll('update', {styleClass: newStyle});
  1719. }
  1720. this.changeDir = function(dir) {
  1721. scroll_right = (dir === 'right');
  1722. }
  1723. //update submenu scrollbars on submenu hide & show
  1724. var lastScrollHeight = -1;
  1725. //hide scrollbars if it's going to be not needed anymore!
  1726. if(!nativeScroll)
  1727. $sidebar.on('hide.ace.submenu.sidebar_hover', '.submenu', function(e) {
  1728. if(lastScrollHeight < 1) return;
  1729. e.stopPropagation();
  1730. var $sub = $(this).closest('.ace-scroll.can-scroll');
  1731. if($sub.length == 0 || !is_element_pos($sub[0], 'absolute')) return;
  1732. if($sub[0].scrollHeight - this.scrollHeight < lastScrollHeight) {
  1733. $sub.ace_scroll('disable');
  1734. }
  1735. });
  1736. //reset scrollbars
  1737. if(!nativeScroll)
  1738. $sidebar.on('shown.ace.submenu.sidebar_hover hidden.ace.submenu.sidebar_hover', '.submenu', function(e) {
  1739. if(lastScrollHeight < 1) return;
  1740. var $sub = $(this).closest('.ace-scroll.can-scroll');
  1741. if($sub.length == 0 || !is_element_pos($sub[0], 'absolute') ) return;
  1742. var sub_h = $sub[0].scrollHeight;
  1743. if(lastScrollHeight > 14 && sub_h - lastScrollHeight > 4) {
  1744. $sub.ace_scroll('enable').ace_scroll('reset');//don't update track position
  1745. }
  1746. else {
  1747. $sub.ace_scroll('disable');
  1748. }
  1749. });
  1750. ///////////////////////
  1751. var currentScroll = -1;
  1752. //some mobile browsers don't have mouseenter
  1753. var event_1 = !hasTouch ? 'mouseenter.sub_hover' : 'touchstart.sub_hover';// pointerdown.sub_hover';
  1754. var event_2 = !hasTouch ? 'mouseleave.sub_hover' : 'touchend.sub_hover touchcancel.sub_hover';// pointerup.sub_hover pointercancel.sub_hover';
  1755. $sidebar.on(event_1, '.nav-list li, .sidebar-shortcuts', function (e) {
  1756. sidebar_vars = $sidebar.ace_sidebar('vars');
  1757. //ignore if collapsible mode (mobile view .navbar-collapse) so it doesn't trigger submenu movements
  1758. //or return if horizontal but not mobile_view (style 1&3)
  1759. if( sidebar_vars['collapsible'] /**|| sidebar_vars['horizontal']*/ ) return;
  1760. var $this = $(this);
  1761. var shortcuts = false;
  1762. var has_hover = $this.hasClass('hover');
  1763. var sub = $this.find('> .submenu').get(0);
  1764. if( !(sub || ((this.parentNode == nav_list || has_hover || (shortcuts = $this.hasClass('sidebar-shortcuts'))) /**&& sidebar_vars['minimized']*/)) ) {
  1765. if(sub) $(sub).removeClass('can-scroll');
  1766. return;//include .compact and .hover state as well?
  1767. }
  1768. var target_element = sub, is_abs = false;
  1769. if( !target_element && this.parentNode == nav_list ) target_element = $this.find('> a > .menu-text').get(0);
  1770. if( !target_element && shortcuts ) target_element = $this.find('.sidebar-shortcuts-large').get(0);
  1771. if( (!target_element || !(is_abs = is_element_pos(target_element, 'absolute'))) && !has_hover ) {
  1772. if(sub) $(sub).removeClass('can-scroll');
  1773. return;
  1774. }
  1775. var sub_hide = getSubHide(this);
  1776. //var show_sub = false;
  1777. if(sub) {
  1778. if(is_abs) {
  1779. self.dirty = true;
  1780. var newScroll = ace.helper.scrollTop();
  1781. //if submenu is becoming visible for first time or document has been scrolled, then adjust menu
  1782. if( !sub_hide.is_visible() || (!hasTouch && newScroll != currentScroll) || old_ie ) {
  1783. //try to move/adjust submenu if the parent is a li.hover or if submenu is minimized
  1784. //if( is_element_pos(sub, 'absolute') ) {//for example in small device .hover > .submenu may not be absolute anymore!
  1785. $(sub).addClass('can-scroll');
  1786. //show_sub = true;
  1787. if(!old_ie && !hasTouch) adjust_submenu.call(this, sub);
  1788. else {
  1789. //because ie8 needs some time for submenu to be displayed and real value of sub.scrollHeight be kicked in
  1790. var that = this;
  1791. setTimeout(function() { adjust_submenu.call(that, sub) }, 0)
  1792. }
  1793. //}
  1794. //else $(sub).removeClass('can-scroll');
  1795. }
  1796. currentScroll = newScroll;
  1797. }
  1798. else {
  1799. $(sub).removeClass('can-scroll');
  1800. }
  1801. }
  1802. //if(show_sub)
  1803. sub_hide.show();
  1804. }).on(event_2, '.nav-list li, .sidebar-shortcuts', function (e) {
  1805. sidebar_vars = $sidebar.ace_sidebar('vars');
  1806. if( sidebar_vars['collapsible'] /**|| sidebar_vars['horizontal']*/ ) return;
  1807. if( !$(this).hasClass('hover-show') ) return;
  1808. getSubHide(this).hideDelay();
  1809. });
  1810. function subHide(li_sub) {
  1811. var self = li_sub, $self = $(self);
  1812. var timer = null;
  1813. var visible = false;
  1814. this.show = function() {
  1815. if(timer != null) clearTimeout(timer);
  1816. timer = null;
  1817. $self.addClass('hover-show hover-shown');
  1818. visible = true;
  1819. //let's hide .hover-show elements that are not .hover-shown anymore (i.e. marked for hiding in hideDelay)
  1820. for(var i = 0; i < sidebars.length ; i++)
  1821. {
  1822. sidebars[i].find('.hover-show').not('.hover-shown').each(function() {
  1823. getSubHide(this).hide();
  1824. })
  1825. }
  1826. }
  1827. this.hide = function() {
  1828. visible = false;
  1829. $self.removeClass('hover-show hover-shown hover-flip');
  1830. if(timer != null) clearTimeout(timer);
  1831. timer = null;
  1832. var sub = $self.find('> .submenu').get(0);
  1833. if(sub) getSubScroll(sub, 'hide');
  1834. }
  1835. this.hideDelay = function(callback) {
  1836. if(timer != null) clearTimeout(timer);
  1837. $self.removeClass('hover-shown');//somehow marked for hiding
  1838. timer = setTimeout(function() {
  1839. visible = false;
  1840. $self.removeClass('hover-show hover-flip');
  1841. timer = null;
  1842. var sub = $self.find('> .submenu').get(0);
  1843. if(sub) getSubScroll(sub, 'hide');
  1844. if(typeof callback === 'function') callback.call(this);
  1845. }, that.settings.sub_hover_delay);
  1846. }
  1847. this.is_visible = function() {
  1848. return visible;
  1849. }
  1850. }
  1851. function getSubHide(el) {
  1852. var sub_hide = $(el).data('subHide');
  1853. if(!sub_hide) $(el).data('subHide', (sub_hide = new subHide(el)));
  1854. return sub_hide;
  1855. }
  1856. function getSubScroll(el, func) {
  1857. var sub_scroll = $(el).data('ace_scroll');
  1858. if(!sub_scroll) return false;
  1859. if(typeof func === 'string') {
  1860. sub_scroll[func]();
  1861. return true;
  1862. }
  1863. return sub_scroll;
  1864. }
  1865. function adjust_submenu(sub) {
  1866. var $li = $(this);
  1867. var $sub = $(sub);
  1868. sub.style.top = '';
  1869. sub.style.bottom = '';
  1870. var menu_text = null
  1871. if( sidebar_vars['minimized'] && (menu_text = $li.find('.menu-text').get(0)) ) {
  1872. //2nd level items don't have .menu-text
  1873. menu_text.style.marginTop = '';
  1874. }
  1875. var scroll = ace.helper.scrollTop();
  1876. var navbar_height = 0;
  1877. var $scroll = scroll;
  1878. if( navbar_fixed ) {
  1879. navbar_height = sidebar.offsetTop;//$navbar.height();
  1880. $scroll += navbar_height + 1;
  1881. //let's avoid our submenu from going below navbar
  1882. //because of chrome z-index stacking issue and firefox's normal .submenu over fixed .navbar flicker issue
  1883. }
  1884. var off = $li.offset();
  1885. off.top = parseInt(off.top);
  1886. var extra = 0, parent_height;
  1887. sub.style.maxHeight = '';//otherwise scrollHeight won't be consistent in consecutive calls!?
  1888. var sub_h = sub.scrollHeight;
  1889. var parent_height = $li.height();
  1890. if(menu_text) {
  1891. extra = parent_height;
  1892. off.top += extra;
  1893. }
  1894. var sub_bottom = parseInt(off.top + sub_h)
  1895. var move_up = 0;
  1896. var winh = $window.height();
  1897. //if the bottom of menu is going to go below visible window
  1898. var top_space = parseInt(off.top - $scroll - extra);//available space on top
  1899. var win_space = winh;//available window space
  1900. var horizontal = sidebar_vars['horizontal'], horizontal_sub = false;
  1901. if(horizontal && this.parentNode == nav_list) {
  1902. move_up = 0;//don't move up first level submenu in horizontal mode
  1903. off.top += $li.height();
  1904. horizontal_sub = true;//first level submenu
  1905. }
  1906. if(!horizontal_sub && (move_up = (sub_bottom - (winh + scroll))) >= 0 ) {
  1907. //don't move up more than available space
  1908. move_up = move_up < top_space ? move_up : top_space;
  1909. //move it up a bit more if there's empty space
  1910. if(move_up == 0) move_up = 20;
  1911. if(top_space - move_up > 10) {
  1912. move_up += parseInt(Math.min(25, top_space - move_up));
  1913. }
  1914. //move it down if submenu's bottom is going above parent LI
  1915. if(off.top + (parent_height - extra) > (sub_bottom - move_up)) {
  1916. move_up -= (off.top + (parent_height - extra) - (sub_bottom - move_up));
  1917. }
  1918. if(move_up > 0) {
  1919. sub.style.top = -(move_up) + 'px';
  1920. if( menu_text ) {
  1921. menu_text.style.marginTop = -(move_up) + 'px';
  1922. }
  1923. }
  1924. }
  1925. if(move_up < 0) move_up = 0;//when it goes below
  1926. var pull_up = move_up > 0 && move_up > parent_height - 20;
  1927. if(pull_up) {
  1928. $li.addClass('pull_up');
  1929. }
  1930. else $li.removeClass('pull_up');
  1931. //flip submenu if out of window width
  1932. if(horizontal) {
  1933. if($li.parent().parent().hasClass('hover-flip')) $li.addClass('hover-flip');//if a parent is already flipped, flip it then!
  1934. else {
  1935. var sub_off = $sub.offset();
  1936. var sub_w = $sub.width();
  1937. var win_w = $window.width();
  1938. if(sub_off.left + sub_w > win_w) {
  1939. $li.addClass('hover-flip');
  1940. }
  1941. }
  1942. }
  1943. //don't add scrollbars if it contains .hover menus
  1944. var has_hover = $li.hasClass('hover') && !sidebar_vars['mobile_view'];
  1945. if(has_hover && $sub.find('> li > .submenu').length > 0) return;
  1946. //if( ) {
  1947. var scroll_height = (win_space - (off.top - scroll)) + (move_up);
  1948. //if after scroll, the submenu is above parent LI, then move it down
  1949. var tmp = move_up - scroll_height;
  1950. if(tmp > 0 && tmp < parent_height) scroll_height += parseInt(Math.max(parent_height, parent_height - tmp));
  1951. scroll_height -= 5;
  1952. if(scroll_height < 90) {
  1953. return;
  1954. }
  1955. var ace_scroll = false;
  1956. if(!nativeScroll) {
  1957. ace_scroll = getSubScroll(sub);
  1958. if(ace_scroll == false) {
  1959. $sub.ace_scroll({
  1960. //hideOnIdle: true,
  1961. observeContent: true,
  1962. detached: true,
  1963. updatePos: false,
  1964. reset: true,
  1965. mouseWheelLock: true,
  1966. styleClass: self.settings.sub_scroll_style
  1967. });
  1968. ace_scroll = getSubScroll(sub);
  1969. var track = ace_scroll.get_track();
  1970. if(track) {
  1971. //detach it from body and insert it after submenu for better and cosistent positioning
  1972. $sub.after(track);
  1973. }
  1974. }
  1975. ace_scroll.update({size: scroll_height});
  1976. }
  1977. else {
  1978. $sub
  1979. .addClass('sub-scroll')
  1980. .css('max-height', (scroll_height)+'px')
  1981. }
  1982. lastScrollHeight = scroll_height;
  1983. if(!nativeScroll && ace_scroll) {
  1984. if(scroll_height > 14 && sub_h - scroll_height > 4) {
  1985. ace_scroll.enable()
  1986. ace_scroll.reset();
  1987. }
  1988. else {
  1989. ace_scroll.disable();
  1990. }
  1991. //////////////////////////////////
  1992. var track = ace_scroll.get_track();
  1993. if(track) {
  1994. track.style.top = -(move_up - extra - 1) + 'px';
  1995. var off = $sub.position();
  1996. var left = off.left
  1997. if( !scroll_right ) {
  1998. left += ($sub.outerWidth() - ace_scroll.track_size());
  1999. }
  2000. else {
  2001. left += 2;
  2002. }
  2003. track.style.left = parseInt(left) + 'px';
  2004. if(horizontal_sub) {//first level submenu
  2005. track.style.left = parseInt(left - 2) + 'px';
  2006. track.style.top = parseInt(off.top) + (menu_text ? extra - 2 : 0) + 'px';
  2007. }
  2008. }
  2009. }
  2010. //}
  2011. //again force redraw for safari!
  2012. if( ace.vars['safari'] ) {
  2013. ace.helper.redraw(sub)
  2014. }
  2015. }
  2016. }
  2017. /////////////////////////////////////////////
  2018. $.fn.ace_sidebar_hover = function (option, value) {
  2019. var method_call;
  2020. var $set = this.each(function () {
  2021. var $this = $(this);
  2022. var data = $this.data('ace_sidebar_hover');
  2023. var options = typeof option === 'object' && option;
  2024. if (!data) $this.data('ace_sidebar_hover', (data = new Sidebar_Hover(this, options)));
  2025. if (typeof option === 'string' && typeof data[option] === 'function') {
  2026. method_call = data[option](value);
  2027. }
  2028. });
  2029. return (method_call === undefined) ? $set : method_call;
  2030. }
  2031. $.fn.ace_sidebar_hover.defaults = {
  2032. 'sub_sub_hover_delay': 750,
  2033. 'sub_scroll_style': 'no-track scroll-thin'
  2034. }
  2035. })(window.jQuery);
  2036. ;/**
  2037. <b>Widget boxes</b>
  2038. */
  2039. (function($ , undefined) {
  2040. var Widget_Box = function(box, options) {
  2041. this.$box = $(box);
  2042. var that = this;
  2043. //this.options = $.extend({}, $.fn.widget_box.defaults, options);
  2044. this.reload = function() {
  2045. var $box = this.$box;
  2046. var $remove_position = false;
  2047. if($box.css('position') == 'static') {
  2048. $remove_position = true;
  2049. $box.addClass('position-relative');
  2050. }
  2051. $box.append('<div class="widget-box-overlay"><i class="'+ ace.vars['icon'] + 'loading-icon fa fa-spinner fa-spin fa-2x white"></i></div>');
  2052. $box.one('reloaded.ace.widget', function() {
  2053. $box.find('.widget-box-overlay').remove();
  2054. if($remove_position) $box.removeClass('position-relative');
  2055. });
  2056. }
  2057. this.close = function() {
  2058. var $box = this.$box;
  2059. var closeSpeed = 300;
  2060. $box.fadeOut(closeSpeed , function(){
  2061. $box.trigger('closed.ace.widget');
  2062. $box.remove();
  2063. }
  2064. )
  2065. }
  2066. this.toggle = function(type, button) {
  2067. var $box = this.$box;
  2068. var $body = $box.find('.widget-body').eq(0);
  2069. var $icon = null;
  2070. var event_name = typeof type !== 'undefined' ? type : ($box.hasClass('collapsed') ? 'show' : 'hide');
  2071. var event_complete_name = event_name == 'show' ? 'shown' : 'hidden';
  2072. if(typeof button === 'undefined') {
  2073. button = $box.find('> .widget-header a[data-action=collapse]').eq(0);
  2074. if(button.length == 0) button = null;
  2075. }
  2076. if(button) {
  2077. $icon = button.find(ace.vars['.icon']).eq(0);
  2078. var $match
  2079. var $icon_down = null
  2080. var $icon_up = null
  2081. if( ($icon_down = $icon.attr('data-icon-show')) ) {
  2082. $icon_up = $icon.attr('data-icon-hide')
  2083. }
  2084. else if( $match = $icon.attr('class').match(/fa\-(.*)\-(up|down)/) ) {
  2085. $icon_down = 'fa-'+$match[1]+'-down'
  2086. $icon_up = 'fa-'+$match[1]+'-up'
  2087. }
  2088. }
  2089. var expandSpeed = 250;
  2090. var collapseSpeed = 200;
  2091. if( event_name == 'show' ) {
  2092. if($icon) $icon.removeClass($icon_down).addClass($icon_up);
  2093. $body.hide();
  2094. $box.removeClass('collapsed');
  2095. $body.slideDown(expandSpeed, function(){
  2096. $box.trigger(event_complete_name+'.ace.widget')
  2097. })
  2098. }
  2099. else {
  2100. if($icon) $icon.removeClass($icon_up).addClass($icon_down);
  2101. $body.slideUp(collapseSpeed, function(){
  2102. $box.addClass('collapsed')
  2103. $box.trigger(event_complete_name+'.ace.widget')
  2104. }
  2105. );
  2106. }
  2107. }
  2108. this.hide = function() {
  2109. this.toggle('hide');
  2110. }
  2111. this.show = function() {
  2112. this.toggle('show');
  2113. }
  2114. this.fullscreen = function() {
  2115. var $icon = this.$box.find('> .widget-header a[data-action=fullscreen]').find(ace.vars['.icon']).eq(0);
  2116. var $icon_expand = null
  2117. var $icon_compress = null
  2118. if( ($icon_expand = $icon.attr('data-icon1')) ) {
  2119. $icon_compress = $icon.attr('data-icon2')
  2120. }
  2121. else {
  2122. $icon_expand = 'fa-expand';
  2123. $icon_compress = 'fa-compress';
  2124. }
  2125. if(!this.$box.hasClass('fullscreen')) {
  2126. $icon.removeClass($icon_expand).addClass($icon_compress);
  2127. this.$box.addClass('fullscreen');
  2128. applyScrollbars(this.$box, true);
  2129. }
  2130. else {
  2131. $icon.addClass($icon_expand).removeClass($icon_compress);
  2132. this.$box.removeClass('fullscreen');
  2133. applyScrollbars(this.$box, false);
  2134. }
  2135. this.$box.trigger('fullscreened.ace.widget')
  2136. }
  2137. }
  2138. $.fn.widget_box = function (option, value) {
  2139. var method_call;
  2140. var $set = this.each(function () {
  2141. var $this = $(this);
  2142. var data = $this.data('widget_box');
  2143. var options = typeof option === 'object' && option;
  2144. if (!data) $this.data('widget_box', (data = new Widget_Box(this, options)));
  2145. if (typeof option === 'string') method_call = data[option](value);
  2146. });
  2147. return (method_call === undefined) ? $set : method_call;
  2148. };
  2149. $(document).on('click.ace.widget', '.widget-header a[data-action]', function (ev) {
  2150. ev.preventDefault();
  2151. var $this = $(this);
  2152. var $box = $this.closest('.widget-box');
  2153. if( $box.length == 0 || $box.hasClass('ui-sortable-helper') ) return;
  2154. var $widget_box = $box.data('widget_box');
  2155. if (!$widget_box) {
  2156. $box.data('widget_box', ($widget_box = new Widget_Box($box.get(0))));
  2157. }
  2158. var $action = $this.data('action');
  2159. if($action == 'collapse') {
  2160. var event_name = $box.hasClass('collapsed') ? 'show' : 'hide';
  2161. var event
  2162. $box.trigger(event = $.Event(event_name+'.ace.widget'))
  2163. if (event.isDefaultPrevented()) return
  2164. $widget_box.toggle(event_name, $this);
  2165. }
  2166. else if($action == 'close') {
  2167. var event
  2168. $box.trigger(event = $.Event('close.ace.widget'))
  2169. if (event.isDefaultPrevented()) return
  2170. $widget_box.close();
  2171. }
  2172. else if($action == 'reload') {
  2173. $this.blur();
  2174. var event
  2175. $box.trigger(event = $.Event('reload.ace.widget'))
  2176. if (event.isDefaultPrevented()) return
  2177. $widget_box.reload();
  2178. }
  2179. else if($action == 'fullscreen') {
  2180. var event
  2181. $box.trigger(event = $.Event('fullscreen.ace.widget'))
  2182. if (event.isDefaultPrevented()) return
  2183. $widget_box.fullscreen();
  2184. }
  2185. else if($action == 'settings') {
  2186. $box.trigger('setting.ace.widget')
  2187. }
  2188. });
  2189. function applyScrollbars($widget, enable) {
  2190. var $main = $widget.find('.widget-main').eq(0);
  2191. $(window).off('resize.widget.scroll');
  2192. //IE8 has an unresolvable issue!!! re-scrollbaring with unknown values?!
  2193. var nativeScrollbars = ace.vars['old_ie'] || ace.vars['touch'];
  2194. if(enable) {
  2195. var ace_scroll = $main.data('ace_scroll');
  2196. if( ace_scroll ) {
  2197. $main.data('save_scroll', {size: ace_scroll['size'], lock: ace_scroll['lock'], lock_anyway: ace_scroll['lock_anyway']});
  2198. }
  2199. var size = $widget.height() - $widget.find('.widget-header').height() - 10;//extra paddings
  2200. size = parseInt(size);
  2201. $main.css('min-height', size);
  2202. if( !nativeScrollbars ) {
  2203. if( ace_scroll ) {
  2204. $main.ace_scroll('update', {'size': size, 'mouseWheelLock': true, 'lockAnyway': true});
  2205. }
  2206. else {
  2207. $main.ace_scroll({'size': size, 'mouseWheelLock': true, 'lockAnyway': true});
  2208. }
  2209. $main.ace_scroll('enable').ace_scroll('reset');
  2210. }
  2211. else {
  2212. if( ace_scroll ) $main.ace_scroll('disable');
  2213. $main.css('max-height', size).addClass('overflow-scroll');
  2214. }
  2215. $(window)
  2216. .on('resize.widget.scroll', function() {
  2217. var size = $widget.height() - $widget.find('.widget-header').height() - 10;//extra paddings
  2218. size = parseInt(size);
  2219. $main.css('min-height', size);
  2220. if( !nativeScrollbars ) {
  2221. $main.ace_scroll('update', {'size': size}).ace_scroll('reset');
  2222. }
  2223. else {
  2224. $main.css('max-height', size).addClass('overflow-scroll');
  2225. }
  2226. });
  2227. }
  2228. else {
  2229. $main.css('min-height', '');
  2230. var saved_scroll = $main.data('save_scroll');
  2231. if(saved_scroll) {
  2232. $main
  2233. .ace_scroll('update', {'size': saved_scroll['size'], 'mouseWheelLock': saved_scroll['lock'], 'lockAnyway': saved_scroll['lock_anyway']})
  2234. .ace_scroll('enable')
  2235. .ace_scroll('reset');
  2236. }
  2237. if( !nativeScrollbars ) {
  2238. if(!saved_scroll) $main.ace_scroll('disable');
  2239. }
  2240. else {
  2241. $main.css('max-height', '').removeClass('overflow-scroll');
  2242. }
  2243. }
  2244. }
  2245. })(window.jQuery);;/**
  2246. <b>Settings box</b>. It's good for demo only. You don't need this.
  2247. */
  2248. (function($ , undefined) {
  2249. $('#ace-settings-btn').on(ace.click_event, function(e){
  2250. e.preventDefault();
  2251. $(this).toggleClass('open');
  2252. $('#ace-settings-box').toggleClass('open');
  2253. })
  2254. $('#ace-settings-navbar').on('click', function(){
  2255. ace.settings.navbar_fixed(null, this.checked);//@ ace-extra.js
  2256. //$(window).triggerHandler('resize.navbar');
  2257. //force redraw?
  2258. //if(ace.vars['webkit']) ace.helper.redraw(document.body);
  2259. }).each(function(){this.checked = ace.settings.is('navbar', 'fixed')})
  2260. $('#ace-settings-sidebar').on('click', function(){
  2261. ace.settings.sidebar_fixed(null, this.checked);//@ ace-extra.js
  2262. //if(ace.vars['webkit']) ace.helper.redraw(document.body);
  2263. }).each(function(){this.checked = ace.settings.is('sidebar', 'fixed')})
  2264. $('#ace-settings-breadcrumbs').on('click', function(){
  2265. ace.settings.breadcrumbs_fixed(null, this.checked);//@ ace-extra.js
  2266. //if(ace.vars['webkit']) ace.helper.redraw(document.body);
  2267. }).each(function(){this.checked = ace.settings.is('breadcrumbs', 'fixed')})
  2268. $('#ace-settings-add-container').on('click', function(){
  2269. ace.settings.main_container_fixed(null, this.checked);//@ ace-extra.js
  2270. //if(ace.vars['webkit']) ace.helper.redraw(document.body);
  2271. }).each(function(){this.checked = ace.settings.is('main-container', 'fixed')})
  2272. $('#ace-settings-compact').on('click', function(){
  2273. if(this.checked) {
  2274. $('#sidebar').addClass('compact');
  2275. var hover = $('#ace-settings-hover');
  2276. if( hover.length > 0 ) {
  2277. hover.removeAttr('checked').trigger('click');
  2278. }
  2279. }
  2280. else {
  2281. $('#sidebar').removeClass('compact');
  2282. $('#sidebar[data-sidebar-scroll=true]').ace_sidebar_scroll('reset')
  2283. }
  2284. if(ace.vars['old_ie']) ace.helper.redraw($('#sidebar')[0], true);
  2285. })/*.removeAttr('checked')*/
  2286. $('#ace-settings-highlight').on('click', function(){
  2287. if(this.checked) $('#sidebar .nav-list > li').addClass('highlight');
  2288. else $('#sidebar .nav-list > li').removeClass('highlight');
  2289. if(ace.vars['old_ie']) ace.helper.redraw($('#sidebar')[0]);
  2290. })/*.removeAttr('checked')*/
  2291. $('#ace-settings-hover').on('click', function(){
  2292. if($('#sidebar').hasClass('h-sidebar')) return;
  2293. if(this.checked) {
  2294. $('#sidebar li').addClass('hover')
  2295. .filter('.open').removeClass('open').find('> .submenu').css('display', 'none');
  2296. //and remove .open items
  2297. }
  2298. else {
  2299. $('#sidebar li.hover').removeClass('hover');
  2300. var compact = $('#ace-settings-compact');
  2301. if( compact.length > 0 && compact.get(0).checked ) {
  2302. compact.trigger('click');
  2303. }
  2304. }
  2305. $('.sidebar[data-sidebar-hover=true]').ace_sidebar_hover('reset')
  2306. $('.sidebar[data-sidebar-scroll=true]').ace_sidebar_scroll('reset')
  2307. if(ace.vars['old_ie']) ace.helper.redraw($('#sidebar')[0]);
  2308. })/*.removeAttr('checked')*/
  2309. })(jQuery);;/**
  2310. <b>RTL</b> (right-to-left direction for Arabic, Hebrew, Persian languages).
  2311. It's good for demo only.
  2312. You should hard code RTL-specific changes inside your HTML/server-side code.
  2313. Dynamically switching to RTL using Javascript is not a good idea.
  2314. Please refer to documentation for more info.
  2315. */
  2316. (function($ , undefined) {
  2317. //Switching to RTL (right to left) Mode
  2318. $('#ace-settings-rtl').removeAttr('checked').on('click', function(){
  2319. switch_direction();
  2320. });
  2321. //>>> you should hard code changes inside HTML for RTL direction
  2322. //you shouldn't use this function to switch direction
  2323. //this is only for dynamically switching for demonstration
  2324. //take a look at this function to see what changes should be made
  2325. //also take a look at docs for some tips
  2326. var switch_direction = function() {
  2327. if($('#ace-rtl-stylesheet').length == 0) {
  2328. //let's load RTL stylesheet only when needed!
  2329. var ace_style = $('head').find('link.ace-main-stylesheet');
  2330. if(ace_style.length == 0) {
  2331. ace_style = $('head').find('link[href*="/ace.min.css"],link[href*="/ace-part2.min.css"]');
  2332. if(ace_style.length == 0) {
  2333. ace_style = $('head').find('link[href*="/ace.css"],link[href*="/ace-part2.css"]');
  2334. }
  2335. }
  2336. var ace_skins = $('head').find('link#ace-skins-stylesheet');
  2337. var stylesheet_url = ace_style.first().attr('href').replace(/(\.min)?\.css$/i , '-rtl$1.css');
  2338. $.ajax({
  2339. 'url': stylesheet_url
  2340. }).done(function() {
  2341. var new_link = jQuery('<link />', {type : 'text/css', rel: 'stylesheet', 'id': 'ace-rtl-stylesheet'})
  2342. if(ace_skins.length > 0) {
  2343. new_link.insertAfter(ace_skins);
  2344. }
  2345. else if(ace_style.length > 0){
  2346. new_link.insertAfter(ace_style.last());
  2347. }
  2348. else new_link.appendTo('head');
  2349. new_link.attr('href', stylesheet_url);
  2350. //we set "href" after insertion, for IE to work
  2351. applyChanges();
  2352. if(window.Pace && Pace.running) Pace.stop();
  2353. })
  2354. }
  2355. else {
  2356. applyChanges();
  2357. }
  2358. //in ajax when new content is loaded, we dynamically apply RTL changes again
  2359. //please note that this is only for Ace demo
  2360. //for info about RTL see Ace's docs
  2361. $('.page-content-area[data-ajax-content=true]').on('ajaxscriptsloaded.rtl', function() {
  2362. if( $('body').hasClass('rtl') ) {
  2363. applyChanges(this);
  2364. }
  2365. });
  2366. /////////////////////////
  2367. function applyChanges(el) {
  2368. var $body = $(document.body);
  2369. if(!el) $body.toggleClass('rtl');//el is 'body'
  2370. el = el || document.body;
  2371. var $container = $(el);
  2372. $container
  2373. //toggle pull-right class on dropdown-menu
  2374. .find('.dropdown-menu:not(.datepicker-dropdown,.colorpicker)').toggleClass('dropdown-menu-right')
  2375. .end()
  2376. //swap pull-left & pull-right
  2377. .find('.pull-right:not(.dropdown-menu,blockquote,.profile-skills .pull-right)').removeClass('pull-right').addClass('tmp-rtl-pull-right')
  2378. .end()
  2379. .find('.pull-left:not(.dropdown-submenu,.profile-skills .pull-left)').removeClass('pull-left').addClass('pull-right')
  2380. .end()
  2381. .find('.tmp-rtl-pull-right').removeClass('tmp-rtl-pull-right').addClass('pull-left')
  2382. .end()
  2383. .find('.chosen-select').toggleClass('chosen-rtl').next().toggleClass('chosen-rtl');
  2384. function swap_classes(class1, class2) {
  2385. $container
  2386. .find('.'+class1).removeClass(class1).addClass('tmp-rtl-'+class1)
  2387. .end()
  2388. .find('.'+class2).removeClass(class2).addClass(class1)
  2389. .end()
  2390. .find('.tmp-rtl-'+class1).removeClass('tmp-rtl-'+class1).addClass(class2)
  2391. }
  2392. swap_classes('align-left', 'align-right');
  2393. swap_classes('no-padding-left', 'no-padding-right');
  2394. swap_classes('arrowed', 'arrowed-right');
  2395. swap_classes('arrowed-in', 'arrowed-in-right');
  2396. swap_classes('tabs-left', 'tabs-right');
  2397. swap_classes('messagebar-item-left', 'messagebar-item-right');//for inbox page
  2398. $('.modal.aside-vc').ace_aside('flip').ace_aside('insideContainer');
  2399. //mirror all icons and attributes that have a "fa-*-right|left" attrobute
  2400. $container.find('.fa').each(function() {
  2401. if(this.className.match(/ui-icon/) || $(this).closest('.fc-button').length > 0) return;
  2402. //skip mirroring icons of plugins that have built in RTL support
  2403. var l = this.attributes.length;
  2404. for(var i = 0 ; i < l ; i++) {
  2405. var val = this.attributes[i].value;
  2406. if(val.match(/fa\-(?:[\w\-]+)\-left/))
  2407. this.attributes[i].value = val.replace(/fa\-([\w\-]+)\-(left)/i , 'fa-$1-right')
  2408. else if(val.match(/fa\-(?:[\w\-]+)\-right/))
  2409. this.attributes[i].value = val.replace(/fa\-([\w\-]+)\-(right)/i , 'fa-$1-left')
  2410. }
  2411. });
  2412. //browsers are incosistent with horizontal scroll and RTL
  2413. //so let's make our scrollbars LTR and wrap the content inside RTL
  2414. var rtl = $body.hasClass('rtl');
  2415. if(rtl) {
  2416. $container.find('.scroll-hz').addClass('make-ltr')
  2417. .find('.scroll-content')
  2418. .wrapInner('<div class="make-rtl" />');
  2419. $('.sidebar[data-sidebar-hover=true]').ace_sidebar_hover('changeDir', 'right');
  2420. }
  2421. else {
  2422. //remove the wrap
  2423. $container.find('.scroll-hz').removeClass('make-ltr')
  2424. .find('.make-rtl').children().unwrap();
  2425. $('.sidebar[data-sidebar-hover=true]').ace_sidebar_hover('changeDir', 'left');
  2426. }
  2427. if($.fn.ace_scroll) $container.find('.scroll-hz').ace_scroll('reset') //to reset scrollLeft
  2428. //redraw the traffic pie chart on homepage with a different parameter
  2429. try {
  2430. var placeholder = $('#piechart-placeholder');
  2431. if(placeholder.length > 0) {
  2432. var pos = $body.hasClass('rtl') ? 'nw' : 'ne';//draw on north-west or north-east?
  2433. placeholder.data('draw').call(placeholder.get(0) , placeholder, placeholder.data('chart'), pos);
  2434. }
  2435. }catch(e) {}
  2436. ace.helper.redraw(el, true);
  2437. }
  2438. }
  2439. })(jQuery);
  2440. ;/**
  2441. <b>Select a different skin</b>. It's good for demo only.
  2442. You should hard code skin-specific changes inside your HTML/server-side code.
  2443. Please refer to documentation for more info.
  2444. */
  2445. (function($ , undefined) {
  2446. try {
  2447. $('#skin-colorpicker').ace_colorpicker({'auto_pos': false});
  2448. } catch(e) {}
  2449. $('#skin-colorpicker').on('change', function(){
  2450. var skin_class = $(this).find('option:selected').data('skin');
  2451. if($('#ace-skins-stylesheet').length == 0) {
  2452. //let's load skins stylesheet only when needed!
  2453. var ace_style = $('head').find('link.ace-main-stylesheet');
  2454. if(ace_style.length == 0) {
  2455. ace_style = $('head').find('link[href*="/ace.min.css"],link[href*="/ace-part2.min.css"]');
  2456. if(ace_style.length == 0) {
  2457. ace_style = $('head').find('link[href*="/ace.css"],link[href*="/ace-part2.css"]');
  2458. }
  2459. }
  2460. var stylesheet_url = ace_style.first().attr('href').replace(/(\.min)?\.css$/i , '-skins$1.css');
  2461. $.ajax({
  2462. 'url': stylesheet_url
  2463. }).done(function() {
  2464. var new_link = jQuery('<link />', {type : 'text/css', rel: 'stylesheet', 'id': 'ace-skins-stylesheet'})
  2465. if(ace_style.length > 0){
  2466. new_link.insertAfter(ace_style.last());
  2467. }
  2468. else new_link.appendTo('head');
  2469. new_link.attr('href', stylesheet_url);
  2470. //we set "href" after insertion, for IE to work
  2471. applyChanges(skin_class);
  2472. if(window.Pace && Pace.running) Pace.stop();
  2473. })
  2474. }
  2475. else {
  2476. applyChanges(skin_class);
  2477. }
  2478. function applyChanges(skin_class) {
  2479. //skin cookie tip
  2480. var body = $(document.body);
  2481. body.removeClass('no-skin skin-1 skin-2 skin-3');
  2482. //if(skin_class != 'skin-0') {
  2483. body.addClass(skin_class);
  2484. ace.data.set('skin', skin_class);
  2485. //save the selected skin to cookies
  2486. //which can later be used by your server side app to set the skin
  2487. //for example: <body class="<?php echo $_COOKIE['ace_skin']; ?>"
  2488. //} else ace.data.remove('skin');
  2489. var skin3_colors = ['red', 'blue', 'green', ''];
  2490. //undo skin-1
  2491. $('.ace-nav > li.grey').removeClass('dark');
  2492. //undo skin-2
  2493. $('.ace-nav > li').removeClass('no-border margin-1');
  2494. $('.ace-nav > li:not(:last-child)').removeClass('light-pink').find('> a > '+ace.vars['.icon']).removeClass('pink').end().eq(0).find('.badge').removeClass('badge-warning');
  2495. $('.sidebar-shortcuts .btn')
  2496. .removeClass('btn-pink btn-white')
  2497. .find(ace.vars['.icon']).removeClass('white');
  2498. //undo skin-3
  2499. $('.ace-nav > li.grey').removeClass('red').find('.badge').removeClass('badge-yellow');
  2500. $('.sidebar-shortcuts .btn').removeClass('btn-primary btn-white')
  2501. var i = 0;
  2502. $('.sidebar-shortcuts .btn').each(function() {
  2503. $(this).find(ace.vars['.icon']).removeClass(skin3_colors[i++]);
  2504. })
  2505. var skin0_buttons = ['btn-success', 'btn-info', 'btn-warning', 'btn-danger'];
  2506. if(skin_class == 'no-skin') {
  2507. var i = 0;
  2508. $('.sidebar-shortcuts .btn').each(function() {
  2509. $(this).attr('class', 'btn ' + skin0_buttons[i++%4]);
  2510. })
  2511. $('.sidebar[data-sidebar-scroll=true]').ace_sidebar_scroll('updateStyle', '');
  2512. $('.sidebar[data-sidebar-hover=true]').ace_sidebar_hover('updateStyle', 'no-track scroll-thin');
  2513. }
  2514. else if(skin_class == 'skin-1') {
  2515. $('.ace-nav > li.grey').addClass('dark');
  2516. var i = 0;
  2517. $('.sidebar-shortcuts')
  2518. .find('.btn').each(function() {
  2519. $(this).attr('class', 'btn ' + skin0_buttons[i++%4]);
  2520. })
  2521. $('.sidebar[data-sidebar-scroll=true]').ace_sidebar_scroll('updateStyle', 'scroll-white no-track');
  2522. $('.sidebar[data-sidebar-hover=true]').ace_sidebar_hover('updateStyle', 'no-track scroll-thin scroll-white');
  2523. }
  2524. else if(skin_class == 'skin-2') {
  2525. $('.ace-nav > li').addClass('no-border margin-1');
  2526. $('.ace-nav > li:not(:last-child)').addClass('light-pink').find('> a > '+ace.vars['.icon']).addClass('pink').end().eq(0).find('.badge').addClass('badge-warning');
  2527. $('.sidebar-shortcuts .btn').attr('class', 'btn btn-white btn-pink')
  2528. .find(ace.vars['.icon']).addClass('white');
  2529. $('.sidebar[data-sidebar-scroll=true]').ace_sidebar_scroll('updateStyle', 'scroll-white no-track');
  2530. $('.sidebar[data-sidebar-hover=true]').ace_sidebar_hover('updateStyle', 'no-track scroll-thin scroll-white');
  2531. }
  2532. //skin-3
  2533. //change shortcut buttons classes, this should be hard-coded if you want to choose this skin
  2534. else if(skin_class == 'skin-3') {
  2535. body.addClass('no-skin');//because skin-3 has many parts of no-skin as well
  2536. $('.ace-nav > li.grey').addClass('red').find('.badge').addClass('badge-yellow');
  2537. var i = 0;
  2538. $('.sidebar-shortcuts .btn').each(function() {
  2539. $(this).attr('class', 'btn btn-primary btn-white');
  2540. $(this).find(ace.vars['.icon']).addClass(skin3_colors[i++]);
  2541. })
  2542. $('.sidebar[data-sidebar-scroll=true]').ace_sidebar_scroll('updateStyle', 'scroll-dark no-track');
  2543. $('.sidebar[data-sidebar-hover=true]').ace_sidebar_hover('updateStyle', 'no-track scroll-thin');
  2544. }
  2545. //some sizing differences may be there in skins, so reset scrollbar size
  2546. $('.sidebar[data-sidebar-scroll=true]').ace_sidebar_scroll('reset')
  2547. //$('.sidebar[data-sidebar-hover=true]').ace_sidebar_hover('reset')
  2548. if(ace.vars['old_ie']) ace.helper.redraw(document.body, true);
  2549. }
  2550. })
  2551. })(jQuery);;/**
  2552. The widget box reload button/event handler. You should use your own handler. An example is available at <i class="text-info">examples/widgets.html</i>.
  2553. <u><i class="glyphicon glyphicon-flash"></i> You don't need this. Used for demo only</u>
  2554. */
  2555. (function($ , undefined) {
  2556. //***default action for reload in this demo
  2557. //you should remove this and add your own handler for each specific .widget-box
  2558. //when data is finished loading or processing is done you can call $box.trigger('reloaded.ace.widget')
  2559. $(document).on('reload.ace.widget', '.widget-box', function (ev) {
  2560. var $box = $(this);
  2561. //trigger the reloaded event to remove the spinner icon after 1-2 seconds
  2562. setTimeout(function() {
  2563. $box.trigger('reloaded.ace.widget');
  2564. }, parseInt(Math.random() * 1000 + 1000));
  2565. });
  2566. //you may want to do something like this:
  2567. /**
  2568. $('#my-widget-box').on('reload.ace.widget', function(){
  2569. //load new data here
  2570. //and when finished trigger "reloaded" event
  2571. $(this).trigger('reloaded.ace.widget');
  2572. });
  2573. */
  2574. })(window.jQuery);;/**
  2575. The autocomplete dropdown when typing inside search box.
  2576. <u><i class="glyphicon glyphicon-flash"></i> You don't need this. Used for demo only</u>
  2577. */
  2578. (function($ , undefined) {
  2579. ace.vars['US_STATES'] = ["Alabama","Alaska","Arizona","Arkansas","California","Colorado","Connecticut","Delaware","Florida","Georgia","Hawaii","Idaho","Illinois","Indiana","Iowa","Kansas","Kentucky","Louisiana","Maine","Maryland","Massachusetts","Michigan","Minnesota","Mississippi","Missouri","Montana","Nebraska","Nevada","New Hampshire","New Jersey","New Mexico","New York","North Dakota","North Carolina","Ohio","Oklahoma","Oregon","Pennsylvania","Rhode Island","South Carolina","South Dakota","Tennessee","Texas","Utah","Vermont","Virginia","Washington","West Virginia","Wisconsin","Wyoming"]
  2580. try {
  2581. $('#nav-search-input').bs_typeahead({
  2582. source: ace.vars['US_STATES'],
  2583. updater:function (item) {
  2584. //when an item is selected from dropdown menu, focus back to input element
  2585. $('#nav-search-input').focus();
  2586. return item;
  2587. }
  2588. });
  2589. } catch(e) {}
  2590. })(window.jQuery);