theme.js 82 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997
  1. window.theme = {};
  2. // Navigation
  3. (function( $ ) {
  4. 'use strict';
  5. var $items = $( '.nav-main li.nav-parent' );
  6. function expand( li ) {
  7. li.children( 'ul.nav-children' ).slideDown( 'fast', function() {
  8. li.addClass( 'nav-expanded' );
  9. $(this).css( 'display', '' );
  10. ensureVisible( li );
  11. });
  12. }
  13. function collapse( li ) {
  14. li.children('ul.nav-children' ).slideUp( 'fast', function() {
  15. $(this).css( 'display', '' );
  16. li.removeClass( 'nav-expanded' );
  17. });
  18. }
  19. function ensureVisible( li ) {
  20. var scroller = li.offsetParent();
  21. if ( !scroller.get(0) ) {
  22. return false;
  23. }
  24. var top = li.position().top;
  25. if ( top < 0 ) {
  26. scroller.animate({
  27. scrollTop: scroller.scrollTop() + top
  28. }, 'fast');
  29. }
  30. }
  31. $items.find('> a').on('click', function() {
  32. var prev = $( this ).closest('ul.nav').find('> li.nav-expanded' ),
  33. next = $( this ).closest('li');
  34. if ( prev.get( 0 ) !== next.get( 0 ) ) {
  35. collapse( prev );
  36. expand( next );
  37. } else {
  38. collapse( prev );
  39. }
  40. });
  41. }).apply( this, [ jQuery ]);
  42. // Skeleton
  43. (function(theme, $) {
  44. 'use strict';
  45. theme = theme || {};
  46. var $body = $( 'body' ),
  47. $html = $( 'html' ),
  48. $window = $( window ),
  49. isAndroid = navigator.userAgent.toLowerCase().indexOf('android') > -1;
  50. // mobile devices with fixed has a lot of issues when focus inputs and others...
  51. if ( typeof $.browser !== 'undefined' && $.browser.mobile && $html.hasClass('fixed') ) {
  52. $html.removeClass( 'fixed' ).addClass( 'scroll' );
  53. }
  54. var Skeleton = {
  55. options: {
  56. sidebars: {
  57. menu: '#content-menu',
  58. left: '#sidebar-left',
  59. right: '#sidebar-right'
  60. }
  61. },
  62. customScroll: ( !Modernizr.overflowscrolling && !isAndroid && $.fn.nanoScroller !== 'undefined'),
  63. initialize: function() {
  64. this
  65. .setVars()
  66. .build()
  67. .events();
  68. },
  69. setVars: function() {
  70. this.sidebars = {};
  71. this.sidebars.left = {
  72. $el: $( this.options.sidebars.left )
  73. };
  74. this.sidebars.right = {
  75. $el: $( this.options.sidebars.right ),
  76. isOpened: $html.hasClass( 'sidebar-right-opened' )
  77. };
  78. this.sidebars.menu = {
  79. $el: $( this.options.sidebars.menu ),
  80. isOpened: $html.hasClass( 'inner-menu-opened' )
  81. };
  82. return this;
  83. },
  84. build: function() {
  85. if ( typeof $.browser !== 'undefined' && $.browser.mobile ) {
  86. $html.addClass( 'mobile-device' );
  87. } else {
  88. $html.addClass( 'no-mobile-device' );
  89. }
  90. $html.addClass( 'custom-scroll' );
  91. if ( this.customScroll ) {
  92. this.buildSidebarLeft();
  93. this.buildContentMenu();
  94. }
  95. this.buildSidebarRight();
  96. return this;
  97. },
  98. events: function() {
  99. if ( this.customScroll ) {
  100. this.eventsSidebarLeft();
  101. }
  102. this.eventsSidebarRight();
  103. this.eventsContentMenu();
  104. if ( typeof $.browser !== 'undefined' && !this.customScroll && isAndroid ) {
  105. this.fixScroll();
  106. }
  107. return this;
  108. },
  109. fixScroll: function() {
  110. var _self = this;
  111. $window
  112. .on( 'sidebar-left-opened sidebar-right-toggle', function( e, data ) {
  113. _self.preventBodyScrollToggle( data.added );
  114. });
  115. },
  116. buildSidebarLeft: function() {
  117. this.sidebars.left.$nano = this.sidebars.left.$el.find( '.nano' );
  118. this.sidebars.left.$nano.nanoScroller({
  119. alwaysVisible: true,
  120. preventPageScrolling: true
  121. });
  122. return this;
  123. },
  124. eventsSidebarLeft: function() {
  125. var $nano = this.sidebars.left.$nano;
  126. var updateNanoScroll = function() {
  127. if ( $.support.transition ) {
  128. $nano.nanoScroller();
  129. $nano
  130. .one('bsTransitionEnd', updateNanoScroll)
  131. .emulateTransitionEnd(150)
  132. } else {
  133. updateNanoScroll();
  134. }
  135. };
  136. this.sidebars.left.$el
  137. .on( 'click', function() {
  138. updateNanoScroll();
  139. });
  140. $nano
  141. .on( 'mouseenter', function() {
  142. if ( $html.hasClass( 'sidebar-left-collapsed' ) ) {
  143. $nano.nanoScroller();
  144. }
  145. })
  146. .on( 'mouseleave', function() {
  147. if ( $html.hasClass( 'sidebar-left-collapsed' ) ) {
  148. $nano.nanoScroller();
  149. }
  150. });
  151. return this;
  152. },
  153. buildSidebarRight: function() {
  154. this.sidebars.right.isOpened = $html.hasClass( 'sidebar-right-opened' );
  155. if ( this.customScroll ) {
  156. this.sidebars.right.$nano = this.sidebars.right.$el.find( '.nano' );
  157. this.sidebars.right.$nano.nanoScroller({
  158. alwaysVisible: true,
  159. preventPageScrolling: true
  160. });
  161. }
  162. return this;
  163. },
  164. eventsSidebarRight: function() {
  165. var _self = this;
  166. var open = function() {
  167. if ( _self.sidebars.right.isOpened ) {
  168. return close();
  169. }
  170. _self.sidebars.right.isOpened = true;
  171. $html.addClass( 'sidebar-right-opened' );
  172. $window.trigger( 'sidebar-right-toggle', {
  173. added: true,
  174. removed: false
  175. });
  176. $html.on( 'click.close-right-sidebar', function(e) {
  177. e.stopPropagation();
  178. close(e);
  179. });
  180. };
  181. var close = function(e) {
  182. if ( !!e && !!e.target && ($(e.target).closest( '.sidebar-right' ).get(0) || !$(e.target).closest( 'html' ).get(0)) ) {
  183. e.preventDefault();
  184. return false;
  185. }
  186. $html.removeClass( 'sidebar-right-opened' );
  187. $html.off( 'click.close-right-sidebar' );
  188. $window.trigger( 'sidebar-right-toggle', {
  189. added: false,
  190. removed: true
  191. });
  192. _self.sidebars.right.isOpened = false;
  193. };
  194. var bind = function() {
  195. $('[data-open="sidebar-right"]').on('click', function(e) {
  196. var $el = $(this);
  197. e.stopPropagation();
  198. if ( $el.is('a') )
  199. e.preventDefault();
  200. open();
  201. });
  202. };
  203. this.sidebars.right.$el.find( '.mobile-close' )
  204. .on( 'click', function( e ) {
  205. e.preventDefault();
  206. $html.trigger( 'click.close-right-sidebar' );
  207. });
  208. bind();
  209. return this;
  210. },
  211. buildContentMenu: function() {
  212. if ( !$html.hasClass( 'fixed' ) ) {
  213. return false;
  214. }
  215. this.sidebars.menu.$nano = this.sidebars.menu.$el.find( '.nano' );
  216. this.sidebars.menu.$nano.nanoScroller({
  217. alwaysVisible: true,
  218. preventPageScrolling: true
  219. });
  220. return this;
  221. },
  222. eventsContentMenu: function() {
  223. var _self = this;
  224. var open = function() {
  225. if ( _self.sidebars.menu.isOpened ) {
  226. return close();
  227. }
  228. _self.sidebars.menu.isOpened = true;
  229. $html.addClass( 'inner-menu-opened' );
  230. $window.trigger( 'inner-menu-toggle', {
  231. added: true,
  232. removed: false
  233. });
  234. $html.on( 'click.close-inner-menu', function(e) {
  235. close(e);
  236. });
  237. };
  238. var close = function(e) {
  239. if ( !!e && !!e.target && !$(e.target).closest( '.inner-menu-collapse' ).get(0) && ($(e.target).closest( '.inner-menu' ).get(0) || !$(e.target).closest( 'html' ).get(0)) ) {
  240. return false;
  241. }
  242. e.stopPropagation();
  243. $html.removeClass( 'inner-menu-opened' );
  244. $html.off( 'click.close-inner-menu' );
  245. $window.trigger( 'inner-menu-toggle', {
  246. added: false,
  247. removed: true
  248. });
  249. _self.sidebars.menu.isOpened = false;
  250. };
  251. var bind = function() {
  252. $('[data-open="inner-menu"]').on('click', function(e) {
  253. var $el = $(this);
  254. e.stopPropagation();
  255. if ( $el.is('a') )
  256. e.preventDefault();
  257. open();
  258. });
  259. };
  260. bind();
  261. /* Nano Scroll */
  262. if ( $html.hasClass( 'fixed' ) ) {
  263. var $nano = this.sidebars.menu.$nano;
  264. var updateNanoScroll = function() {
  265. if ( $.support.transition ) {
  266. $nano.nanoScroller();
  267. $nano
  268. .one('bsTransitionEnd', updateNanoScroll)
  269. .emulateTransitionEnd(150)
  270. } else {
  271. updateNanoScroll();
  272. }
  273. };
  274. this.sidebars.menu.$el
  275. .on( 'click', function() {
  276. updateNanoScroll();
  277. });
  278. }
  279. return this;
  280. },
  281. preventBodyScrollToggle: function( shouldPrevent, $el ) {
  282. setTimeout(function() {
  283. if ( shouldPrevent ) {
  284. $body
  285. .data( 'scrollTop', $body.get(0).scrollTop )
  286. .css({
  287. position: 'fixed',
  288. top: $body.get(0).scrollTop * -1
  289. })
  290. } else {
  291. $body
  292. .css({
  293. position: '',
  294. top: ''
  295. })
  296. .scrollTop( $body.data( 'scrollTop' ) );
  297. }
  298. }, 150);
  299. }
  300. };
  301. // expose to scope
  302. $.extend(theme, {
  303. Skeleton: Skeleton
  304. });
  305. }).apply(this, [ window.theme, jQuery ]);
  306. // Base
  307. (function(theme, $) {
  308. 'use strict';
  309. theme = theme || {};
  310. theme.Skeleton.initialize();
  311. }).apply(this, [ window.theme, jQuery ]);
  312. /*
  313. Name: Theme Admin Extension
  314. Written by: Okler Themes - (http://www.okler.net)
  315. Theme Version: 1.3.0
  316. */
  317. window.theme = {};
  318. // Mailbox
  319. (function(theme, $) {
  320. theme = theme || {};
  321. var instanceName = '__mailbox';
  322. var capitalizeString = function( str ) {
  323. return str.charAt( 0 ).toUpperCase() + str.slice( 1 );
  324. }
  325. var Mailbox = function($wrapper) {
  326. return this.initialize($wrapper);
  327. };
  328. Mailbox.prototype = {
  329. initialize: function($wrapper) {
  330. if ( $wrapper.data( instanceName ) ) {
  331. return this;
  332. }
  333. this.$wrapper = $wrapper;
  334. this
  335. .setVars()
  336. .setData()
  337. .build()
  338. .events();
  339. return this;
  340. },
  341. setVars: function() {
  342. this.view = capitalizeString( this.$wrapper.data( 'mailbox-view' ) || "" );
  343. return this;
  344. },
  345. setData: function() {
  346. this.$wrapper.data(instanceName, this);
  347. return this;
  348. },
  349. build: function() {
  350. if ( typeof this[ 'build' + this.view ] === 'function' ) {
  351. this[ 'build' + this.view ].call( this );
  352. }
  353. return this;
  354. },
  355. events: function() {
  356. if ( typeof this[ 'events' + this.view ] === 'function' ) {
  357. this[ 'events' + this.view ].call( this );
  358. }
  359. return this;
  360. },
  361. buildFolder: function() {
  362. this.$wrapper.find('.mailbox-email-list .nano').nanoScroller({
  363. alwaysVisible: true,
  364. preventPageScrolling: true
  365. });
  366. },
  367. buildEmail: function() {
  368. this.buildComposer();
  369. },
  370. buildCompose: function() {
  371. this.buildComposer();
  372. },
  373. buildComposer: function() {
  374. this.$wrapper.find( '#compose-field' ).summernote({
  375. height: 250,
  376. toolbar: [
  377. ['style', ['style']],
  378. ['font', ['bold', 'italic', 'underline', 'clear']],
  379. ['fontname', ['fontname']],
  380. ['color', ['color']],
  381. ['para', ['ul', 'ol', 'paragraph']],
  382. ['height', ['height']],
  383. ['table', ['table']],
  384. ['insert', ['link', 'picture', 'video']],
  385. ['view', ['fullscreen']],
  386. ['help', ['help']]
  387. ]
  388. });
  389. },
  390. eventsCompose: function() {
  391. var $composer,
  392. $contentBody,
  393. $html,
  394. $innerBody;
  395. $composer = $( '.note-editable' );
  396. $contentBody = $( '.content-body' );
  397. $html = $( 'html' );
  398. $innerBody = $( '.inner-body' );
  399. var adjustComposeSize = function() {
  400. var composerHeight,
  401. composerTop,
  402. contentBodyPaddingBottom,
  403. innerBodyHeight,
  404. viewportHeight,
  405. viewportWidth;
  406. contentBodyPaddingBottom = parseInt( $contentBody.css('paddingBottom'), 10 ) || 0;
  407. viewportHeight = Math.max( document.documentElement.clientHeight, window.innerHeight || 0 );
  408. viewportWidth = Math.max( document.documentElement.clientWidth, window.innerWidth || 0 );
  409. $composer.css( 'height', '' );
  410. if ( viewportWidth < 767 || $html.hasClass('mobile-device') ) {
  411. composerTop = $composer.offset().top;
  412. composerHeight = viewportHeight - composerTop;
  413. } else {
  414. if ( $html.hasClass( 'fixed' ) ) {
  415. composerTop = $composer.offset().top;
  416. } else {
  417. composerTop = $composer.position().top;
  418. }
  419. composerHeight = $innerBody.outerHeight() - composerTop;
  420. }
  421. composerHeight -= contentBodyPaddingBottom;
  422. $composer.css({
  423. height: composerHeight
  424. });
  425. };
  426. var timer;
  427. $(window)
  428. .on( 'resize orientationchange sidebar-left-toggle mailbox-recalc', function() {
  429. clearTimeout( timer );
  430. timer = setTimeout(function() {
  431. adjustComposeSize();
  432. }, 100);
  433. });
  434. adjustComposeSize();
  435. }
  436. };
  437. // expose to scope
  438. $.extend(theme, {
  439. Mailbox: Mailbox
  440. });
  441. // jquery plugin
  442. $.fn.themeMailbox = function(opts) {
  443. return this.each(function() {
  444. var $this = $(this);
  445. if ($this.data(instanceName)) {
  446. return $this.data(instanceName);
  447. } else {
  448. return new Mailbox($this);
  449. }
  450. });
  451. }
  452. }).apply(this, [ window.theme, jQuery ]);
  453. // Lock Screen
  454. (function( $ ) {
  455. 'use strict';
  456. var LockScreen = {
  457. initialize: function() {
  458. this.$body = $( 'body' );
  459. this
  460. .build()
  461. .events();
  462. },
  463. build: function() {
  464. var lockHTML,
  465. userinfo;
  466. userinfo = this.getUserInfo();
  467. this.lockHTML = this.buildTemplate( userinfo );
  468. this.$lock = this.$body.children( '#LockScreenInline' );
  469. this.$userPicture = this.$lock.find( '#LockUserPicture' );
  470. this.$userName = this.$lock.find( '#LockUserName' );
  471. this.$userEmail = this.$lock.find( '#LockUserEmail' );
  472. return this;
  473. },
  474. events: function() {
  475. var _self = this;
  476. this.$body.find( '[data-lock-screen="true"]' ).on( 'click', function( e ) {
  477. e.preventDefault();
  478. _self.show();
  479. });
  480. return this;
  481. },
  482. formEvents: function( $form ) {
  483. var _self = this;
  484. $form.on( 'submit', function( e ) {
  485. e.preventDefault();
  486. _self.hide();
  487. });
  488. },
  489. show: function() {
  490. var _self = this,
  491. userinfo = this.getUserInfo();
  492. this.$userPicture.attr( 'src', userinfo.picture );
  493. this.$userName.text( userinfo.username );
  494. this.$userEmail.text( userinfo.email );
  495. this.$body.addClass( 'show-lock-screen' );
  496. $.magnificPopup.open({
  497. items: {
  498. src: this.lockHTML,
  499. type: 'inline'
  500. },
  501. modal: true,
  502. mainClass: 'mfp-lock-screen',
  503. callbacks: {
  504. change: function() {
  505. _self.formEvents( this.content.find( 'form' ) );
  506. }
  507. }
  508. });
  509. },
  510. hide: function() {
  511. $.magnificPopup.close();
  512. },
  513. getUserInfo: function() {
  514. var $info,
  515. picture,
  516. name,
  517. email;
  518. // always search in case something is changed through ajax
  519. $info = $( '#userbox' );
  520. picture = $info.find( '.profile-picture img' ).attr( 'data-lock-picture' );
  521. name = $info.find( '.profile-info' ).attr( 'data-lock-name' );
  522. email = $info.find( '.profile-info' ).attr( 'data-lock-email' );
  523. return {
  524. picture: picture,
  525. username: name,
  526. email: email
  527. };
  528. },
  529. buildTemplate: function( userinfo ) {
  530. return [
  531. '<section id="LockScreenInline" class="body-sign body-locked body-locked-inline">',
  532. '<div class="center-sign">',
  533. '<div class="panel panel-sign">',
  534. '<div class="panel-body">',
  535. '<form>',
  536. '<div class="current-user text-center">',
  537. '<img id="LockUserPicture" src="{{picture}}" alt="John Doe" class="img-circle user-image" />',
  538. '<h2 id="LockUserName" class="user-name text-dark m-none">{{username}}</h2>',
  539. '<p id="LockUserEmail" class="user-email m-none">{{email}}</p>',
  540. '</div>',
  541. '<div class="form-group mb-lg">',
  542. '<div class="input-group input-group-icon">',
  543. '<input id="pwd" name="pwd" type="password" class="form-control input-lg" placeholder="Password" />',
  544. '<span class="input-group-addon">',
  545. '<span class="icon icon-lg">',
  546. '<i class="fa fa-lock"></i>',
  547. '</span>',
  548. '</span>',
  549. '</div>',
  550. '</div>',
  551. '<div class="row">',
  552. '<div class="col-xs-6">',
  553. '<p class="mt-xs mb-none">',
  554. '<a href="#">Not John Doe?</a>',
  555. '</p>',
  556. '</div>',
  557. '<div class="col-xs-6 text-right">',
  558. '<button type="submit" class="btn btn-primary">Unlock</button>',
  559. '</div>',
  560. '</div>',
  561. '</form>',
  562. '</div>',
  563. '</div>',
  564. '</div>',
  565. '</section>'
  566. ]
  567. .join( '' )
  568. .replace( /\{\{picture\}\}/, userinfo.picture )
  569. .replace( /\{\{username\}\}/, userinfo.username )
  570. .replace( /\{\{email\}\}/, userinfo.email );
  571. }
  572. };
  573. this.LockScreen = LockScreen;
  574. $(function() {
  575. LockScreen.initialize();
  576. });
  577. }).apply(this, [ jQuery ]);
  578. // Panels
  579. (function( $ ) {
  580. $(function() {
  581. $('.panel')
  582. .on( 'click', '.panel-actions a.fa-caret-up', function( e ) {
  583. e.preventDefault();
  584. var $this,
  585. $panel;
  586. $this = $( this );
  587. $panel = $this.closest( '.panel' );
  588. $this
  589. .removeClass( 'fa-caret-up' )
  590. .addClass( 'fa-caret-down' );
  591. $panel.find('.panel-body, .panel-footer').slideDown( 200 );
  592. })
  593. .on( 'click', '.panel-actions a.fa-caret-down', function( e ) {
  594. e.preventDefault();
  595. var $this,
  596. $panel;
  597. $this = $( this );
  598. $panel = $this.closest( '.panel' );
  599. $this
  600. .removeClass( 'fa-caret-down' )
  601. .addClass( 'fa-caret-up' );
  602. $panel.find('.panel-body, .panel-footer').slideUp( 200 );
  603. })
  604. .on( 'click', '.panel-actions a.fa-times', function( e ) {
  605. e.preventDefault();
  606. var $panel,
  607. $row;
  608. $panel = $(this).closest('.panel');
  609. if ( !!( $panel.parent('div').attr('class') || '' ).match( /col-(xs|sm|md|lg)/g ) && $panel.siblings().length === 0 ) {
  610. $row = $panel.closest('.row');
  611. $panel.parent('div').remove();
  612. if ( $row.children().length === 0 ) {
  613. $row.remove();
  614. }
  615. } else {
  616. $panel.remove();
  617. }
  618. });
  619. });
  620. })( jQuery );
  621. // Bootstrap Toggle
  622. (function( $ ) {
  623. 'use strict';
  624. var $window = $( window );
  625. var toggleClass = function( $el ) {
  626. if ( !!$el.data('toggleClassBinded') ) {
  627. return false;
  628. }
  629. var $target,
  630. className,
  631. eventName;
  632. $target = $( $el.attr('data-target') );
  633. className = $el.attr('data-toggle-class');
  634. eventName = $el.attr('data-fire-event');
  635. $el.on('click.toggleClass', function(e) {
  636. e.preventDefault();
  637. $target.toggleClass( className );
  638. var hasClass = $target.hasClass( className );
  639. if ( !!eventName ) {
  640. $window.trigger( eventName, {
  641. added: hasClass,
  642. removed: !hasClass
  643. });
  644. }
  645. });
  646. $el.data('toggleClassBinded', true);
  647. return true;
  648. };
  649. $(function() {
  650. $('[data-toggle-class][data-target]').each(function() {
  651. toggleClass( $(this) );
  652. });
  653. });
  654. }).apply( this, [ jQuery ]);
  655. // Form to Object
  656. (function( $ ) {
  657. 'use strict';
  658. $.fn.formToObject = function() {
  659. var arrayData,
  660. objectData;
  661. arrayData = this.serializeArray();
  662. objectData = {};
  663. $.each( arrayData, function() {
  664. var value;
  665. if (this.value != null) {
  666. value = this.value;
  667. } else {
  668. value = '';
  669. }
  670. if (objectData[this.name] != null) {
  671. if (!objectData[this.name].push) {
  672. objectData[this.name] = [objectData[this.name]];
  673. }
  674. objectData[this.name].push(value);
  675. } else {
  676. objectData[this.name] = value;
  677. }
  678. });
  679. return objectData;
  680. };
  681. })( jQuery );
  682. // Codemirror
  683. (function(theme, $) {
  684. theme = theme || {};
  685. var instanceName = '__codemirror';
  686. var PluginCodeMirror = function($el, opts) {
  687. return this.initialize($el, opts);
  688. };
  689. PluginCodeMirror.defaults = {
  690. lineNumbers: true,
  691. styleActiveLine: true,
  692. matchBrackets: true,
  693. theme: 'monokai'
  694. };
  695. PluginCodeMirror.prototype = {
  696. initialize: function($el, opts) {
  697. if ( $el.data( instanceName ) ) {
  698. return this;
  699. }
  700. this.$el = $el;
  701. this
  702. .setData()
  703. .setOptions(opts)
  704. .build();
  705. return this;
  706. },
  707. setData: function() {
  708. this.$el.data(instanceName, this);
  709. return this;
  710. },
  711. setOptions: function(opts) {
  712. this.options = $.extend( true, {}, PluginCodeMirror.defaults, opts );
  713. return this;
  714. },
  715. build: function() {
  716. CodeMirror.fromTextArea( this.$el.get(0), this.options );
  717. return this;
  718. }
  719. };
  720. // expose to scope
  721. $.extend(theme, {
  722. PluginCodeMirror: PluginCodeMirror
  723. });
  724. // jquery plugin
  725. $.fn.themePluginCodeMirror = function(opts) {
  726. return this.each(function() {
  727. var $this = $(this);
  728. if ($this.data(instanceName)) {
  729. return $this.data(instanceName);
  730. } else {
  731. return new PluginCodeMirror($this, opts);
  732. }
  733. });
  734. }
  735. }).apply(this, [ window.theme, jQuery ]);
  736. // Colorpicker
  737. (function(theme, $) {
  738. theme = theme || {};
  739. var instanceName = '__colorpicker';
  740. var PluginColorPicker = function($el, opts) {
  741. return this.initialize($el, opts);
  742. };
  743. PluginColorPicker.defaults = {
  744. };
  745. PluginColorPicker.prototype = {
  746. initialize: function($el, opts) {
  747. if ( $el.data( instanceName ) ) {
  748. return this;
  749. }
  750. this.$el = $el;
  751. this
  752. .setData()
  753. .setOptions(opts)
  754. .build();
  755. return this;
  756. },
  757. setData: function() {
  758. this.$el.data(instanceName, this);
  759. return this;
  760. },
  761. setOptions: function(opts) {
  762. this.options = $.extend( true, {}, PluginColorPicker.defaults, opts );
  763. return this;
  764. },
  765. build: function() {
  766. this.$el.colorpicker( this.options );
  767. return this;
  768. }
  769. };
  770. // expose to scope
  771. $.extend(theme, {
  772. PluginColorPicker: PluginColorPicker
  773. });
  774. // jquery plugin
  775. $.fn.themePluginColorPicker = function(opts) {
  776. return this.each(function() {
  777. var $this = $(this);
  778. if ($this.data(instanceName)) {
  779. return $this.data(instanceName);
  780. } else {
  781. return new PluginColorPicker($this, opts);
  782. }
  783. });
  784. }
  785. }).apply(this, [ window.theme, jQuery ]);
  786. // Datepicker
  787. (function(theme, $) {
  788. theme = theme || {};
  789. var instanceName = '__datepicker';
  790. var PluginDatePicker = function($el, opts) {
  791. return this.initialize($el, opts);
  792. };
  793. PluginDatePicker.defaults = {
  794. };
  795. PluginDatePicker.prototype = {
  796. initialize: function($el, opts) {
  797. if ( $el.data( instanceName ) ) {
  798. return this;
  799. }
  800. this.$el = $el;
  801. this
  802. .setVars()
  803. .setData()
  804. .setOptions(opts)
  805. .build();
  806. return this;
  807. },
  808. setVars: function() {
  809. this.skin = this.$el.data( 'plugin-skin' );
  810. return this;
  811. },
  812. setData: function() {
  813. this.$el.data(instanceName, this);
  814. return this;
  815. },
  816. setOptions: function(opts) {
  817. this.options = $.extend( true, {}, PluginDatePicker.defaults, opts );
  818. return this;
  819. },
  820. build: function() {
  821. this.$el.datepicker( this.options );
  822. if ( !!this.skin ) {
  823. this.$el.data('datepicker').picker.addClass( 'datepicker-' + this.skin );
  824. }
  825. return this;
  826. }
  827. };
  828. // expose to scope
  829. $.extend(theme, {
  830. PluginDatePicker: PluginDatePicker
  831. });
  832. // jquery plugin
  833. $.fn.themePluginDatePicker = function(opts) {
  834. return this.each(function() {
  835. var $this = $(this);
  836. if ($this.data(instanceName)) {
  837. return $this.data(instanceName);
  838. } else {
  839. return new PluginDatePicker($this, opts);
  840. }
  841. });
  842. }
  843. }).apply(this, [ window.theme, jQuery ]);
  844. // iosSwitcher
  845. (function(theme, $) {
  846. theme = theme || {};
  847. var instanceName = '__IOS7Switch';
  848. var PluginIOS7Switch = function($el) {
  849. return this.initialize($el);
  850. };
  851. PluginIOS7Switch.prototype = {
  852. initialize: function($el) {
  853. if ( $el.data( instanceName ) ) {
  854. return this;
  855. }
  856. this.$el = $el;
  857. this
  858. .setData()
  859. .build();
  860. return this;
  861. },
  862. setData: function() {
  863. this.$el.data(instanceName, this);
  864. return this;
  865. },
  866. build: function() {
  867. var switcher = new Switch( this.$el.get(0) );
  868. $( switcher.el ).on( 'click', function( e ) {
  869. e.preventDefault();
  870. switcher.toggle();
  871. });
  872. return this;
  873. }
  874. };
  875. // expose to scope
  876. $.extend(theme, {
  877. PluginIOS7Switch: PluginIOS7Switch
  878. });
  879. // jquery plugin
  880. $.fn.themePluginIOS7Switch = function(opts) {
  881. return this.each(function() {
  882. var $this = $(this);
  883. if ($this.data(instanceName)) {
  884. return $this.data(instanceName);
  885. } else {
  886. return new PluginIOS7Switch($this);
  887. }
  888. });
  889. }
  890. }).apply(this, [ window.theme, jQuery ]);
  891. // Markdown
  892. (function(theme, $) {
  893. theme = theme || {};
  894. var instanceName = '__markdownEditor';
  895. var PluginMarkdownEditor = function($el, opts) {
  896. return this.initialize($el, opts);
  897. };
  898. PluginMarkdownEditor.defaults = {
  899. iconlibrary: 'fa'
  900. };
  901. PluginMarkdownEditor.prototype = {
  902. initialize: function($el, opts) {
  903. if ( $el.data( instanceName ) ) {
  904. return this;
  905. }
  906. this.$el = $el;
  907. this
  908. .setData()
  909. .setOptions(opts)
  910. .build();
  911. return this;
  912. },
  913. setData: function() {
  914. this.$el.data(instanceName, this);
  915. return this;
  916. },
  917. setOptions: function(opts) {
  918. this.options = $.extend( true, {}, PluginMarkdownEditor.defaults, opts );
  919. return this;
  920. },
  921. build: function() {
  922. this.$el.markdown( this.options );
  923. return this;
  924. }
  925. };
  926. // expose to scope
  927. $.extend(theme, {
  928. PluginMarkdownEditor: PluginMarkdownEditor
  929. });
  930. // jquery plugin
  931. $.fn.themePluginMarkdownEditor = function(opts) {
  932. return this.each(function() {
  933. var $this = $(this);
  934. if ($this.data(instanceName)) {
  935. return $this.data(instanceName);
  936. } else {
  937. return new PluginMarkdownEditor($this, opts);
  938. }
  939. });
  940. }
  941. }).apply(this, [ window.theme, jQuery ]);
  942. // Masked Input
  943. (function(theme, $) {
  944. theme = theme || {};
  945. var instanceName = '__maskedInput';
  946. var PluginMaskedInput = function($el, opts) {
  947. return this.initialize($el, opts);
  948. };
  949. PluginMaskedInput.defaults = {
  950. };
  951. PluginMaskedInput.prototype = {
  952. initialize: function($el, opts) {
  953. if ( $el.data( instanceName ) ) {
  954. return this;
  955. }
  956. this.$el = $el;
  957. this
  958. .setData()
  959. .setOptions(opts)
  960. .build();
  961. return this;
  962. },
  963. setData: function() {
  964. this.$el.data(instanceName, this);
  965. return this;
  966. },
  967. setOptions: function(opts) {
  968. this.options = $.extend( true, {}, PluginMaskedInput.defaults, opts );
  969. return this;
  970. },
  971. build: function() {
  972. this.$el.mask( this.$el.data('input-mask'), this.options );
  973. return this;
  974. }
  975. };
  976. // expose to scope
  977. $.extend(theme, {
  978. PluginMaskedInput: PluginMaskedInput
  979. });
  980. // jquery plugin
  981. $.fn.themePluginMaskedInput = function(opts) {
  982. return this.each(function() {
  983. var $this = $(this);
  984. if ($this.data(instanceName)) {
  985. return $this.data(instanceName);
  986. } else {
  987. return new PluginMaskedInput($this, opts);
  988. }
  989. });
  990. }
  991. }).apply(this, [ window.theme, jQuery ]);
  992. // MaxLength
  993. (function(theme, $) {
  994. theme = theme || {};
  995. var instanceName = '__maxlength';
  996. var PluginMaxLength = function($el, opts) {
  997. return this.initialize($el, opts);
  998. };
  999. PluginMaxLength.defaults = {
  1000. alwaysShow: true,
  1001. placement: 'bottom-left',
  1002. warningClass: 'label label-success bottom-left',
  1003. limitReachedClass: 'label label-danger bottom-left'
  1004. };
  1005. PluginMaxLength.prototype = {
  1006. initialize: function($el, opts) {
  1007. if ( $el.data( instanceName ) ) {
  1008. return this;
  1009. }
  1010. this.$el = $el;
  1011. this
  1012. .setData()
  1013. .setOptions(opts)
  1014. .build();
  1015. return this;
  1016. },
  1017. setData: function() {
  1018. this.$el.data(instanceName, this);
  1019. return this;
  1020. },
  1021. setOptions: function(opts) {
  1022. this.options = $.extend( true, {}, PluginMaxLength.defaults, opts );
  1023. return this;
  1024. },
  1025. build: function() {
  1026. this.$el.maxlength( this.options );
  1027. return this;
  1028. }
  1029. };
  1030. // expose to scope
  1031. $.extend(theme, {
  1032. PluginMaxLength: PluginMaxLength
  1033. });
  1034. // jquery plugin
  1035. $.fn.themePluginMaxLength = function(opts) {
  1036. return this.each(function() {
  1037. var $this = $(this);
  1038. if ($this.data(instanceName)) {
  1039. return $this.data(instanceName);
  1040. } else {
  1041. return new PluginMaxLength($this, opts);
  1042. }
  1043. });
  1044. }
  1045. }).apply(this, [ window.theme, jQuery ]);
  1046. // MultiSelect
  1047. (function(theme, $) {
  1048. theme = theme || {};
  1049. var instanceName = '__multiselect';
  1050. var PluginMultiSelect = function($el, opts) {
  1051. return this.initialize($el, opts);
  1052. };
  1053. PluginMultiSelect.defaults = {
  1054. templates: {
  1055. filter: '<div class="input-group"><span class="input-group-addon"><i class="fa fa-search"></i></span><input class="form-control multiselect-search" type="text"></div>'
  1056. }
  1057. };
  1058. PluginMultiSelect.prototype = {
  1059. initialize: function($el, opts) {
  1060. if ( $el.data( instanceName ) ) {
  1061. return this;
  1062. }
  1063. this.$el = $el;
  1064. this
  1065. .setData()
  1066. .setOptions(opts)
  1067. .build();
  1068. return this;
  1069. },
  1070. setData: function() {
  1071. this.$el.data(instanceName, this);
  1072. return this;
  1073. },
  1074. setOptions: function(opts) {
  1075. this.options = $.extend( true, {}, PluginMultiSelect.defaults, opts );
  1076. return this;
  1077. },
  1078. build: function() {
  1079. this.$el.multiselect( this.options );
  1080. return this;
  1081. }
  1082. };
  1083. // expose to scope
  1084. $.extend(theme, {
  1085. PluginMultiSelect: PluginMultiSelect
  1086. });
  1087. // jquery plugin
  1088. $.fn.themePluginMultiSelect = function(opts) {
  1089. return this.each(function() {
  1090. var $this = $(this);
  1091. if ($this.data(instanceName)) {
  1092. return $this.data(instanceName);
  1093. } else {
  1094. return new PluginMultiSelect($this, opts);
  1095. }
  1096. });
  1097. }
  1098. }).apply(this, [ window.theme, jQuery ]);
  1099. // Select2
  1100. (function(theme, $) {
  1101. theme = theme || {};
  1102. var instanceName = '__select2';
  1103. var PluginSelect2 = function($el, opts) {
  1104. return this.initialize($el, opts);
  1105. };
  1106. PluginSelect2.defaults = {
  1107. };
  1108. PluginSelect2.prototype = {
  1109. initialize: function($el, opts) {
  1110. if ( $el.data( instanceName ) ) {
  1111. return this;
  1112. }
  1113. this.$el = $el;
  1114. this
  1115. .setData()
  1116. .setOptions(opts)
  1117. .build();
  1118. return this;
  1119. },
  1120. setData: function() {
  1121. this.$el.data(instanceName, this);
  1122. return this;
  1123. },
  1124. setOptions: function(opts) {
  1125. this.options = $.extend( true, {}, PluginSelect2.defaults, opts );
  1126. return this;
  1127. },
  1128. build: function() {
  1129. this.$el.select2( this.options );
  1130. return this;
  1131. }
  1132. };
  1133. // expose to scope
  1134. $.extend(theme, {
  1135. PluginSelect2: PluginSelect2
  1136. });
  1137. // jquery plugin
  1138. $.fn.themePluginSelect2 = function(opts) {
  1139. return this.each(function() {
  1140. var $this = $(this);
  1141. if ($this.data(instanceName)) {
  1142. return $this.data(instanceName);
  1143. } else {
  1144. return new PluginSelect2($this, opts);
  1145. }
  1146. });
  1147. }
  1148. }).apply(this, [ window.theme, jQuery ]);
  1149. // Spinner
  1150. (function(theme, $) {
  1151. theme = theme || {};
  1152. var instanceName = '__spinner';
  1153. var PluginSpinner = function($el, opts) {
  1154. return this.initialize($el, opts);
  1155. };
  1156. PluginSpinner.defaults = {
  1157. };
  1158. PluginSpinner.prototype = {
  1159. initialize: function($el, opts) {
  1160. if ( $el.data( instanceName ) ) {
  1161. return this;
  1162. }
  1163. this.$el = $el;
  1164. this
  1165. .setData()
  1166. .setOptions(opts)
  1167. .build();
  1168. return this;
  1169. },
  1170. setData: function() {
  1171. this.$el.data(instanceName, this);
  1172. return this;
  1173. },
  1174. setOptions: function(opts) {
  1175. this.options = $.extend( true, {}, PluginSpinner.defaults, opts );
  1176. return this;
  1177. },
  1178. build: function() {
  1179. this.$el.spinner( this.options );
  1180. return this;
  1181. }
  1182. };
  1183. // expose to scope
  1184. $.extend(theme, {
  1185. PluginSpinner: PluginSpinner
  1186. });
  1187. // jquery plugin
  1188. $.fn.themePluginSpinner = function(opts) {
  1189. return this.each(function() {
  1190. var $this = $(this);
  1191. if ($this.data(instanceName)) {
  1192. return $this.data(instanceName);
  1193. } else {
  1194. return new PluginSpinner($this, opts);
  1195. }
  1196. });
  1197. }
  1198. }).apply(this, [ window.theme, jQuery ]);
  1199. // SummerNote
  1200. (function(theme, $) {
  1201. theme = theme || {};
  1202. var instanceName = '__summernote';
  1203. var PluginSummerNote = function($el, opts) {
  1204. return this.initialize($el, opts);
  1205. };
  1206. PluginSummerNote.defaults = {
  1207. onfocus: function() {
  1208. $( this ).closest( '.note-editor' ).addClass( 'active' );
  1209. },
  1210. onblur: function() {
  1211. $( this ).closest( '.note-editor' ).removeClass( 'active' );
  1212. }
  1213. };
  1214. PluginSummerNote.prototype = {
  1215. initialize: function($el, opts) {
  1216. if ( $el.data( instanceName ) ) {
  1217. return this;
  1218. }
  1219. this.$el = $el;
  1220. this
  1221. .setData()
  1222. .setOptions(opts)
  1223. .build();
  1224. return this;
  1225. },
  1226. setData: function() {
  1227. this.$el.data(instanceName, this);
  1228. return this;
  1229. },
  1230. setOptions: function(opts) {
  1231. this.options = $.extend( true, {}, PluginSummerNote.defaults, opts );
  1232. return this;
  1233. },
  1234. build: function() {
  1235. this.$el.summernote( this.options );
  1236. return this;
  1237. }
  1238. };
  1239. // expose to scope
  1240. $.extend(theme, {
  1241. PluginSummerNote: PluginSummerNote
  1242. });
  1243. // jquery plugin
  1244. $.fn.themePluginSummerNote = function(opts) {
  1245. return this.each(function() {
  1246. var $this = $(this);
  1247. if ($this.data(instanceName)) {
  1248. return $this.data(instanceName);
  1249. } else {
  1250. return new PluginSummerNote($this, opts);
  1251. }
  1252. });
  1253. }
  1254. }).apply(this, [ window.theme, jQuery ]);
  1255. // TextArea AutoSize
  1256. (function(theme, $) {
  1257. theme = theme || {};
  1258. var initialized = false;
  1259. var instanceName = '__textareaAutosize';
  1260. var PluginTextAreaAutoSize = function($el, opts) {
  1261. return this.initialize($el, opts);
  1262. };
  1263. PluginTextAreaAutoSize.defaults = {
  1264. };
  1265. PluginTextAreaAutoSize.prototype = {
  1266. initialize: function($el, opts) {
  1267. if (initialized) {
  1268. return this;
  1269. }
  1270. this.$el = $el;
  1271. this
  1272. .setData()
  1273. .setOptions(opts)
  1274. .build();
  1275. return this;
  1276. },
  1277. setData: function() {
  1278. this.$el.data(instanceName, this);
  1279. return this;
  1280. },
  1281. setOptions: function(opts) {
  1282. this.options = $.extend( true, {}, PluginTextAreaAutoSize.defaults, opts );
  1283. return this;
  1284. },
  1285. build: function() {
  1286. this.$el.autosize( this.options );
  1287. return this;
  1288. }
  1289. };
  1290. // expose to scope
  1291. $.extend(theme, {
  1292. PluginTextAreaAutoSize: PluginTextAreaAutoSize
  1293. });
  1294. // jquery plugin
  1295. $.fn.themePluginTextAreaAutoSize = function(opts) {
  1296. return this.each(function() {
  1297. var $this = $(this);
  1298. if ($this.data(instanceName)) {
  1299. return $this.data(instanceName);
  1300. } else {
  1301. return new PluginTextAreaAutoSize($this, opts);
  1302. }
  1303. });
  1304. }
  1305. }).apply(this, [ window.theme, jQuery ]);
  1306. // TimePicker
  1307. (function(theme, $) {
  1308. theme = theme || {};
  1309. var instanceName = '__timepicker';
  1310. var PluginTimePicker = function($el, opts) {
  1311. return this.initialize($el, opts);
  1312. };
  1313. PluginTimePicker.defaults = {
  1314. disableMousewheel: true
  1315. };
  1316. PluginTimePicker.prototype = {
  1317. initialize: function($el, opts) {
  1318. if ( $el.data( instanceName ) ) {
  1319. return this;
  1320. }
  1321. this.$el = $el;
  1322. this
  1323. .setData()
  1324. .setOptions(opts)
  1325. .build();
  1326. return this;
  1327. },
  1328. setData: function() {
  1329. this.$el.data(instanceName, this);
  1330. return this;
  1331. },
  1332. setOptions: function(opts) {
  1333. this.options = $.extend( true, {}, PluginTimePicker.defaults, opts );
  1334. return this;
  1335. },
  1336. build: function() {
  1337. this.$el.timepicker( this.options );
  1338. return this;
  1339. }
  1340. };
  1341. // expose to scope
  1342. $.extend(theme, {
  1343. PluginTimePicker: PluginTimePicker
  1344. });
  1345. // jquery plugin
  1346. $.fn.themePluginTimePicker = function(opts) {
  1347. return this.each(function() {
  1348. var $this = $(this);
  1349. if ($this.data(instanceName)) {
  1350. return $this.data(instanceName);
  1351. } else {
  1352. return new PluginTimePicker($this, opts);
  1353. }
  1354. });
  1355. }
  1356. }).apply(this, [ window.theme, jQuery ]);
  1357. // Map Builder
  1358. (function( theme, $ ) {
  1359. 'use strict';
  1360. // prevent undefined var
  1361. theme = theme || {};
  1362. // internal var to check if reached limit
  1363. var timeouts = 0;
  1364. // instance
  1365. var instanceName = '__gmapbuilder';
  1366. // private
  1367. var roundNumber = function( number, precision ) {
  1368. if( precision < 0 ) {
  1369. precision = 0;
  1370. } else if( precision > 10 ) {
  1371. precision = 10;
  1372. }
  1373. var a = [ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000 ];
  1374. return Math.round( number * a[ precision ] ) / a[ precision ];
  1375. };
  1376. // definition
  1377. var GMapBuilder = function( $wrapper, opts ) {
  1378. return this.initialize( $wrapper, opts );
  1379. };
  1380. GMapBuilder.defaults = {
  1381. mapSelector: '#gmap',
  1382. markers: {
  1383. modal: '#MarkerModal',
  1384. list: '#MarkersList',
  1385. removeAll: '#MarkerRemoveAll'
  1386. },
  1387. previewModal: '#ModalPreview',
  1388. getCodeModal: '#ModalGetCode',
  1389. mapOptions: {
  1390. center: {
  1391. lat: -38.908133,
  1392. lng: -13.692628
  1393. },
  1394. panControl: true,
  1395. zoom: 3
  1396. }
  1397. };
  1398. GMapBuilder.prototype = {
  1399. markers: [],
  1400. initialize: function( $wrapper, opts ) {
  1401. this.$wrapper = $wrapper;
  1402. this
  1403. .setData()
  1404. .setOptions( opts )
  1405. .setVars()
  1406. .build()
  1407. .events();
  1408. return this;
  1409. },
  1410. setData: function() {
  1411. this.$wrapper.data( instanceName, this );
  1412. return this;
  1413. },
  1414. setOptions: function( opts ) {
  1415. this.options = $.extend( true, {}, GMapBuilder.defaults, opts );
  1416. return this;
  1417. },
  1418. setVars: function() {
  1419. this.$mapContainer = this.$wrapper.find( this.options.mapSelector );
  1420. this.$previewModal = $( this.options.previewModal );
  1421. this.$getCodeModal = $( this.options.getCodeModal );
  1422. this.marker = {};
  1423. this.marker.$modal = $( this.options.markers.modal );
  1424. this.marker.$form = this.marker.$modal.find( 'form' );
  1425. this.marker.$list = $( this.options.markers.list );
  1426. this.marker.$removeAll = $( this.options.markers.removeAll );
  1427. return this;
  1428. },
  1429. build: function() {
  1430. var _self = this;
  1431. if ( !!window.SnazzyThemes ) {
  1432. var themeOpts = [];
  1433. $.each( window.SnazzyThemes, function( i, theme ) {
  1434. themeOpts.push( $('<option value="' + theme.id + '">' + theme.name + '</option>').data( 'json', theme.json ) );
  1435. });
  1436. this.$wrapper.find( '[data-builder-field="maptheme"]' ).append( themeOpts );
  1437. }
  1438. this.geocoder = new google.maps.Geocoder();
  1439. google.maps.event.addDomListener( window, 'load', function() {
  1440. _self.options.mapOptions.center = new google.maps.LatLng( _self.options.mapOptions.center.lat, _self.options.mapOptions.center.lng );
  1441. _self.map = new google.maps.Map( _self.$mapContainer.get(0), _self.options.mapOptions );
  1442. _self
  1443. .updateControl( 'latlng' )
  1444. .updateControl( 'zoomlevel' );
  1445. _self.mapEvents();
  1446. });
  1447. return this;
  1448. },
  1449. events: function() {
  1450. var _self = this;
  1451. this.$wrapper.find( '[data-builder-field]' ).each(function() {
  1452. var $this = $( this ),
  1453. field,
  1454. value;
  1455. field = $this.data( 'builder-field' );
  1456. $this.on( 'change', function() {
  1457. if ( $this.is( 'select' ) ) {
  1458. value = $this.children( 'option:selected' ).val().toLowerCase();
  1459. } else {
  1460. value = $this.val().toLowerCase();
  1461. }
  1462. _self.updateMap( field, value );
  1463. });
  1464. });
  1465. this.marker.$form.on( 'submit', function( e ) {
  1466. e.preventDefault();
  1467. _self.saveMarker( _self.marker.$form.formToObject() );
  1468. });
  1469. this.marker.$removeAll.on( 'click', function( e ) {
  1470. e.preventDefault();
  1471. _self.removeAllMarkers();
  1472. });
  1473. // preview events
  1474. this.$previewModal.on( 'shown.bs.modal', function() {
  1475. _self.preview();
  1476. });
  1477. this.$previewModal.on( 'hidden.bs.modal', function() {
  1478. _self.$previewModal.find( 'iframe' ).get(0).contentWindow.document.body.innerHTML = '';
  1479. });
  1480. // get code events
  1481. this.$getCodeModal.on( 'shown.bs.modal', function() {
  1482. _self.getCode();
  1483. });
  1484. return this;
  1485. },
  1486. // MAP FUNCTIONS
  1487. // -----------------------------------------------------------------------------
  1488. mapEvents: function() {
  1489. var _self = this;
  1490. google.maps.event.addDomListener( _self.map, 'resize', function() {
  1491. google.maps.event.trigger( _self.map, 'resize' );
  1492. });
  1493. google.maps.event.addListener( this.map, 'center_changed', function() {
  1494. var coords = _self.map.getCenter();
  1495. _self.updateControl( 'latlng', {
  1496. lat: roundNumber( coords.lat(), 6 ),
  1497. lng: roundNumber( coords.lng(), 6 )
  1498. });
  1499. });
  1500. google.maps.event.addListener( this.map, 'zoom_changed', function() {
  1501. _self.updateControl( 'zoomlevel', _self.map.getZoom() );
  1502. });
  1503. google.maps.event.addListener( this.map, 'maptypeid_changed', function() {
  1504. _self.updateControl( 'maptype', _self.map.getMapTypeId() );
  1505. });
  1506. return this;
  1507. },
  1508. updateMap: function( prop, value ) {
  1509. var updateFn;
  1510. updateFn = this.updateMapProperty[ prop ];
  1511. if ( $.isFunction( updateFn ) ) {
  1512. updateFn.apply( this, [ value ] );
  1513. } else {
  1514. console.info( 'missing update function for', prop );
  1515. }
  1516. return this;
  1517. },
  1518. updateMapProperty: {
  1519. latlng: function() {
  1520. var lat,
  1521. lng;
  1522. lat = this.$wrapper.find('[data-builder-field][name="latitude"]').val();
  1523. lng = this.$wrapper.find('[data-builder-field][name="longitude"]').val();
  1524. if ( lat.length > 0 && lng.length > 0 ) {
  1525. this.map.setCenter( new google.maps.LatLng( lat, lng ) );
  1526. }
  1527. return this;
  1528. },
  1529. zoomlevel: function( value ) {
  1530. var value = arguments[ 0 ];
  1531. this.map.setZoom( parseInt( value, 10 ) );
  1532. return this;
  1533. },
  1534. maptypecontrol: function( value ) {
  1535. var options;
  1536. options = {};
  1537. if ( value === 'false' ){
  1538. options.mapTypeControl = false;
  1539. } else {
  1540. options = {
  1541. mapTypeControl: true,
  1542. mapTypeControlOptions: {
  1543. style: google.maps.MapTypeControlStyle[ value.toUpperCase() ]
  1544. }
  1545. };
  1546. }
  1547. this.map.setOptions( options );
  1548. return this;
  1549. },
  1550. zoomcontrol: function( value ) {
  1551. var options;
  1552. options = {};
  1553. if ( value === 'false' ){
  1554. options.zoomControl = false;
  1555. } else {
  1556. options = {
  1557. zoomControl: true,
  1558. zoomControlOptions: {
  1559. style: google.maps.ZoomControlStyle[ value.toUpperCase() ]
  1560. }
  1561. };
  1562. }
  1563. this.map.setOptions( options );
  1564. return this;
  1565. },
  1566. scalecontrol: function( value ) {
  1567. var options;
  1568. options = {};
  1569. options.scaleControl = value !== 'false';
  1570. this.map.setOptions( options );
  1571. return this;
  1572. },
  1573. streetviewcontrol: function( value ) {
  1574. var options;
  1575. options = {};
  1576. options.streetViewControl = value !== 'false';
  1577. this.map.setOptions( options );
  1578. return this;
  1579. },
  1580. pancontrol: function( value ) {
  1581. var options;
  1582. options = {};
  1583. options.panControl = value !== 'false';
  1584. this.map.setOptions( options );
  1585. return this;
  1586. },
  1587. overviewcontrol: function( value ) {
  1588. var options;
  1589. options = {};
  1590. if ( value === 'false' ){
  1591. options.overviewMapControl = false;
  1592. } else {
  1593. options = {
  1594. overviewMapControl: true,
  1595. overviewMapControlOptions: {
  1596. opened: value === 'opened'
  1597. }
  1598. };
  1599. }
  1600. this.map.setOptions( options );
  1601. return this;
  1602. },
  1603. draggablecontrol: function( value ) {
  1604. var options;
  1605. options = {};
  1606. options.draggable = value !== 'false';
  1607. this.map.setOptions( options );
  1608. return this;
  1609. },
  1610. clicktozoomcontrol: function( value ) {
  1611. var options;
  1612. options = {};
  1613. options.disableDoubleClickZoom = value === 'false';
  1614. this.map.setOptions( options );
  1615. return this;
  1616. },
  1617. scrollwheelcontrol: function( value ) {
  1618. var options;
  1619. options = {};
  1620. options.scrollwheel = value !== 'false';
  1621. this.map.setOptions( options );
  1622. return this;
  1623. },
  1624. maptype: function( value ) {
  1625. var options,
  1626. mapStyles,
  1627. mapType;
  1628. mapStyles = this.$wrapper.find( '[data-builder-field="maptheme"]' ).children( 'option' ).filter( ':selected' ).data( 'json' );
  1629. mapType = google.maps.MapTypeId[ value.toUpperCase() ];
  1630. options = {
  1631. mapTypeId: mapType
  1632. };
  1633. if ( $.inArray( google.maps.MapTypeId[ value.toUpperCase() ], [ 'terrain', 'roadmap' ]) > -1 && !!mapStyles ) {
  1634. options.styles = eval( mapStyles );
  1635. } else {
  1636. options.styles = false;
  1637. this.updateControl( 'maptheme' );
  1638. }
  1639. this.map.setOptions( options );
  1640. },
  1641. maptheme: function( value ) {
  1642. var json,
  1643. mapType,
  1644. options;
  1645. mapType = google.maps.MapTypeId[ this.map.getMapTypeId() === 'terrain' ? 'TERRAIN' : 'ROADMAP' ];
  1646. options = {};
  1647. json = this.$wrapper.find( '[data-builder-field="maptheme"]' ).children( 'option' ).filter( ':selected' ).data( 'json' );
  1648. if ( !json ) {
  1649. options = {
  1650. mapTypeId: mapType,
  1651. styles: false
  1652. };
  1653. } else {
  1654. options = {
  1655. mapTypeId: mapType,
  1656. styles: eval( json )
  1657. };
  1658. }
  1659. this.map.setOptions( options );
  1660. }
  1661. },
  1662. // CONTROLS FUNCTIONS
  1663. // -----------------------------------------------------------------------------
  1664. updateControl: function( prop ) {
  1665. var updateFn;
  1666. updateFn = this.updateControlValue[ prop ];
  1667. if ( $.isFunction( updateFn ) ) {
  1668. updateFn.apply( this );
  1669. } else {
  1670. console.info( 'missing update function for', prop );
  1671. }
  1672. return this;
  1673. },
  1674. updateControlValue: {
  1675. latlng: function() {
  1676. var center = this.map.getCenter();
  1677. this.$wrapper.find('[data-builder-field][name="latitude"]').val( roundNumber( center.lat() , 6 ) );
  1678. this.$wrapper.find('[data-builder-field][name="longitude"]').val( roundNumber( center.lng() , 6 ) );
  1679. },
  1680. zoomlevel: function() {
  1681. var $control,
  1682. level;
  1683. level = this.map.getZoom();
  1684. $control = this.$wrapper.find('[data-builder-field="zoomlevel"]');
  1685. $control
  1686. .children( 'option[value="' + level + '"]' )
  1687. .prop( 'selected', true );
  1688. if ( $control.hasClass( 'select2-offscreen' ) ) {
  1689. $control.select2( 'val', level );
  1690. }
  1691. },
  1692. maptype: function() {
  1693. var $control,
  1694. mapType;
  1695. mapType = this.map.getMapTypeId();
  1696. $control = this.$wrapper.find('[data-builder-field="maptype"]');
  1697. $control
  1698. .children( 'option[value="' + mapType + '"]' )
  1699. .prop( 'selected', true );
  1700. if ( $control.hasClass( 'select2-offscreen' ) ) {
  1701. $control.select2( 'val', mapType );
  1702. }
  1703. },
  1704. maptheme: function() {
  1705. var $control;
  1706. $control = this.$wrapper.find('[data-builder-field="maptheme"]');
  1707. $control
  1708. .children( 'option[value="false"]' )
  1709. .prop( 'selected', true );
  1710. if ( $control.hasClass( 'select2-offscreen' ) ) {
  1711. $control.select2( 'val', 'false' );
  1712. }
  1713. }
  1714. },
  1715. // MARKERS FUNCTIONS
  1716. // -----------------------------------------------------------------------------
  1717. editMarker: function( marker ) {
  1718. this.currentMarker = marker;
  1719. this.marker.$form
  1720. .find( '#MarkerLocation' ).val( marker.location );
  1721. this.marker.$form
  1722. .find( '#MarkerTitle' ).val( marker.title );
  1723. this.marker.$form
  1724. .find( '#MarkerDescription' ).val( marker.description );
  1725. this.marker.$modal.modal( 'show' );
  1726. },
  1727. removeMarker: function( marker ) {
  1728. var i;
  1729. marker._instance.setMap( null );
  1730. marker._$html.remove();
  1731. for( i = 0; i < this.markers.length; i++ ) {
  1732. if ( marker === this.markers[ i ] ) {
  1733. this.markers.splice( i, 1 );
  1734. break;
  1735. }
  1736. }
  1737. if ( this.markers.length === 0 ) {
  1738. this.marker.$list.addClass( 'hidden' );
  1739. }
  1740. },
  1741. saveMarker: function( marker ) {
  1742. this._geocode( marker );
  1743. },
  1744. removeAllMarkers: function() {
  1745. var i = 0,
  1746. l,
  1747. marker;
  1748. l = this.markers.length;
  1749. for( ; i < l; i++ ) {
  1750. marker = this.markers[ i ];
  1751. marker._instance.setMap( null );
  1752. marker._$html.remove();
  1753. }
  1754. this.markers = [];
  1755. this.marker.$list.addClass( 'hidden' );
  1756. },
  1757. _geocode: function( marker ) {
  1758. var _self = this,
  1759. status;
  1760. this.geocoder.geocode({ address: marker.location }, function( response, status ) {
  1761. _self._onGeocodeResult( marker, response, status );
  1762. });
  1763. },
  1764. _onGeocodeResult: function( marker, response, status ) {
  1765. var result;
  1766. if ( !response || status !== google.maps.GeocoderStatus.OK ) {
  1767. if ( status == google.maps.GeocoderStatus.ZERO_RESULTS ) {
  1768. // show notification
  1769. } else {
  1770. timeouts++;
  1771. if ( timeouts > 3 ) {
  1772. // show notification reached limit of requests
  1773. }
  1774. }
  1775. } else {
  1776. timeouts = 0;
  1777. if ( this.currentMarker ) {
  1778. this.removeMarker( this.currentMarker );
  1779. this.currentMarker = null;
  1780. }
  1781. // grab first result of the list
  1782. result = response[ 0 ];
  1783. // get lat & lng and set to marker
  1784. marker.lat = Math.round( result.geometry.location.lat() * 1000000 ) / 1000000;
  1785. marker.lng = Math.round( result.geometry.location.lng() * 1000000 ) / 1000000;
  1786. var opts = {
  1787. position: new google.maps.LatLng( marker.lat, marker.lng ),
  1788. map: this.map
  1789. };
  1790. if ( marker.title.length > 0 ) {
  1791. opts.title = marker.title;
  1792. }
  1793. if ( marker.description.length > 0 ) {
  1794. opts.desc = marker.description;
  1795. }
  1796. marker.position = opts.position;
  1797. marker._instance = new google.maps.Marker( opts );
  1798. if ( !!marker.title || !!marker.description ) {
  1799. this._bindMarkerClick( marker );
  1800. }
  1801. this.markers.push( marker );
  1802. // append to markers list
  1803. this._appendMarkerToList( marker );
  1804. // hide modal and reset form
  1805. this.marker.$form.get(0).reset();
  1806. this.marker.$modal.modal( 'hide' );
  1807. }
  1808. },
  1809. _appendMarkerToList: function( marker ) {
  1810. var _self = this,
  1811. html;
  1812. html = [
  1813. '<li>',
  1814. '<p>{location}</p>',
  1815. '<a href="#" class="location-action location-center"><i class="fa fa-map-marker"></i></a>',
  1816. '<a href="#" class="location-action location-edit"><i class="fa fa-edit"></i></a>',
  1817. '<a href="#" class="location-action location-remove text-danger"><i class="fa fa-times"></i></a>',
  1818. '</li>'
  1819. ].join('');
  1820. html = html.replace( /\{location\}/, !!marker.title ? marker.title : marker.location );
  1821. marker._$html = $( html );
  1822. // events
  1823. marker._$html.find( '.location-center' )
  1824. .on( 'click', function( e ) {
  1825. _self.map.setCenter( marker.position );
  1826. });
  1827. marker._$html.find( '.location-remove' )
  1828. .on( 'click', function( e ) {
  1829. e.preventDefault();
  1830. _self.removeMarker( marker );
  1831. });
  1832. marker._$html.find( '.location-edit' )
  1833. .on( 'click', function( e ) {
  1834. e.preventDefault();
  1835. _self.editMarker( marker );
  1836. });
  1837. this.marker.$list
  1838. .append( marker._$html )
  1839. .removeClass( 'hidden' );
  1840. },
  1841. _bindMarkerClick: function( marker ) {
  1842. var _self = this,
  1843. html;
  1844. html = [
  1845. '<div style="background-color: #FFF; color: #000; padding: 5px; width: 150px;">',
  1846. '{title}',
  1847. '{description}',
  1848. '</div>'
  1849. ].join('');
  1850. html = html.replace(/\{title\}/, !!marker.title ? ("<h4>" + marker.title + "</h4>") : "" );
  1851. html = html.replace(/\{description\}/, !!marker.description ? ("<p>" + marker.description + "</p>") : "" );
  1852. marker._infoWindow = new google.maps.InfoWindow({ content: html });
  1853. google.maps.event.addListener( marker._instance, 'click', function() {
  1854. if ( marker._infoWindow.isOpened ) {
  1855. marker._infoWindow.close();
  1856. marker._infoWindow.isOpened = false;
  1857. } else {
  1858. marker._infoWindow.open( _self.map, this );
  1859. marker._infoWindow.isOpened = true;
  1860. }
  1861. });
  1862. },
  1863. preview: function() {
  1864. var customScript,
  1865. googleScript,
  1866. iframe,
  1867. previewHtml;
  1868. previewHtml = [
  1869. '<style>',
  1870. 'html, body { margin: 0; padding: 0; }',
  1871. '</style>',
  1872. '<div id="' + this.$wrapper.find('[data-builder-field="mapid"]').val() + '" style="width: 100%; height: 100%;"></div>'
  1873. ];
  1874. iframe = this.$previewModal.find( 'iframe' ).get(0).contentWindow.document;
  1875. iframe.body.innerHTML = previewHtml.join('');
  1876. customScript = iframe.createElement( 'script' );
  1877. customScript.type = 'text/javascript';
  1878. customScript.text = "window.initialize = function() { " + this.generate() + " init(); }; ";
  1879. iframe.body.appendChild( customScript );
  1880. googleScript = iframe.createElement( 'script' );
  1881. googleScript.type = 'text/javascript';
  1882. googleScript.text = 'function loadScript() { var script = document.createElement("script"); script.type = "text/javascript"; script.src = "http://maps.googleapis.com/maps/api/js?key=&sensor=&callback=initialize"; document.body.appendChild(script); } loadScript()';
  1883. iframe.body.appendChild( googleScript );
  1884. },
  1885. getCode: function() {
  1886. this.$getCodeModal.find('.modal-body pre').html( this.generate().replace( /</g, '&lt;' ).replace( />/g, '&gt;' ) );
  1887. },
  1888. // GENERATE CODE
  1889. // -----------------------------------------------------------------------------
  1890. generate: function() {
  1891. var i,
  1892. work;
  1893. var output = [
  1894. ' google.maps.event.addDomListener(window, "load", init);',
  1895. ' var map;',
  1896. ' function init() {',
  1897. ' var mapOptions = {',
  1898. ' center: new google.maps.LatLng({lat}, {lng}),',
  1899. ' zoom: {zoom},',
  1900. ' zoomControl: {zoomControl},',
  1901. ' {zoomControlOptions}',
  1902. ' disableDoubleClickZoom: {disableDoubleClickZoom},',
  1903. ' mapTypeControl: {mapTypeControl},',
  1904. ' {mapTypeControlOptions}',
  1905. ' scaleControl: {scaleControl},',
  1906. ' scrollwheel: {scrollwheel},',
  1907. ' panControl: {panControl},',
  1908. ' streetViewControl: {streetViewControl},',
  1909. ' draggable : {draggable},',
  1910. ' overviewMapControl: {overviewMapControl},',
  1911. ' {overviewMapControlOptions}',
  1912. ' mapTypeId: google.maps.MapTypeId.{mapTypeId}{styles}',
  1913. ' };',
  1914. '',
  1915. ' var mapElement = document.getElementById("{mapid}");',
  1916. ' var map = new google.maps.Map(mapElement, mapOptions);',
  1917. ' {locations}',
  1918. ' }'
  1919. ];
  1920. output = output.join("\r\n");
  1921. var zoomControl = this.$wrapper.find('[data-builder-field="zoomcontrol"] option:selected').val() !== 'false';
  1922. var mapTypeControl = this.$wrapper.find('[data-builder-field="maptypecontrol"] option:selected').val() !== 'false';
  1923. var overviewMapControl = this.$wrapper.find('[data-builder-field="overviewcontrol"] option:selected').val().toLowerCase();
  1924. var $themeControl = this.$wrapper.find('[data-builder-field="maptheme"] option:selected').filter( ':selected' );
  1925. output = output
  1926. .replace( /\{mapid\}/, this.$wrapper.find('[data-builder-field="mapid"]').val() )
  1927. .replace( /\{lat\}/, this.$wrapper.find('[data-builder-field][name="latitude"]').val() )
  1928. .replace( /\{lng\}/, this.$wrapper.find('[data-builder-field][name="longitude"]').val() )
  1929. .replace( /\{zoom\}/, this.$wrapper.find('[data-builder-field="zoomlevel"] option:selected').val() )
  1930. .replace( /\{zoomControl\}/, zoomControl )
  1931. .replace( /\{disableDoubleClickZoom\}/, this.$wrapper.find('[data-builder-field="clicktozoomcontrol"] option:selected').val() === 'false' )
  1932. .replace( /\{mapTypeControl\}/, mapTypeControl )
  1933. .replace( /\{scaleControl\}/, this.$wrapper.find('[data-builder-field="scalecontrol"] option:selected').val() !== 'false' )
  1934. .replace( /\{scrollwheel\}/, this.$wrapper.find('[data-builder-field="scrollwheelcontrol"] option:selected').val() !== 'false' )
  1935. .replace( /\{panControl\}/, this.$wrapper.find('[data-builder-field="pancontrol"] option:selected').val() !== 'false' )
  1936. .replace( /\{streetViewControl\}/, this.$wrapper.find('[data-builder-field="streetviewcontrol"] option:selected').val() !== 'false' )
  1937. .replace( /\{draggable\}/, this.$wrapper.find('[data-builder-field="draggablecontrol"] option:selected').val() !== 'false' )
  1938. .replace( /\{overviewMapControl\}/, overviewMapControl !== 'false' )
  1939. .replace( /\{mapTypeId\}/, this.$wrapper.find('[data-builder-field="maptype"] option:selected').val().toUpperCase() );
  1940. if ( zoomControl ) {
  1941. work = {
  1942. zoomControlOptions: {
  1943. style: this.$wrapper.find('[data-builder-field="maptypecontrol"] option:selected').val().toUpperCase()
  1944. }
  1945. };
  1946. output = output.replace( /\{zoomControlOptions\}/, "zoomControlOptions: {\r\n style: google.maps.ZoomControlStyle." + this.$wrapper.find('[data-builder-field="zoomcontrol"] option:selected').val().toUpperCase() + "\r\n\ },");
  1947. } else {
  1948. output = output.replace( /\{zoomControlOptions\}/, '' );
  1949. }
  1950. if ( mapTypeControl ) {
  1951. work = {
  1952. zoomControlOptions: {
  1953. style: this.$wrapper.find('[data-builder-field="maptypecontrol"] option:selected').val().toUpperCase()
  1954. }
  1955. };
  1956. output = output.replace( /\{mapTypeControlOptions\}/, "mapTypeControlOptions: {\r\n style: google.maps.MapTypeControlStyle." + this.$wrapper.find('[data-builder-field="maptypecontrol"] option:selected').val().toUpperCase() + "\r\n\ },");
  1957. } else {
  1958. output = output.replace( /\{mapTypeControlOptions\}/, '' );
  1959. }
  1960. if ( overviewMapControl !== 'false' ) {
  1961. output = output.replace( /\{overviewMapControlOptions\}/, "overviewMapControlOptions: {\r\n opened: " + (overviewMapControl === 'opened') + "\r\n\ },");
  1962. } else {
  1963. output = output.replace( /\{overviewMapControlOptions\}/, '' );
  1964. }
  1965. if ( $themeControl.val() !== 'false' ) {
  1966. output = output.replace( /\{styles\}/, ',\r\n styles: ' + $themeControl.data( 'json' ).replace(/\r\n/g, '') );
  1967. } else {
  1968. output = output.replace( /\{styles\}/, '' );
  1969. }
  1970. if ( this.markers.length > 0 ) {
  1971. var work = [ 'var locations = [' ];
  1972. var m,
  1973. object;
  1974. for( i = 0; i < this.markers.length; i++ ) {
  1975. m = this.markers[ i ];
  1976. object = '';
  1977. object += ' { lat: ' + m.lat + ', lng: ' + m.lng;
  1978. if ( !!m.title ) {
  1979. object += ', title: "' + m.title + '"';
  1980. }
  1981. if ( !!m.description ) {
  1982. object += ', description: "' + m.description + '"';
  1983. }
  1984. object += ' }';
  1985. if ( i + 1 < this.markers.length ) {
  1986. object += ',';
  1987. }
  1988. work.push( object );
  1989. }
  1990. work.push( ' ];\r\n' )
  1991. work.push( ' var opts = {};' )
  1992. work.push( ' for (var i = 0; i < locations.length; i++) {' );
  1993. work.push( ' opts.position = new google.maps.LatLng( locations[ i ].lat, locations[ i ].lng );' );
  1994. work.push( ' opts.map = map;' );
  1995. work.push( ' if ( !!locations[ i ] .title ) { opts.title = locations[ i ].title; }');
  1996. work.push( ' if ( !!locations[ i ] .description ) { opts.description = locations[ i ].description; }');
  1997. work.push( ' marker = new google.maps.Marker( opts );' );
  1998. work.push( '' );
  1999. work.push( ' (function() {' );
  2000. work.push( ' var html = [' );
  2001. work.push( ' \'<div style="background-color: #FFF; color: #000; padding: 5px; width: 150px;">\',' );
  2002. work.push( ' \'{title}\',' );
  2003. work.push( ' \'{description}\',' );
  2004. work.push( ' \'</div>\'' );
  2005. work.push( ' ].join(\'\');' );
  2006. work.push( '' );
  2007. work.push( ' html = html.replace(/\{title\}/, !!opts.title ? ("<h4>" + opts.title + "</h4>") : "" );' );
  2008. work.push( ' html = html.replace(/\{description\}/, !!opts.description ? ("<p>" + opts.description + "</p>") : "" );' );
  2009. work.push( ' var infoWindow = new google.maps.InfoWindow({ content: html });' );
  2010. work.push( ' google.maps.event.addListener( marker, \'click\', function() {' );
  2011. work.push( ' if ( infoWindow.isOpened ) {' );
  2012. work.push( ' infoWindow.close();' );
  2013. work.push( ' infoWindow.isOpened = false;' );
  2014. work.push( ' } else {' );
  2015. work.push( ' infoWindow.open( map, this );' );
  2016. work.push( ' infoWindow.isOpened = true;' );
  2017. work.push( ' }' );
  2018. work.push( ' });' );
  2019. work.push( ' })();' )
  2020. work.push( ' }');
  2021. output = output.replace( /\{locations\}/, work.join('\r\n') );
  2022. } else {
  2023. output = output.replace( /\{locations\}/, '' );
  2024. }
  2025. console.log( output );
  2026. return output;
  2027. }
  2028. };
  2029. // expose
  2030. $.extend( true, theme, {
  2031. Maps: {
  2032. GMapBuilder: GMapBuilder
  2033. }
  2034. });
  2035. // jQuery plugin
  2036. $.fn.themeGMapBuilder = function( opts ) {
  2037. return this.map(function() {
  2038. var $this = $( this ),
  2039. instance;
  2040. instance = $this.data( instanceName );
  2041. if ( instance ) {
  2042. return instance;
  2043. } else {
  2044. return (new GMapBuilder( $this, opts ));
  2045. }
  2046. });
  2047. };
  2048. // auto initialize
  2049. $(function() {
  2050. $('[data-theme-gmap-builder]').each(function() {
  2051. var $this = $( this );
  2052. window.builder = $this.themeGMapBuilder();
  2053. });
  2054. });
  2055. }).apply(this, [ window.theme, jQuery ]);
  2056. // Animate
  2057. (function(theme, $) {
  2058. theme = theme || {};
  2059. var instanceName = '__animate';
  2060. var PluginAnimate = function($el, opts) {
  2061. return this.initialize($el, opts);
  2062. };
  2063. PluginAnimate.defaults = {
  2064. accX: 0,
  2065. accY: -150,
  2066. delay: 1
  2067. };
  2068. PluginAnimate.prototype = {
  2069. initialize: function($el, opts) {
  2070. if ( $el.data( instanceName ) ) {
  2071. return this;
  2072. }
  2073. this.$el = $el;
  2074. this
  2075. .setData()
  2076. .setOptions(opts)
  2077. .build();
  2078. return this;
  2079. },
  2080. setData: function() {
  2081. this.$el.data(instanceName, this);
  2082. return this;
  2083. },
  2084. setOptions: function(opts) {
  2085. this.options = $.extend(true, {}, PluginAnimate.defaults, opts, {
  2086. wrapper: this.$el
  2087. });
  2088. return this;
  2089. },
  2090. build: function() {
  2091. var self = this,
  2092. $el = this.options.wrapper,
  2093. delay = 0;
  2094. $el.addClass('appear-animation');
  2095. if(!$('html').hasClass('no-csstransitions') && $(window).width() > 767) {
  2096. $el.appear(function() {
  2097. delay = ($el.attr('data-appear-animation-delay') ? $el.attr('data-appear-animation-delay') : self.options.delay);
  2098. if(delay > 1) {
  2099. $el.css('animation-delay', delay + 'ms');
  2100. }
  2101. $el.addClass($el.attr('data-appear-animation'));
  2102. setTimeout(function() {
  2103. $el.addClass('appear-animation-visible');
  2104. }, delay);
  2105. }, {accX: self.options.accX, accY: self.options.accY});
  2106. } else {
  2107. $el.addClass('appear-animation-visible');
  2108. }
  2109. return this;
  2110. }
  2111. };
  2112. // expose to scope
  2113. $.extend(theme, {
  2114. PluginAnimate: PluginAnimate
  2115. });
  2116. // jquery plugin
  2117. $.fn.themePluginAnimate = function(opts) {
  2118. return this.map(function() {
  2119. var $this = $(this);
  2120. if ($this.data(instanceName)) {
  2121. return $this.data(instanceName);
  2122. } else {
  2123. return new PluginAnimate($this, opts);
  2124. }
  2125. });
  2126. };
  2127. }).apply(this, [ window.theme, jQuery ]);
  2128. // Carousel
  2129. (function(theme, $) {
  2130. theme = theme || {};
  2131. var initialized = false;
  2132. var instanceName = '__carousel';
  2133. var PluginCarousel = function($el, opts) {
  2134. return this.initialize($el, opts);
  2135. };
  2136. PluginCarousel.defaults = {
  2137. itemsDesktop: false,
  2138. itemsDesktopSmall: false,
  2139. itemsTablet: false,
  2140. itemsTabletSmall: false,
  2141. itemsMobile: false
  2142. };
  2143. PluginCarousel.prototype = {
  2144. initialize: function($el, opts) {
  2145. if ( $el.data( instanceName ) ) {
  2146. return this;
  2147. }
  2148. this.$el = $el;
  2149. this
  2150. .setData()
  2151. .setOptions(opts)
  2152. .build();
  2153. return this;
  2154. },
  2155. setData: function() {
  2156. this.$el.data(instanceName, this);
  2157. return this;
  2158. },
  2159. setOptions: function(opts) {
  2160. this.options = $.extend(true, {}, PluginCarousel.defaults, opts, {
  2161. wrapper: this.$el
  2162. });
  2163. return this;
  2164. },
  2165. build: function() {
  2166. this.options.wrapper.owlCarousel(this.options).addClass("owl-carousel-init");
  2167. return this;
  2168. }
  2169. };
  2170. // expose to scope
  2171. $.extend(theme, {
  2172. PluginCarousel: PluginCarousel
  2173. });
  2174. // jquery plugin
  2175. $.fn.themePluginCarousel = function(opts) {
  2176. return this.map(function() {
  2177. var $this = $(this);
  2178. if ($this.data(instanceName)) {
  2179. return $this.data(instanceName);
  2180. } else {
  2181. return new PluginCarousel($this, opts);
  2182. }
  2183. });
  2184. }
  2185. }).apply(this, [ window.theme, jQuery ]);
  2186. // Chart Circular
  2187. (function(theme, $) {
  2188. theme = theme || {};
  2189. var instanceName = '__chartCircular';
  2190. var PluginChartCircular = function($el, opts) {
  2191. return this.initialize($el, opts);
  2192. };
  2193. PluginChartCircular.defaults = {
  2194. accX: 0,
  2195. accY: -150,
  2196. delay: 1,
  2197. barColor: '#0088CC',
  2198. trackColor: '#f2f2f2',
  2199. scaleColor: false,
  2200. scaleLength: 5,
  2201. lineCap: 'round',
  2202. lineWidth: 13,
  2203. size: 175,
  2204. rotate: 0,
  2205. animate: ({
  2206. duration: 2500,
  2207. enabled: true
  2208. })
  2209. };
  2210. PluginChartCircular.prototype = {
  2211. initialize: function($el, opts) {
  2212. if ( $el.data( instanceName ) ) {
  2213. return this;
  2214. }
  2215. this.$el = $el;
  2216. this
  2217. .setData()
  2218. .setOptions(opts)
  2219. .build();
  2220. return this;
  2221. },
  2222. setData: function() {
  2223. this.$el.data(instanceName, this);
  2224. return this;
  2225. },
  2226. setOptions: function(opts) {
  2227. this.options = $.extend(true, {}, PluginChartCircular.defaults, opts, {
  2228. wrapper: this.$el
  2229. });
  2230. return this;
  2231. },
  2232. build: function() {
  2233. var self = this,
  2234. $el = this.options.wrapper,
  2235. value = ($el.attr('data-percent') ? $el.attr('data-percent') : 0),
  2236. percentEl = $el.find('.percent'),
  2237. shouldAnimate,
  2238. data;
  2239. shouldAnimate = $.isFunction($.fn[ 'appear' ]) && ( typeof $.browser !== 'undefined' && !$.browser.mobile );
  2240. data = { accX: self.options.accX, accY: self.options.accY };
  2241. $.extend(true, self.options, {
  2242. onStep: function(from, to, currentValue) {
  2243. percentEl.html(parseInt(currentValue));
  2244. }
  2245. });
  2246. $el.attr('data-percent', (shouldAnimate ? 0 : value) );
  2247. $el.easyPieChart( this.options );
  2248. if ( shouldAnimate ) {
  2249. $el.appear(function() {
  2250. setTimeout(function() {
  2251. $el.data('easyPieChart').update(value);
  2252. $el.attr('data-percent', value);
  2253. }, self.options.delay);
  2254. }, data);
  2255. } else {
  2256. $el.data('easyPieChart').update(value);
  2257. $el.attr('data-percent', value);
  2258. }
  2259. return this;
  2260. }
  2261. };
  2262. // expose to scope
  2263. $.extend(true, theme, {
  2264. Chart: {
  2265. PluginChartCircular: PluginChartCircular
  2266. }
  2267. });
  2268. // jquery plugin
  2269. $.fn.themePluginChartCircular = function(opts) {
  2270. return this.map(function() {
  2271. var $this = $(this);
  2272. if ($this.data(instanceName)) {
  2273. return $this.data(instanceName);
  2274. } else {
  2275. return new PluginChartCircular($this, opts);
  2276. }
  2277. });
  2278. }
  2279. }).apply(this, [ window.theme, jQuery ]);
  2280. // Lightbox
  2281. (function(theme, $) {
  2282. theme = theme || {};
  2283. var instanceName = '__lightbox';
  2284. var PluginLightbox = function($el, opts) {
  2285. return this.initialize($el, opts);
  2286. };
  2287. PluginLightbox.defaults = {
  2288. tClose: 'Close (Esc)', // Alt text on close button
  2289. tLoading: 'Loading...', // Text that is displayed during loading. Can contain %curr% and %total% keys
  2290. gallery: {
  2291. tPrev: 'Previous (Left arrow key)', // Alt text on left arrow
  2292. tNext: 'Next (Right arrow key)', // Alt text on right arrow
  2293. tCounter: '%curr% of %total%' // Markup for "1 of 7" counter
  2294. },
  2295. image: {
  2296. tError: '<a href="%url%">The image</a> could not be loaded.' // Error message when image could not be loaded
  2297. },
  2298. ajax: {
  2299. tError: '<a href="%url%">The content</a> could not be loaded.' // Error message when ajax request failed
  2300. }
  2301. };
  2302. PluginLightbox.prototype = {
  2303. initialize: function($el, opts) {
  2304. if ( $el.data( instanceName ) ) {
  2305. return this;
  2306. }
  2307. this.$el = $el;
  2308. this
  2309. .setData()
  2310. .setOptions(opts)
  2311. .build();
  2312. return this;
  2313. },
  2314. setData: function() {
  2315. this.$el.data(instanceName, this);
  2316. return this;
  2317. },
  2318. setOptions: function(opts) {
  2319. this.options = $.extend(true, {}, PluginLightbox.defaults, opts, {
  2320. wrapper: this.$el
  2321. });
  2322. return this;
  2323. },
  2324. build: function() {
  2325. this.options.wrapper.magnificPopup(this.options);
  2326. return this;
  2327. }
  2328. };
  2329. // expose to scope
  2330. $.extend(theme, {
  2331. PluginLightbox: PluginLightbox
  2332. });
  2333. // jquery plugin
  2334. $.fn.themePluginLightbox = function(opts) {
  2335. return this.each(function() {
  2336. var $this = $(this);
  2337. if ($this.data(instanceName)) {
  2338. return $this.data(instanceName);
  2339. } else {
  2340. return new PluginLightbox($this, opts);
  2341. }
  2342. });
  2343. }
  2344. }).apply(this, [ window.theme, jQuery ]);
  2345. // Portlets
  2346. (function(theme, $) {
  2347. theme = theme || {};
  2348. var instanceName = '__portlet',
  2349. storageOrderKey = '__portletOrder',
  2350. storageStateKey = '__portletState';
  2351. var PluginPortlet = function($el, opts) {
  2352. return this.initialize($el, opts);
  2353. };
  2354. PluginPortlet.defaults = {
  2355. connectWith: '[data-plugin-portlet]',
  2356. items: '[data-portlet-item]',
  2357. handle: '.portlet-handler',
  2358. opacity: 0.7,
  2359. placeholder: 'portlet-placeholder',
  2360. cancel: 'portlet-cancel',
  2361. forcePlaceholderSize: true,
  2362. forceHelperSize: true,
  2363. tolerance: 'pointer',
  2364. helper: 'original',
  2365. revert: 200
  2366. };
  2367. PluginPortlet.prototype = {
  2368. initialize: function($el, opts) {
  2369. if ( $el.data( instanceName ) ) {
  2370. return this;
  2371. }
  2372. this.$el = $el;
  2373. this
  2374. .setData()
  2375. .setOptions(opts)
  2376. .build();
  2377. return this;
  2378. },
  2379. setData: function() {
  2380. this.$el.data(instanceName, this);
  2381. return this;
  2382. },
  2383. setOptions: function(opts) {
  2384. var _self = this;
  2385. this.options = $.extend(true, {}, PluginPortlet.defaults, opts, {
  2386. wrapper: this.$el,
  2387. update: _self.onUpdate,
  2388. create: _self.onLoad
  2389. });
  2390. return this;
  2391. },
  2392. onUpdate: function(event, ui) {
  2393. var key = storageOrderKey,
  2394. data = store.get(key),
  2395. $this = $(this),
  2396. porletId = $this.prop('id');
  2397. if (!data) {
  2398. data = {};
  2399. }
  2400. if (!!porletId) {
  2401. data[porletId] = $this.sortable('toArray');
  2402. store.set(key, data);
  2403. }
  2404. },
  2405. onLoad: function(event, ui) {
  2406. var key = storageOrderKey,
  2407. data = store.get(key),
  2408. $this = $(this),
  2409. porletId = $this.prop('id'),
  2410. portlet = $('#' + porletId);
  2411. if (!!data) {
  2412. var panels = data[porletId];
  2413. if (!!panels) {
  2414. $.each(panels, function(index, panelId) {
  2415. $('#' + panelId).appendTo(portlet);
  2416. });
  2417. }
  2418. }
  2419. },
  2420. saveState: function( panel ) {
  2421. var key = storageStateKey,
  2422. data = store.get(key),
  2423. panelId = panel.prop('id');
  2424. if (!data) {
  2425. data = {};
  2426. }
  2427. if (!panelId) {
  2428. return this;
  2429. }
  2430. var collapse = panel.find('.panel-actions').children('a.fa-caret-up, a.fa-caret-down'),
  2431. isCollapsed = !!collapse.hasClass('fa-caret-up'),
  2432. isRemoved = !panel.closest('body').get(0);
  2433. if (isRemoved) {
  2434. data[panelId] = 'removed';
  2435. } else if (isCollapsed) {
  2436. data[panelId] = 'collapsed';
  2437. } else {
  2438. delete data[panelId];
  2439. }
  2440. store.set(key, data);
  2441. return this;
  2442. },
  2443. loadState: function() {
  2444. var key = storageStateKey,
  2445. data = store.get(key);
  2446. if (!!data) {
  2447. $.each(data, function(panelId, state) {
  2448. var panel = $('#' + panelId);
  2449. if (!panel.data('portlet-state-loaded')) {
  2450. if (state == 'collapsed') {
  2451. panel.find('.panel-actions a.fa-caret-down').trigger('click');
  2452. } else if (state == 'removed') {
  2453. panel.find('.panel-actions a.fa-times').trigger('click');
  2454. }
  2455. panel.data('portlet-state-loaded', true);
  2456. }
  2457. });
  2458. }
  2459. return this;
  2460. },
  2461. build: function() {
  2462. var _self = this;
  2463. if ( $.isFunction( $.fn.sortable ) ) {
  2464. this.$el.sortable( this.options );
  2465. this.$el.find('[data-portlet-item]').each(function() {
  2466. _self.events( $(this) );
  2467. });
  2468. }
  2469. var portlet = this.$el;
  2470. portlet.css('min-height', 150);
  2471. return this;
  2472. },
  2473. events: function($el) {
  2474. var _self = this,
  2475. portlet = $el.closest('[data-plugin-portlet]');
  2476. this.loadState();
  2477. $el.find('.panel-actions').on( 'click', 'a.fa-caret-up, a.fa-caret-down, a.fa-times', function( e ) {
  2478. setTimeout(function() {
  2479. _self.saveState( $el );
  2480. }, 250);
  2481. });
  2482. return this;
  2483. }
  2484. };
  2485. // expose to scope
  2486. $.extend(theme, {
  2487. PluginPortlet: PluginPortlet
  2488. });
  2489. // jquery plugin
  2490. $.fn.themePluginPortlet = function(opts) {
  2491. return this.map(function() {
  2492. var $this = $(this);
  2493. if ($this.data(instanceName)) {
  2494. return $this.data(instanceName);
  2495. } else {
  2496. return new PluginPortlet($this, opts);
  2497. }
  2498. });
  2499. }
  2500. }).apply(this, [ window.theme, jQuery ]);
  2501. // Slider
  2502. (function(theme, $) {
  2503. theme = theme || {};
  2504. var instanceName = '__slider';
  2505. var PluginSlider = function($el, opts) {
  2506. return this.initialize($el, opts);
  2507. };
  2508. PluginSlider.defaults = {
  2509. };
  2510. PluginSlider.prototype = {
  2511. initialize: function($el, opts) {
  2512. if ( $el.data( instanceName ) ) {
  2513. return this;
  2514. }
  2515. this.$el = $el;
  2516. this
  2517. .setVars()
  2518. .setData()
  2519. .setOptions(opts)
  2520. .build();
  2521. return this;
  2522. },
  2523. setVars: function() {
  2524. var $output = $( this.$el.data('plugin-slider-output') );
  2525. this.$output = $output.get(0) ? $output : null;
  2526. return this;
  2527. },
  2528. setData: function() {
  2529. this.$el.data(instanceName, this);
  2530. return this;
  2531. },
  2532. setOptions: function(opts) {
  2533. var _self = this;
  2534. this.options = $.extend( true, {}, PluginSlider.defaults, opts );
  2535. if ( this.$output ) {
  2536. $.extend( this.options, {
  2537. slide: function( event, ui ) {
  2538. _self.onSlide( event, ui );
  2539. }
  2540. });
  2541. }
  2542. return this;
  2543. },
  2544. build: function() {
  2545. this.$el.slider( this.options );
  2546. return this;
  2547. },
  2548. onSlide: function( event, ui ) {
  2549. if ( !ui.values ) {
  2550. this.$output.val( ui.value );
  2551. } else {
  2552. this.$output.val( ui.values[ 0 ] + '/' + ui.values[ 1 ] );
  2553. }
  2554. this.$output.trigger('change');
  2555. }
  2556. };
  2557. // expose to scope
  2558. $.extend(theme, {
  2559. PluginSlider: PluginSlider
  2560. });
  2561. // jquery plugin
  2562. $.fn.themePluginSlider = function(opts) {
  2563. return this.each(function() {
  2564. var $this = $(this);
  2565. if ($this.data(instanceName)) {
  2566. return $this.data(instanceName);
  2567. } else {
  2568. return new PluginSlider($this, opts);
  2569. }
  2570. });
  2571. }
  2572. }).apply(this, [ window.theme, jQuery ]);
  2573. // Toggle
  2574. (function(theme, $) {
  2575. theme = theme || {};
  2576. var instanceName = '__toggle';
  2577. var PluginToggle = function($el, opts) {
  2578. return this.initialize($el, opts);
  2579. };
  2580. PluginToggle.defaults = {
  2581. duration: 350,
  2582. isAccordion: false,
  2583. addIcons: true
  2584. };
  2585. PluginToggle.prototype = {
  2586. initialize: function($el, opts) {
  2587. if ( $el.data( instanceName ) ) {
  2588. return this;
  2589. }
  2590. this.$el = $el;
  2591. this
  2592. .setData()
  2593. .setOptions(opts)
  2594. .build();
  2595. return this;
  2596. },
  2597. setData: function() {
  2598. this.$el.data(instanceName, this);
  2599. return this;
  2600. },
  2601. setOptions: function(opts) {
  2602. this.options = $.extend(true, {}, PluginToggle.defaults, opts, {
  2603. wrapper: this.$el
  2604. });
  2605. return this;
  2606. },
  2607. build: function() {
  2608. var self = this,
  2609. $wrapper = this.options.wrapper,
  2610. $items = $wrapper.find('.toggle'),
  2611. $el = null;
  2612. $items.each(function() {
  2613. $el = $(this);
  2614. if(self.options.addIcons) {
  2615. $el.find('> label').prepend(
  2616. $('<i />').addClass('fa fa-plus'),
  2617. $('<i />').addClass('fa fa-minus')
  2618. );
  2619. }
  2620. if($el.hasClass('active')) {
  2621. $el.find('> p').addClass('preview-active');
  2622. $el.find('> .toggle-content').slideDown(self.options.duration);
  2623. }
  2624. self.events($el);
  2625. });
  2626. if(self.options.isAccordion) {
  2627. self.options.duration = self.options.duration/2;
  2628. }
  2629. return this;
  2630. },
  2631. events: function($el) {
  2632. var self = this,
  2633. previewParCurrentHeight = 0,
  2634. previewParAnimateHeight = 0,
  2635. toggleContent = null;
  2636. $el.find('> label').click(function(e) {
  2637. var $this = $(this),
  2638. parentSection = $this.parent(),
  2639. parentWrapper = $this.parents('.toggle'),
  2640. previewPar = null,
  2641. closeElement = null;
  2642. if(self.options.isAccordion && typeof(e.originalEvent) != 'undefined') {
  2643. closeElement = parentWrapper.find('.toggle.active > label');
  2644. if(closeElement[0] == $this[0]) {
  2645. return;
  2646. }
  2647. }
  2648. parentSection.toggleClass('active');
  2649. // Preview Paragraph
  2650. if(parentSection.find('> p').get(0)) {
  2651. previewPar = parentSection.find('> p');
  2652. previewParCurrentHeight = previewPar.css('height');
  2653. previewPar.css('height', 'auto');
  2654. previewParAnimateHeight = previewPar.css('height');
  2655. previewPar.css('height', previewParCurrentHeight);
  2656. }
  2657. // Content
  2658. toggleContent = parentSection.find('> .toggle-content');
  2659. if(parentSection.hasClass('active')) {
  2660. $(previewPar).animate({
  2661. height: previewParAnimateHeight
  2662. }, self.options.duration, function() {
  2663. $(this).addClass('preview-active');
  2664. });
  2665. toggleContent.slideDown(self.options.duration, function() {
  2666. if(closeElement) {
  2667. closeElement.trigger('click');
  2668. }
  2669. });
  2670. } else {
  2671. $(previewPar).animate({
  2672. height: 0
  2673. }, self.options.duration, function() {
  2674. $(this).removeClass('preview-active');
  2675. });
  2676. toggleContent.slideUp(self.options.duration);
  2677. }
  2678. });
  2679. }
  2680. };
  2681. // expose to scope
  2682. $.extend(theme, {
  2683. PluginToggle: PluginToggle
  2684. });
  2685. // jquery plugin
  2686. $.fn.themePluginToggle = function(opts) {
  2687. return this.map(function() {
  2688. var $this = $(this);
  2689. if ($this.data(instanceName)) {
  2690. return $this.data(instanceName);
  2691. } else {
  2692. return new PluginToggle($this, opts);
  2693. }
  2694. });
  2695. }
  2696. }).apply(this, [ window.theme, jQuery ]);
  2697. // Widget - Todo
  2698. (function(theme, $) {
  2699. theme = theme || {};
  2700. var instanceName = '__widgetTodoList';
  2701. var WidgetTodoList = function($el, opts) {
  2702. return this.initialize($el, opts);
  2703. };
  2704. WidgetTodoList.defaults = {
  2705. };
  2706. WidgetTodoList.prototype = {
  2707. initialize: function($el, opts) {
  2708. if ( $el.data( instanceName ) ) {
  2709. return this;
  2710. }
  2711. this.$el = $el;
  2712. this
  2713. .setData()
  2714. .setOptions(opts)
  2715. .build()
  2716. .events();
  2717. return this;
  2718. },
  2719. setData: function() {
  2720. this.$el.data(instanceName, this);
  2721. return this;
  2722. },
  2723. setOptions: function(opts) {
  2724. this.options = $.extend( true, {}, WidgetTodoList.defaults, opts );
  2725. return this;
  2726. },
  2727. check: function( input, label ) {
  2728. if ( input.is(':checked') ) {
  2729. label.addClass('line-through');
  2730. } else {
  2731. label.removeClass('line-through');
  2732. }
  2733. },
  2734. build: function() {
  2735. var _self = this,
  2736. $check = this.$el.find('.todo-check');
  2737. $check.each(function () {
  2738. var label = $(this).closest('li').find('.todo-label');
  2739. _self.check( $(this), label );
  2740. });
  2741. return this;
  2742. },
  2743. events: function() {
  2744. var _self = this,
  2745. $remove = this.$el.find( '.todo-remove' ),
  2746. $check = this.$el.find('.todo-check'),
  2747. $window = $( window );
  2748. $remove.on('click.widget-todo-list', function( ev ) {
  2749. ev.preventDefault();
  2750. $(this).closest("li").remove();
  2751. });
  2752. $check.on('change', function () {
  2753. var label = $(this).closest('li').find('.todo-label');
  2754. _self.check( $(this), label );
  2755. });
  2756. if ( $.isFunction( $.fn.sortable ) ) {
  2757. this.$el.sortable({
  2758. sort: function(event, ui) {
  2759. var top = event.pageY - _self.$el.offset().top - (ui.helper.outerHeight(true) / 2);
  2760. ui.helper.css({'top' : top + 'px'});
  2761. }
  2762. });
  2763. }
  2764. return this;
  2765. }
  2766. };
  2767. // expose to scope
  2768. $.extend(theme, {
  2769. WidgetTodoList: WidgetTodoList
  2770. });
  2771. // jquery plugin
  2772. $.fn.themePluginWidgetTodoList = function(opts) {
  2773. return this.each(function() {
  2774. var $this = $(this);
  2775. if ($this.data(instanceName)) {
  2776. return $this.data(instanceName);
  2777. } else {
  2778. return new WidgetTodoList($this, opts);
  2779. }
  2780. });
  2781. }
  2782. }).apply(this, [ window.theme, jQuery ]);
  2783. // Widget - Toggle
  2784. (function(theme, $) {
  2785. theme = theme || {};
  2786. var instanceName = '__widgetToggleExpand';
  2787. var WidgetToggleExpand = function($el, opts) {
  2788. return this.initialize($el, opts);
  2789. };
  2790. WidgetToggleExpand.defaults = {
  2791. };
  2792. WidgetToggleExpand.prototype = {
  2793. initialize: function($el, opts) {
  2794. if ( $el.data( instanceName ) ) {
  2795. return this;
  2796. }
  2797. this.$el = $el;
  2798. this
  2799. .setData()
  2800. .setOptions(opts)
  2801. .build()
  2802. .events();
  2803. return this;
  2804. },
  2805. setData: function() {
  2806. this.$el.data(instanceName, this);
  2807. return this;
  2808. },
  2809. setOptions: function(opts) {
  2810. this.options = $.extend( true, {}, WidgetToggleExpand.defaults, opts );
  2811. return this;
  2812. },
  2813. build: function() {
  2814. return this;
  2815. },
  2816. events: function() {
  2817. var _self = this,
  2818. $toggler = this.$el.find( '.widget-toggle' );
  2819. $toggler.on('click.widget-toggler', function() {
  2820. _self.$el.hasClass('widget-collapsed') ? _self.expand( _self.$el ) : _self.collapse( _self.$el );
  2821. });
  2822. return this;
  2823. },
  2824. expand: function( content ) {
  2825. content.children( '.widget-content-expanded' ).slideDown( 'fast', function() {
  2826. $(this).css( 'display', '' );
  2827. content.removeClass( 'widget-collapsed' );
  2828. });
  2829. },
  2830. collapse: function( content ) {
  2831. content.children('.widget-content-expanded' ).slideUp( 'fast', function() {
  2832. content.addClass( 'widget-collapsed' );
  2833. $(this).css( 'display', '' );
  2834. });
  2835. }
  2836. };
  2837. // expose to scope
  2838. $.extend(theme, {
  2839. WidgetToggleExpand: WidgetToggleExpand
  2840. });
  2841. // jquery plugin
  2842. $.fn.themePluginWidgetToggleExpand = function(opts) {
  2843. return this.each(function() {
  2844. var $this = $(this);
  2845. if ($this.data(instanceName)) {
  2846. return $this.data(instanceName);
  2847. } else {
  2848. return new WidgetToggleExpand($this, opts);
  2849. }
  2850. });
  2851. }
  2852. }).apply(this, [ window.theme, jQuery ]);
  2853. // Word Rotate
  2854. (function(theme, $) {
  2855. theme = theme || {};
  2856. var instanceName = '__wordRotate';
  2857. var PluginWordRotate = function($el, opts) {
  2858. return this.initialize($el, opts);
  2859. };
  2860. PluginWordRotate.defaults = {
  2861. delay: 2000
  2862. };
  2863. PluginWordRotate.prototype = {
  2864. initialize: function($el, opts) {
  2865. if ( $el.data( instanceName ) ) {
  2866. return this;
  2867. }
  2868. this.$el = $el;
  2869. this
  2870. .setData()
  2871. .setOptions(opts)
  2872. .build();
  2873. return this;
  2874. },
  2875. setData: function() {
  2876. this.$el.data(instanceName, this);
  2877. return this;
  2878. },
  2879. setOptions: function(opts) {
  2880. this.options = $.extend(true, {}, PluginWordRotate.defaults, opts, {
  2881. wrapper: this.$el
  2882. });
  2883. return this;
  2884. },
  2885. build: function() {
  2886. var $el = this.options.wrapper,
  2887. itemsWrapper = $el.find(".word-rotate-items"),
  2888. items = itemsWrapper.find("> span"),
  2889. firstItem = items.eq(0),
  2890. firstItemClone = firstItem.clone(),
  2891. itemHeight = firstItem.height(),
  2892. currentItem = 1,
  2893. currentTop = 0;
  2894. itemsWrapper.append(firstItemClone);
  2895. $el
  2896. .height(itemHeight)
  2897. .addClass("active");
  2898. setInterval(function() {
  2899. currentTop = (currentItem * itemHeight);
  2900. itemsWrapper.animate({
  2901. top: -(currentTop) + "px"
  2902. }, 300, function() {
  2903. currentItem++;
  2904. if(currentItem > items.length) {
  2905. itemsWrapper.css("top", 0);
  2906. currentItem = 1;
  2907. }
  2908. });
  2909. }, this.options.delay);
  2910. return this;
  2911. }
  2912. };
  2913. // expose to scope
  2914. $.extend(theme, {
  2915. PluginWordRotate: PluginWordRotate
  2916. });
  2917. // jquery plugin
  2918. $.fn.themePluginWordRotate = function(opts) {
  2919. return this.each(function() {
  2920. var $this = $(this);
  2921. if ($this.data(instanceName)) {
  2922. return $this.data(instanceName);
  2923. } else {
  2924. return new PluginWordRotate($this, opts);
  2925. }
  2926. });
  2927. }
  2928. }).apply(this, [ window.theme, jQuery ]);
  2929. // Data Tables - Config
  2930. (function($) {
  2931. 'use strict';
  2932. // we overwrite initialize of all datatables here
  2933. // because we want to use select2, give search input a bootstrap look
  2934. // keep in mind if you overwrite this fnInitComplete somewhere,
  2935. // you should run the code inside this function to keep functionality.
  2936. //
  2937. // there's no better way to do this at this time :(
  2938. if ( $.isFunction( $.fn[ 'dataTable' ] ) ) {
  2939. $.extend(true, $.fn.dataTable.defaults, {
  2940. sDom: "<'row datatables-header form-inline'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>r><'table-responsive't><'row datatables-footer'<'col-sm-12 col-md-6'i><'col-sm-12 col-md-6'p>>",
  2941. oLanguage: {
  2942. sLengthMenu: '_MENU_ records per page',
  2943. sProcessing: '<i class="fa fa-spinner fa-spin"></i> Loading'
  2944. },
  2945. fnInitComplete: function( settings, json ) {
  2946. // select 2
  2947. if ( $.isFunction( $.fn[ 'select2' ] ) ) {
  2948. $('.dataTables_length select', settings.nTableWrapper).select2({
  2949. minimumResultsForSearch: -1
  2950. });
  2951. }
  2952. var options = $( 'table', settings.nTableWrapper ).data( 'plugin-options' ) || {};
  2953. // search
  2954. var $search = $('.dataTables_filter input', settings.nTableWrapper);
  2955. $search
  2956. .attr({
  2957. placeholder: typeof options.searchPlaceholder !== 'undefined' ? options.searchPlaceholder : 'Search'
  2958. })
  2959. .addClass('form-control');
  2960. if ( $.isFunction( $.fn.placeholder ) ) {
  2961. $search.placeholder();
  2962. }
  2963. }
  2964. });
  2965. }
  2966. }).apply( this, [ jQuery ]);
  2967. // Notifications - Config
  2968. (function($) {
  2969. 'use strict';
  2970. // use font awesome icons if available
  2971. if ( typeof PNotify != 'undefined' ) {
  2972. PNotify.prototype.options.styling = "fontawesome";
  2973. $.extend(true, PNotify.prototype.options, {
  2974. shadow: false,
  2975. stack: {
  2976. spacing1: 15,
  2977. spacing2: 15
  2978. }
  2979. });
  2980. $.extend(PNotify.styling.fontawesome, {
  2981. // classes
  2982. container: "notification",
  2983. notice: "notification-warning",
  2984. info: "notification-info",
  2985. success: "notification-success",
  2986. error: "notification-danger",
  2987. // icons
  2988. notice_icon: "fa fa-exclamation",
  2989. info_icon: "fa fa-info",
  2990. success_icon: "fa fa-check",
  2991. error_icon: "fa fa-times"
  2992. });
  2993. }
  2994. }).apply(this, [jQuery]);