j1-template 2021.1.5 → 2021.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/assets/data/themes.json +6 -6
  3. data/assets/themes/j1/adapter/js/cookieConsent.js +54 -28
  4. data/assets/themes/j1/adapter/js/j1.js +119 -150
  5. data/assets/themes/j1/adapter/js/themer.js +37 -29
  6. data/assets/themes/j1/adapter/js/toccer.js +4 -45
  7. data/assets/themes/j1/modules/cookieConsent/js/cookieConsent.js +286 -286
  8. data/assets/themes/j1/modules/cookieConsent/js/cookieConsent.min.js +3 -3
  9. data/assets/themes/j1/modules/fam/css/{uno → theme/uno}/fam.css +0 -0
  10. data/assets/themes/j1/modules/fam/css/theme/uno/fam.min.css +15 -0
  11. data/assets/themes/j1/modules/fam/js/fam.js +1 -6
  12. data/assets/themes/j1/modules/mmenuLight/css/{mmenu.css → mmenu-light.css} +0 -0
  13. data/assets/themes/j1/modules/mmenuLight/css/{mmenu.min.css → mmenu-light.min.css} +0 -0
  14. data/assets/themes/j1/modules/mmenuLight/css/theme/{uno.css → uno/mmenu.css} +0 -0
  15. data/assets/themes/j1/modules/mmenuLight/css/theme/{uno.min.css → uno/mmenu.min.css} +0 -0
  16. data/assets/themes/j1/modules/rtable/css/theme/{uno.css → uno/rtable.css} +0 -0
  17. data/assets/themes/j1/modules/rtable/css/theme/{uno.min.css → uno/rtable.min.css} +0 -0
  18. data/assets/themes/j1/modules/themeSwitcher/js/switcher.js +33 -47
  19. data/assets/themes/j1/modules/themeSwitcher/js/switcher.min.js +410 -2
  20. data/lib/j1/version.rb +1 -1
  21. data/lib/j1_app/j1_auth_manager/auth_manager.rb +2 -3
  22. data/lib/starter_web/Gemfile +1 -1
  23. data/lib/starter_web/_config.yml +1 -1
  24. data/lib/starter_web/_data/j1_config.yml +20 -17
  25. data/lib/starter_web/_data/modules/defaults/themer.yml +2 -1
  26. data/lib/starter_web/_data/private.default.yml +119 -0
  27. data/lib/starter_web/_data/resources.yml +6 -7
  28. data/lib/starter_web/_includes/attributes.asciidoc +1 -1
  29. data/lib/starter_web/_plugins/lunr_index.rb +1 -1
  30. data/lib/starter_web/dot.gitignore +1 -1
  31. data/lib/starter_web/package.json +1 -1
  32. data/lib/starter_web/pages/public/blog/navigator/archive.html +3 -2
  33. data/lib/starter_web/pages/public/blog/navigator/archive/categoryview.html +3 -2
  34. data/lib/starter_web/pages/public/blog/navigator/archive/dateview.html +3 -2
  35. data/lib/starter_web/pages/public/blog/navigator/archive/tagview.html +3 -2
  36. data/lib/starter_web/utilsrv/_defaults/package.json +1 -1
  37. data/lib/starter_web/utilsrv/package.json +1 -1
  38. metadata +11 -9
@@ -19,10 +19,10 @@
19
19
  #
20
20
  # -----------------------------------------------------------------------------
21
21
  # NOTE:
22
- # BS Cookie Consent is an MODIFIED version of bootstrap-cookie-banner
23
- # for the use with J1 Template. This modiefied version cannot be used
22
+ # BS Cookie Consent is a MODIFIED version of bootstrap-cookie-banner
23
+ # for the use with J1 Template. This modified version cannot be used
24
24
  # outside of J1 Template!
25
- # -----------------------------------------------------------------------------
25
+ # -----------------------------------------------------------------------------
26
26
  */
27
27
 
28
28
  "use strict";function BootstrapCookieConsent(c){var g;var e;var q;var r=log4javascript.getLogger("j1.core.bsCookieConsent");var p="bccs-modal";var l=this;var n=false;this.props={autoShowDialog:true,language:navigator.language,languages:["en","de"],contentURL:"./content",cookieName:"cookie-consent-settings",cookieStorageDays:365,postSelectionCallback:undefined,whitelisted:[],xhr_data_element:""};for(var d in c){this.props[d]=c[d]}this.language=this.props.language;if(this.language.indexOf("-")!==-1){this.language=this.language.split("-")[0]}if(!this.props.languages.includes(this.language)){this.language=this.props.languages[0]}var f={set:function(u,v,x){var w=window.btoa(v);var s="";if(x){var t=new Date();t.setTime(t.getTime()+(x*24*60*60*1000));s="; expires="+t.toUTCString()}document.cookie=u+"="+(w||"")+s+"; Path=/; SameSite=Strict;"},get:function(t){var w=t+"=";var s=document.cookie.split(";");for(var u=0;u<s.length;u++){var y=s[u];while(y.charAt(0)===" "){y=y.substring(1,y.length)}if(y.indexOf(w)===0){var x=y.substring(w.length,y.length);var v=window.atob(x);return v}}return undefined}};var k={documentReady:function(s){if(document.readyState!=="loading"){s()}else{document.addEventListener("DOMContentLoaded",s)}}};function j(s){k.documentReady(function(){l.modal=document.getElementById(p);if(!l.modal){l.modal=document.createElement("div");l.modal.id=p;l.modal.setAttribute("class","modal fade");l.modal.setAttribute("tabindex","-1");l.modal.setAttribute("role","dialog");l.modal.setAttribute("aria-labelledby",p);document.body.append(l.modal);l.$modal=$(l.modal);if(l.props.postSelectionCallback){l.$modal.on("hidden.bs.modal",function(){l.props.postSelectionCallback()})}var t=l.props.contentURL+"/index.html";$.get(t).done(function(u){l.modal.innerHTML=u;l.modal.innerHTML=$("#"+l.props.xhr_data_element).eq(0).html();$(l.modal).modal({backdrop:"static",keyboard:false});l.$buttonDoNotAgree=$("#bccs-buttonDoNotAgree");l.$buttonAgree=$("#bccs-buttonAgree");l.$buttonSave=$("#bccs-buttonSave");l.$buttonAgreeAll=$("#bccs-buttonAgreeAll");i();h();$("#bccs-options").on("hide.bs.collapse",function(){n=false;i()}).on("show.bs.collapse",function(){n=true;i()});l.$buttonDoNotAgree.click(function(){b()});l.$buttonAgree.click(function(){m()});l.$buttonSave.click(function(){$("#bccs-options").collapse("hide");o();h()});l.$buttonAgreeAll.click(function(){$("#bccs-options").collapse("hide");m();h()})}).fail(function(){r.error("You probably need to set `contentURL` in the props")})}else{l.$modal.modal("show")}}.bind(this))}function h(){var u=l.getSettings();if(u){for(var t in u){var s=l.$modal.find("#bccs-options .bccs-option[data-name='"+t+"'] input[type='checkbox']");s.prop("checked",u[t])}}}function i(){if(n){l.$buttonDoNotAgree.hide();l.$buttonAgree.hide();l.$buttonSave.show();l.$buttonAgreeAll.show()}else{l.$buttonDoNotAgree.show();l.$buttonAgree.show();l.$buttonSave.hide();l.$buttonAgreeAll.hide()}}function a(t){var s=l.$modal.find("#bccs-options .bccs-option");var v={};for(var w=0;w<s.length;w++){var y=s[w];var u=y.getAttribute("data-name");if(u==="necessary"){v[u]=true}else{if(t===undefined){var x=$(y).find("input[type='checkbox']");v[u]=x.prop("checked")}else{v[u]=!!t}}}return v}function m(){f.set(l.props.cookieName,JSON.stringify(a(true)),l.props.cookieStorageDays);l.$modal.modal("hide")}function b(){f.set(l.props.cookieName,JSON.stringify(a(false)),l.props.cookieStorageDays);r.warn("delete cookie: j1.user.consent");j1.deleteCookie("all");l.$modal.modal("hide");j1.goHome()}function o(){f.set(l.props.cookieName,JSON.stringify(a()),l.props.cookieStorageDays);l.$modal.modal("hide")}q=(this.props.whitelisted.indexOf(window.location.pathname)>-1);if(f.get(this.props.cookieName)===undefined&&this.props.autoShowDialog&&!q){j()}this.showDialog=function(){q=(this.props.whitelisted.indexOf(window.location.pathname)>-1);if(!q){j()}};this.getSettings=function(t){var s=f.get(l.props.cookieName);if(s){var u=JSON.parse(f.get(l.props.cookieName));if(t===undefined){return u}else{if(u){return u[t]}else{return false}}}else{return undefined}}};
@@ -0,0 +1,15 @@
1
+ /*
2
+ # -----------------------------------------------------------------------------
3
+ # ~/assets/themes/j1/modules/fam/css/fam.min.css
4
+ # Provides styles for J1 Module FAM (Floating Button Menu)
5
+ #
6
+ # Product/Info:
7
+ # https://jekyll.one
8
+ #
9
+ # Copyright (C) 2021 Juergen Adams
10
+ #
11
+ # J1 Template is licensed under the MIT License.
12
+ # See: https://github.com/jekyll-one-org/J1 Template/blob/master/LICENSE
13
+ # -----------------------------------------------------------------------------
14
+ */
15
+ .fam-btn ul{left:0;right:0;text-align:center;position:absolute;bottom:64px;margin:0;visibility:hidden;padding-left:0;list-style-type:none}.btn-large,.btn-small{border:0;border-radius:2px;display:inline-block;height:36px;line-height:36px;padding:0 16px;text-transform:uppercase;vertical-align:middle;-webkit-tap-highlight-color:transparent}.disabled.btn-large,.disabled.btn-small,.btn-fab-floating.disabled,.btn-large.disabled,.btn-small.disabled,.btn-large:disabled,.btn-small:disabled,.btn-fab-floating:disabled,.btn-large:disabled,.btn-small:disabled,[disabled].btn-large,[disabled].btn-small,.btn-fab-floating[disabled],.btn-large[disabled],.btn-small[disabled]{pointer-events:none;background-color:#dfdfdf!important;-webkit-box-shadow:none;box-shadow:none;color:#9f9f9f!important;cursor:default}.disabled.btn-large:hover,.disabled.btn-small:hover,.btn-fab-floating.disabled:hover,.btn-large.disabled:hover,.btn-small.disabled:hover,.btn-large:disabled:hover,.btn-small:disabled:hover,.btn-fab-floating:disabled:hover,.btn-large:disabled:hover,.btn-small:disabled:hover,[disabled].btn-large:hover,[disabled].btn-small:hover,.btn-fab-floating[disabled]:hover,.btn-large[disabled]:hover,.btn-small[disabled]:hover{background-color:#dfdfdf!important;color:#9f9f9f!important}.btn-large,.btn-small,.btn-fab-floating{font-size:14px;outline:0}.btn-large i,.btn-small i,.btn-fab-floating i{font-size:1.3rem;line-height:inherit}.btn-large:focus,.btn-small:focus,.btn-fab-floating:focus{background-color:#1d7d74}.btn-large,.btn-small{text-decoration:none;color:#fff;background-color:#26a69a;text-align:center;letter-spacing:.5px;-webkit-transition:background-color .2s ease-out;transition:background-color .2s ease-out;cursor:pointer}.btn-large:hover,.btn-small:hover{background-color:#424242!important}.btn-fab-floating:hover{background-color:#424242!important}.btn-fab-floating{display:inline-block;color:#fff;position:relative;overflow:hidden;z-index:1;width:40px;height:40px;line-height:40px;padding:0;background-color:#26a69a;border-radius:50%;-webkit-transition:background-color .3s;transition:background-color .3s;cursor:pointer;vertical-align:middle}.btn-fab-floating:before{border-radius:0}.btn-fab-floating.btn-large{width:56px;height:56px;padding:0}.btn-fab-floating.btn-large.halfway-fab{bottom:-28px}.btn-fab-floating.btn-large i{line-height:56px}.btn-fab-floating.btn-small{width:32.4px;height:32.4px}.btn-fab-floating.btn-small.halfway-fab{bottom:-16.2px}.btn-fab-floating.btn-small i{line-height:32.4px}.btn-fab-floating.halfway-fab{position:absolute;right:24px;bottom:-20px}.btn-fab-floating.halfway-fab.left{right:auto;left:24px}.btn-fab-floating i{width:inherit;display:inline-block;text-align:center;color:#fff;font-size:1.6rem;line-height:40px}button.btn-fab-floating{border:0}.fam-btn{position:fixed;right:1rem;bottom:1rem;padding-top:4rem;margin-bottom:0;z-index:9}.fam-btn.active ul{visibility:visible}.fam-btn.direction-left,.fam-btn.direction-right{padding:0 0 0 15px}.fam-btn.direction-left ul,.fam-btn.direction-right ul{text-align:right;right:64px;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);height:100%;left:auto;width:500px}.fam-btn.direction-left ul li,.fam-btn.direction-right ul li{display:inline-block;margin:7.5px 15px 0 0}.fam-btn.direction-right{padding:0 15px 0 0}.fam-btn.direction-right ul{text-align:left;direction:rtl;left:64px;right:auto}.fam-btn.direction-right ul li{margin:7.5px 0 0 15px}.fam-btn.direction-bottom{padding:0 0 15px 0}.fam-btn.direction-bottom ul{top:64px;bottom:auto;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}.fam-btn.direction-bottom ul li{margin:15px 0 0 0}.fam-btn.toolbar{padding:0;height:56px}.fam-btn.toolbar.active>a i{opacity:0}.fam-btn.toolbar ul{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;top:0;bottom:0;z-index:1}.fam-btn.toolbar ul li{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;display:inline-block;margin:0;height:100%;-webkit-transition:none;transition:none}.fam-btn.toolbar ul li a{display:block;overflow:hidden;position:relative;width:100%;height:100%;background-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#fff;line-height:56px;z-index:1}.fam-btn.toolbar ul li a i{line-height:inherit}.fam-btn ul{left:0;right:0;text-align:center;position:absolute;bottom:64px;margin:0;visibility:hidden}.fam-btn ul li{margin-bottom:15px}.fam-btn ul a.btn-fab-floating{opacity:0}.fam-btn .fam-btn-backdrop{position:absolute;top:0;left:0;z-index:-1;width:40px;height:40px;background-color:#26a69a;border-radius:50%;-webkit-transform:scale(0);transform:scale(0)}.btn-large{height:54px;line-height:54px;font-size:15px;padding:0 28px}.btn-large i{font-size:1.6rem}.btn-small{height:32.4px;line-height:32.4px;font-size:13px}.btn-small i{font-size:1.2rem}
@@ -40,12 +40,7 @@
40
40
  // jadams, 2020-10-10, added class from main (materialize.js)
41
41
  //
42
42
  class Component {
43
- /**
44
- * Generic constructor for all components
45
- * @constructor
46
- * @param {Element} el
47
- * @param {Object} options
48
- */
43
+
49
44
  constructor(classDef, el, options) {
50
45
  // Display error if el is valid HTML Element
51
46
  if (!(el instanceof Element)) {
@@ -66,16 +66,7 @@
66
66
  this.settings = $.extend({}, $.fn.bootstrapThemeSwitcher.defaults, options);
67
67
  this.themesList = [];
68
68
 
69
- // $.when (
70
- // this.getThemes()
71
- // )
72
- // .then(function(data) {
73
- // logger.info('loading local themes (json) finished');
74
- // })
75
- // .catch(function(error) {
76
- // logger.error('loading local themes (json) failed: ' + error);
77
- // });
78
-
69
+ // loading local themes
79
70
  this.getThemes();
80
71
  return this;
81
72
  };
@@ -98,9 +89,9 @@
98
89
  // checkStyleSheetByName
99
90
  // -------------------------------------------------------------------------
100
91
  checkStyleSheetByName: function (name) {
101
- var found = false;
102
- var test = '\/' + name + '\/';
103
- var re = new RegExp(test, 'i');
92
+ var found = false;
93
+ var test = '\/' + name + '\/';
94
+ var re = new RegExp(test, 'i');
104
95
 
105
96
  for(var i = 0; i < document.styleSheets.length; i++){
106
97
  if(re.test(document.styleSheets[i].href)){
@@ -131,29 +122,26 @@
131
122
  var debug = settings.debug;
132
123
  var includeCSS = this.settings.includeBootswatch;
133
124
 
134
- // Detect|Set J1 UserState
125
+ // detect|set user state cookie
135
126
  user_state_detected = j1.existsCookie ( 'j1.user.state' );
136
127
  if ( user_state_detected ) {
137
- logger.debug('user state cookie found');
128
+ logger.debug('cookie found: j1.user.state');
138
129
  j1_user_state = j1.readCookie(user_state_cookie_name);
139
130
  } else {
140
- logger.error('user state NOT cookie found');
131
+ logger.error('cookie not found: j1.user.state');
141
132
  }
142
133
 
143
134
  themeName = j1_user_state.theme_name;
144
135
  theme_css = j1_user_state.theme_css;
145
- theme_extension_css = j1_user_state.theme_extension_css;
146
136
 
147
- if ( cssFile === undefined ) { cssFile = this.settings.defaultCssFile; }
148
- if ( name === undefined ) { name = cssFile; }
149
- // Clear 'includeCSS' if NO theme extension CSS is needed
150
- if ( name === this.settings.skipIncludeBootswatch ) { includeCSS = ''; }
137
+ if (typeof cssFile === 'undefined') { cssFile = this.settings.defaultCssFile; }
138
+ if (typeof name === 'undefined') { name = cssFile; }
151
139
 
152
140
  // check if theme is to be saved to cookie
153
- if ( settings.saveToCookie ) {
154
- if ( Cookies === undefined ) {
141
+ if (settings.saveToCookie) {
142
+ if ( typeof Cookies === 'undefined' ) {
155
143
  if ( debug === 'true' ) {
156
- logger.error('saveToCookie is set to true but Cookies library is not present');
144
+ logger.error('cookies library not present');
157
145
  }
158
146
  return false;
159
147
  }
@@ -162,17 +150,18 @@
162
150
  j1_user_state.theme_css = cssFile;
163
151
 
164
152
  if (!(j1_user_state.theme_name.includes('Uno') || j1_user_state.theme_name == 'Bootstrap')) {
165
- j1_user_state.theme_author = 'Bootswatch';
166
- j1_user_state.theme_author_url = 'https://bootswatch.com/';
153
+ j1_user_state.theme_author = 'Bootswatch';
154
+ j1_user_state.theme_author_url = 'https://bootswatch.com/';
167
155
  } else {
168
- j1_user_state.theme_author = 'J1 Team';
169
- j1_user_state.theme_author_url = 'https://jekyll.one/';
156
+ j1_user_state.theme_author = 'J1 Team';
157
+ j1_user_state.theme_author_url = 'https://jekyll.one/';
170
158
  }
171
159
 
172
160
  j1.writeCookie({
173
161
  name: user_state_cookie_name,
174
162
  data: j1_user_state
175
163
  });
164
+
176
165
  // force reload the page from the server (skip cache)
177
166
  // and detect selected theme from cookie
178
167
  location.reload(true);
@@ -188,20 +177,21 @@
188
177
  // -------------------------------------------------------------------------
189
178
  loadThemeFromCookie: function (options) {
190
179
 
191
- if ( Cookies === undefined ) {
192
- logger.error('loadThemeFromCookie was called but Cookies library is not present');
180
+ if ( typeof Cookies === 'undefined' ) {
181
+ logger.error('cookies library not present');
193
182
  return false;
194
183
  }
195
184
 
196
185
  var settings = $.extend({}, $.fn.bootstrapThemeSwitcher.defaults, options);
197
186
 
198
- // Detect|Set J1 UserState
187
+ // detect|set user state cookie
199
188
  user_state_detected = j1.existsCookie ( 'j1.user.state' );
189
+
200
190
  if ( user_state_detected ) {
201
- logger.info('User state cookie found');
191
+ logger.info('cookie found: j1.user.state');
202
192
  j1_user_state = j1.readCookie(user_state_cookie_name);
203
193
  } else {
204
- logger.error('User state NOT cookie found');
194
+ logger.error('cookie not found: j1.user.state');
205
195
  }
206
196
 
207
197
  var themeName = j1_user_state.theme_name;
@@ -214,8 +204,8 @@
214
204
  // addTheme
215
205
  // -------------------------------------------------------------------------
216
206
  addTheme: function(name, cssFile, start, deleteCount) {
217
- if (start === undefined) { start = 0; }
218
- if (deleteCount === undefined) { deleteCount = 0; }
207
+ if (typeof start === 'undefined') { start = 0; }
208
+ if (typeof deleteCount === 'undefined') { deleteCount = 0; }
219
209
  this.themesList.splice(start, deleteCount, {name: name, css: cssFile});
220
210
  this.addThemesToControl();
221
211
  }, // END addTheme
@@ -224,11 +214,11 @@
224
214
  // addThemesToControl
225
215
  // -------------------------------------------------------------------------
226
216
  addThemesToControl: function() {
227
- if (this.$element === undefined) {
217
+ if (typeof this.$element === 'undefined') {
228
218
  logger.error('bootstrapThemeSelector|addThemesToControl: Element is undefined');
229
219
  return false;
230
220
  }
231
- if (this.themesList === undefined) {
221
+ if (typeof this.themesList === 'undefined') {
232
222
  logger.error('bootstrapThemeSelector|addThemesToControl: Themes is undefined');
233
223
  return false;
234
224
  }
@@ -264,7 +254,7 @@
264
254
  var themeName;
265
255
  var debug = settings.debug;
266
256
 
267
- // Detect|Set J1 UserState
257
+ // detect|set user state cookie
268
258
  user_state_detected = j1.existsCookie ( 'j1.user.state' );
269
259
  if ( user_state_detected ) {
270
260
  logger.debug('User state cookie found');
@@ -308,7 +298,7 @@
308
298
  } else {
309
299
  base.switchTheme(value.name, value.cssCdn);
310
300
  }
311
- //Remove previous "active" class and apply to latest clicked element
301
+ // remove previous "active" class and apply to latest clicked element
312
302
  $(this).parent().find('li').removeClass('active');
313
303
  $(this).addClass('active');
314
304
  });
@@ -355,8 +345,6 @@
355
345
  $.ajax({
356
346
  url: this.settings.localFeed,
357
347
  // jadams 2016-10-10: removed the setting for sychronous XMLHttpRequest
358
- // because deprecated by jQuery on the MAIN thread. Because the Theme Manager
359
- // is initialized very early, no blocking (sychronous) AJAX call is needed
360
348
  // async: false,
361
349
  dataType: 'json',
362
350
  success: function (data) {
@@ -373,12 +361,10 @@
373
361
  $.ajax({
374
362
  url: this.settings.bootswatchApiUrl + '/' + this.settings.bootswatchApiVersion + '.json',
375
363
  // jadams 2016-10-10: removed the setting for sychronous XMLHttpRequest
376
- // because deprecated by jQuery on the main thread. Because the Theme Manager
377
- // is initialized very early, no blocking|sychronous AJAX call is needed
378
364
  // async: false,
379
365
  dataType: 'json',
380
366
  success: function (data) {
381
- if (data.themes === undefined) {
367
+ if (typeof data.themes === 'undefined') {
382
368
  return null;
383
369
  }
384
370
  base.themesList = data.themes;
@@ -393,7 +379,7 @@
393
379
  // themes
394
380
  // -------------------------------------------------------------------------
395
381
  themes : function (newThemeList) {
396
- if (newThemeList === undefined) {
382
+ if (typeof newThemeList === 'undefined') {
397
383
  return this.themesList;
398
384
  }
399
385
  else {
@@ -419,7 +405,7 @@
419
405
  if (typeof option === 'string') {
420
406
  methodReturn = data[ option ].apply(data, args);
421
407
  }
422
- return ( methodReturn === undefined ) ? $this : methodReturn;
408
+ return ( typeof methodReturn === 'undefined' ) ? $this : methodReturn;
423
409
  };
424
410
 
425
411
  $.fn.bootstrapThemeSwitcher.defaults = {
@@ -430,7 +416,7 @@
430
416
  cookieThemeCss: 'boostrapTheme.css',
431
417
  cookieExpiration: 365,
432
418
  cookiePath: '/',
433
- defaultCssFile: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css',
419
+ defaultCssFile: 'https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css',
434
420
  bootswatchApiUrl: 'https://bootswatch.com/api/',
435
421
  bootswatchApiVersion: '4',
436
422
  loadFromBootswatch: true,
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  # -----------------------------------------------------------------------------
3
- # ~/assets/themes/j1/modules/bsThemeSwitcher/js/switcher.min.js
3
+ # ~/assets/themes/j1/modules/bsThemeSwitcher/js/switcher.js
4
4
  # Provides Javascript functions for Bootstrap ThemeSwitcher
5
5
  #
6
6
  # Product/Info:
@@ -15,7 +15,26 @@
15
15
  # Bootstrap Theme Switcher is licensed under the MIT License.
16
16
  # See: https://github.com/jguadagno/bootstrapThemeSwitcher
17
17
  # -----------------------------------------------------------------------------
18
+ # NOTE: This modules is MODIFIED to be used with MobileMenu (mmenuLight).
19
+ # The original version cannot be used with J1 for theme menu creation!
20
+ # -----------------------------------------------------------------------------
18
21
  */
22
+ 'use strict';
23
+
24
+ // -----------------------------------------------------------------------------
25
+ // ESLint shimming
26
+ // -----------------------------------------------------------------------------
27
+ /* eslint indent: "off" */
28
+ /* eslint no-console: ["error", { allow: ["log", "warn", "error"] }] */
29
+ /* eslint no-unused-vars: "off" */
30
+ /* eslint no-undef: "off" */
31
+ /* eslint no-useless-escape: "off" */
32
+ /* eslint no-prototype-builtins: "off" */
33
+ /* eslint no-shadow-restricted-names: "off" */
34
+ /* global jQuery */
35
+ /* global Cookies */
36
+ // -----------------------------------------------------------------------------
37
+
19
38
  /**
20
39
  * jQuery Twitter Bootstrap Theme Switcher v1.1.5
21
40
  * https://github.com/jguadagno/bootstrapThemeSwitcher
@@ -23,4 +42,393 @@
23
42
  * Copyright 2014, Joseph Guadagno
24
43
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
25
44
  */
26
- "use strict";(function(h,i,j,e){var d=h.fn.bootstrapThemeSwitcher;var f=j1.getCookieNames();const n=f.user_state;var m=log4javascript.getLogger("j1.core.switcher");var a;var g;var b={};var k;var c;var l=function(p,o){this.$element=h(p);this.settings=h.extend({},h.fn.bootstrapThemeSwitcher.defaults,o);this.themesList=[];this.getThemes();return this};l.prototype={clear:function(){m.debug("bootstrapThemeSwitcher.clear");return this.$element.each(function(){this.$element.empty()})},update:function(){m.debug("bootstrapThemeSwitcher.update");this.getThemes()},checkStyleSheetByName:function(o){var r=false;var s="/"+o+"/";var q=new RegExp(s,"i");for(var p=0;p<j.styleSheets.length;p++){if(q.test(j.styleSheets[p].href)){r=true;break}}return r},switchTheme:function(p,u){var v=h(this);var r=h.extend({},h.fn.bootstrapThemeSwitcher.defaults,v.data("bootstrapThemeSwitcher"));var t;var x;var w;var q=r.cssThemeLink;var o=r.debug;var s=this.settings.includeBootswatch;g=j1.existsCookie("j1.user.state");if(g){m.debug("user state cookie found");b=j1.readCookie(n)}else{m.error("user state NOT cookie found")}t=b.theme_name;x=b.theme_css;w=b.theme_extension_css;if(u===e){u=this.settings.defaultCssFile}if(p===e){p=u}if(p===this.settings.skipIncludeBootswatch){s=""}if(r.saveToCookie){if(Cookies===e){if(o==="true"){m.error("saveToCookie is set to true but Cookies library is not present")}return false}b.theme_name=p;b.theme_css=u;if(!(b.theme_name.includes("Uno")||b.theme_name=="Bootstrap")){b.theme_author="Bootswatch";b.theme_author_url="https://bootswatch.com/"}else{b.theme_author="J1 Team";b.theme_author_url="https://jekyll.one/"}j1.writeCookie({name:n,data:b});location.reload(true)}else{m.warn("write to cookie : disabled");m.warn("selected theme not activated: "+p)}},loadThemeFromCookie:function(o){if(Cookies===e){m.error("loadThemeFromCookie was called but Cookies library is not present");return false}var p=h.extend({},h.fn.bootstrapThemeSwitcher.defaults,o);g=j1.existsCookie("j1.user.state");if(g){m.info("User state cookie found");b=j1.readCookie(n)}else{m.error("User state NOT cookie found")}var r=b.theme_name;var q=b.theme_css;this.switchTheme(r,q)},addTheme:function(p,o,r,q){if(r===e){r=0}if(q===e){q=0}this.themesList.splice(r,q,{name:p,css:o});this.addThemesToControl()},addThemesToControl:function(){if(this.$element===e){m.error("bootstrapThemeSelector|addThemesToControl: Element is undefined");return false}if(this.themesList===e){m.error("bootstrapThemeSelector|addThemesToControl: Themes is undefined");return false}if(this.settings.excludeBootswatch){var v;if(this.settings.excludeBootswatch.indexOf(",")!==-1){v=this.settings.excludeBootswatch.replace(/ /g,"").split(",")}else{v=[];v.push(this.settings.excludeBootswatch)}var r=this.themesList;h.each(r,function(z,A){if(A&&A.name){if(h.inArray(A.name,v)!==-1){r.splice(z,1)}}});this.themesList=r}var q=this;if(this.$element.is("ul")){var w=h(this);var s=h.extend({},h.fn.bootstrapThemeSwitcher.defaults,w.data("bootstrapThemeSwitcher"));var p=s.cssThemeLink;var t;var o=s.debug;g=j1.existsCookie("j1.user.state");if(g){m.debug("User state cookie found");b=j1.readCookie(n)}else{m.error("User state NOT cookie found")}t=b.theme_name;if(o==="true"){m.debug("bootstrapThemeSelector: UL element selected")}this.$element.empty();var y;var x="#9E9E9E";h.each(this.themesList,function(A,B){if(q.$element[0].id.includes("mmenu")){y="mmenu-item"}else{y="dropdown-item"}if(B.name===t){if(q.$element[0].id.includes("mmenu")){y="mmenu-item active"}else{y="dropdown-item active"}}var z=h("<li />").attr("class",y).append('<a href="#"><i class="mdi mdi-view-quilt mdi-18px mr-2" style="color: '+x+'"></i>'+B.name+"</a>").on("click",function(){if(s.loadFromBootswatch){q.switchTheme(B.name,B.css)}else{q.switchTheme(B.name,B.cssCdn)}h(this).parent().find("li").removeClass("active");h(this).addClass("active")});q.$element.append(z)})}else{if(this.$element.is("select")){m.debug("bootstrapThemeSelector: SELECT element selected");this.$element.empty();var u;h.each(this.themesList,function(z,A){u=null;if(A.name===t){u="selected"}if(s.loadFromBootswatch){q.$element.append("<option "+u+" value='"+A.css+"'>"+A.name+"</option>")}else{q.$element.append("<option "+u+" value='"+A.cssCdn+"'>"+A.name+"</option>")}});this.$element.on("change",function(){var z=h("option:selected",this);q.switchTheme(z.text(),z.val())})}else{m.info("bootstrapThemeSelector: no UL or SELECT element found");m.error("bootstrapThemeSelector: failed")}}},getThemes:function(){var o=this;if(this.settings.localFeed!==null&&this.settings.localFeed!==""){h.ajax({url:this.settings.localFeed,dataType:"json",success:function(p){o.themesList=p.themes;o.addThemesToControl()},error:function(p,r,q){m.error("Failed to retrieve the local feed from: '"+o.settings.localFeed+"'")}})}else{h.ajax({url:this.settings.bootswatchApiUrl+"/"+this.settings.bootswatchApiVersion+".json",dataType:"json",success:function(p){if(p.themes===e){return null}o.themesList=p.themes;o.themesList.splice(0,0,{name:"default",css:o.settings.defaultCssFile});o.addThemesToControl()}})}},themes:function(o){if(o===e){return this.themesList}else{this.themesList=o}}};h.fn.bootstrapThemeSwitcher=function(q){var s;var p=Array.prototype.slice.call(arguments,1);var t=h(this);var r=t.data("bootstrapThemeSwitcher");var o=typeof q==="object"&&q;if(!r){t.data("bootstrapThemeSwitcher",(r=new l(this,o)))}if(typeof q==="string"){s=r[q].apply(r,p)}return(s===e)?t:s};h.fn.bootstrapThemeSwitcher.defaults={debug:false,saveToCookie:true,cssThemeLink:"bootstrapTheme",cookieThemeName:"bootstrapTheme.name",cookieThemeCss:"boostrapTheme.css",cookieExpiration:365,cookiePath:"/",defaultCssFile:"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css",bootswatchApiUrl:"https://bootswatch.com/api/",bootswatchApiVersion:"4",loadFromBootswatch:true,localFeed:"",excludeBootswatch:""};h.fn.bootstrapThemeSwitcher.Constructor=l;h.fn.bootstrapThemeSwitcher.noConflict=function(){h.fn.BootstrapThemeSwitcher=d;return this}})(jQuery,window,document);
45
+
46
+ (function ($, window, document, undefined) {
47
+
48
+ var old = $.fn.bootstrapThemeSwitcher;
49
+
50
+ var cookie_names = j1.getCookieNames();
51
+ const user_state_cookie_name = cookie_names.user_state;
52
+
53
+ var logger = log4javascript.getLogger('j1.core.switcher');
54
+ var logText;
55
+
56
+ var user_state_detected;
57
+ var j1_user_state = {};
58
+ var j1_user_state_json;
59
+ var j1_user_state_cookie;
60
+
61
+ // Constructor
62
+ // ---------------------------------------------------------------------------
63
+ var BootstrapThemeSwitcher = function (element, options) {
64
+
65
+ this.$element = $(element);
66
+ this.settings = $.extend({}, $.fn.bootstrapThemeSwitcher.defaults, options);
67
+ this.themesList = [];
68
+
69
+ // loading local themes
70
+ this.getThemes();
71
+ return this;
72
+ };
73
+
74
+ // Prototype
75
+ // ---------------------------------------------------------------------------
76
+ BootstrapThemeSwitcher.prototype = {
77
+ clear: function () {
78
+ logger.debug('bootstrapThemeSwitcher.clear');
79
+ return this.$element.each(function () {
80
+ this.$element.empty();
81
+ });
82
+ },
83
+ update: function () {
84
+ logger.debug('bootstrapThemeSwitcher.update');
85
+ this.getThemes();
86
+ },
87
+
88
+ // -------------------------------------------------------------------------
89
+ // checkStyleSheetByName
90
+ // -------------------------------------------------------------------------
91
+ checkStyleSheetByName: function (name) {
92
+ var found = false;
93
+ var test = '\/' + name + '\/';
94
+ var re = new RegExp(test, 'i');
95
+
96
+ for(var i = 0; i < document.styleSheets.length; i++){
97
+ if(re.test(document.styleSheets[i].href)){
98
+ found=true;
99
+ break;
100
+ }
101
+ }
102
+ return found;
103
+ },
104
+
105
+ // -------------------------------------------------------------------------
106
+ // switchTheme
107
+ // -------------------------------------------------------------------------
108
+ // NOTE:
109
+ // For J1 template, switchTheme set only the cookies contents. The theme
110
+ // switch is done by a page reload. The reload triggers the theme_generator
111
+ // to load theme CSS from cookies, finally.
112
+ // -------------------------------------------------------------------------
113
+ switchTheme: function (name, cssFile) {
114
+
115
+ var $this = $(this);
116
+ var settings = $.extend({}, $.fn.bootstrapThemeSwitcher.defaults, $this.data('bootstrapThemeSwitcher'));
117
+ var themeName;
118
+ var theme_css;
119
+ var theme_extension_css;
120
+
121
+ var id = settings.cssThemeLink;
122
+ var debug = settings.debug;
123
+ var includeCSS = this.settings.includeBootswatch;
124
+
125
+ // detect|set user state cookie
126
+ user_state_detected = j1.existsCookie ( 'j1.user.state' );
127
+ if ( user_state_detected ) {
128
+ logger.debug('cookie found: j1.user.state');
129
+ j1_user_state = j1.readCookie(user_state_cookie_name);
130
+ } else {
131
+ logger.error('cookie not found: j1.user.state');
132
+ }
133
+
134
+ themeName = j1_user_state.theme_name;
135
+ theme_css = j1_user_state.theme_css;
136
+
137
+ if (typeof cssFile === 'undefined') { cssFile = this.settings.defaultCssFile; }
138
+ if (typeof name === 'undefined') { name = cssFile; }
139
+
140
+ // check if theme is to be saved to cookie
141
+ if (settings.saveToCookie) {
142
+ if ( typeof Cookies === 'undefined' ) {
143
+ if ( debug === 'true' ) {
144
+ logger.error('cookies library not present');
145
+ }
146
+ return false;
147
+ }
148
+
149
+ j1_user_state.theme_name = name;
150
+ j1_user_state.theme_css = cssFile;
151
+
152
+ if (!(j1_user_state.theme_name.includes('Uno') || j1_user_state.theme_name == 'Bootstrap')) {
153
+ j1_user_state.theme_author = 'Bootswatch';
154
+ j1_user_state.theme_author_url = 'https://bootswatch.com/';
155
+ } else {
156
+ j1_user_state.theme_author = 'J1 Team';
157
+ j1_user_state.theme_author_url = 'https://jekyll.one/';
158
+ }
159
+
160
+ j1.writeCookie({
161
+ name: user_state_cookie_name,
162
+ data: j1_user_state
163
+ });
164
+
165
+ // force reload the page from the server (skip cache)
166
+ // and detect selected theme from cookie
167
+ location.reload(true);
168
+ } else {
169
+ logger.warn('write to cookie : disabled');
170
+ logger.warn('selected theme not activated: ' + name);
171
+ } // END if saveToCookie
172
+
173
+ }, // END switchTheme
174
+
175
+ // -------------------------------------------------------------------------
176
+ // loadThemeFromCookie
177
+ // -------------------------------------------------------------------------
178
+ loadThemeFromCookie: function (options) {
179
+
180
+ if ( typeof Cookies === 'undefined' ) {
181
+ logger.error('cookies library not present');
182
+ return false;
183
+ }
184
+
185
+ var settings = $.extend({}, $.fn.bootstrapThemeSwitcher.defaults, options);
186
+
187
+ // detect|set user state cookie
188
+ user_state_detected = j1.existsCookie ( 'j1.user.state' );
189
+
190
+ if ( user_state_detected ) {
191
+ logger.info('cookie found: j1.user.state');
192
+ j1_user_state = j1.readCookie(user_state_cookie_name);
193
+ } else {
194
+ logger.error('cookie not found: j1.user.state');
195
+ }
196
+
197
+ var themeName = j1_user_state.theme_name;
198
+ var themeCss = j1_user_state.theme_css;
199
+ this.switchTheme(themeName, themeCss);
200
+
201
+ }, // END loadThemeFromCookie
202
+
203
+ // -------------------------------------------------------------------------
204
+ // addTheme
205
+ // -------------------------------------------------------------------------
206
+ addTheme: function(name, cssFile, start, deleteCount) {
207
+ if (typeof start === 'undefined') { start = 0; }
208
+ if (typeof deleteCount === 'undefined') { deleteCount = 0; }
209
+ this.themesList.splice(start, deleteCount, {name: name, css: cssFile});
210
+ this.addThemesToControl();
211
+ }, // END addTheme
212
+
213
+ // -------------------------------------------------------------------------
214
+ // addThemesToControl
215
+ // -------------------------------------------------------------------------
216
+ addThemesToControl: function() {
217
+ if (typeof this.$element === 'undefined') {
218
+ logger.error('bootstrapThemeSelector|addThemesToControl: Element is undefined');
219
+ return false;
220
+ }
221
+ if (typeof this.themesList === 'undefined') {
222
+ logger.error('bootstrapThemeSelector|addThemesToControl: Themes is undefined');
223
+ return false;
224
+ }
225
+
226
+ // if BootSwatch excludes are set
227
+ if(this.settings.excludeBootswatch){
228
+ var excludeBootswatchs;
229
+ // split the string on ,
230
+ if(this.settings.excludeBootswatch.indexOf(',') !== -1){
231
+ excludeBootswatchs = this.settings.excludeBootswatch.replace(/ /g, '').split(',');
232
+ } else {
233
+ excludeBootswatchs = [];
234
+ excludeBootswatchs.push(this.settings.excludeBootswatch);
235
+ }
236
+
237
+ var tempThemeList = this.themesList;
238
+ $.each(tempThemeList, function (i, value) {
239
+ if(value && value.name){
240
+ if( $.inArray( value.name, excludeBootswatchs ) !== -1 ){
241
+ tempThemeList.splice(i,1);
242
+ }
243
+ }
244
+ });
245
+ this.themesList = tempThemeList;
246
+ }
247
+
248
+ var base = this;
249
+
250
+ if (this.$element.is('ul')) {
251
+ var $this = $(this);
252
+ var settings = $.extend({}, $.fn.bootstrapThemeSwitcher.defaults, $this.data('bootstrapThemeSwitcher'));
253
+ var id = settings.cssThemeLink;
254
+ var themeName;
255
+ var debug = settings.debug;
256
+
257
+ // detect|set user state cookie
258
+ user_state_detected = j1.existsCookie ( 'j1.user.state' );
259
+ if ( user_state_detected ) {
260
+ logger.debug('User state cookie found');
261
+ j1_user_state = j1.readCookie(user_state_cookie_name);
262
+ } else {
263
+ logger.error('User state NOT cookie found');
264
+ }
265
+
266
+ themeName = j1_user_state.theme_name;
267
+
268
+ if ( debug === 'true' ) {
269
+ logger.debug('bootstrapThemeSelector: UL element selected');
270
+ }
271
+ this.$element.empty();
272
+
273
+ var cssClass;
274
+ var iconColor = '#9E9E9E';
275
+ $.each(this.themesList, function (i, value) {
276
+ // Use DIFFERENT class for MobileMenu
277
+ //if (base.$element[0].id.includes('MMenu')) {
278
+ if (base.$element[0].id.includes('mmenu')) {
279
+ cssClass = 'mmenu-item';
280
+ } else {
281
+ cssClass = 'dropdown-item';
282
+ }
283
+ // Add class "active" to the current theme selected
284
+ if ( value.name === themeName ) {
285
+ // if (base.$element[0].id.includes('MMenu')) {
286
+ if (base.$element[0].id.includes('mmenu')) {
287
+ cssClass = 'mmenu-item active';
288
+ } else {
289
+ cssClass = 'dropdown-item active';
290
+ }
291
+ }
292
+ var li = $('<li />')
293
+ .attr('class',cssClass)
294
+ .append('<a href="#"><i class="mdi mdi-view-quilt mdi-18px mr-2" style="color: ' +iconColor+ '"></i>' +value.name+ '</a>')
295
+ .on('click', function () {
296
+ if (settings.loadFromBootswatch) {
297
+ base.switchTheme(value.name, value.css);
298
+ } else {
299
+ base.switchTheme(value.name, value.cssCdn);
300
+ }
301
+ // remove previous "active" class and apply to latest clicked element
302
+ $(this).parent().find('li').removeClass('active');
303
+ $(this).addClass('active');
304
+ });
305
+ base.$element.append(li);
306
+ });
307
+
308
+ } else if (this.$element.is('select')) {
309
+ logger.debug('bootstrapThemeSelector: SELECT element selected');
310
+ this.$element.empty();
311
+
312
+ var optionSelectedMarker;
313
+ $.each(this.themesList, function (i, value) {
314
+ optionSelectedMarker = null;
315
+ if ( value.name === themeName ) {
316
+ optionSelectedMarker = 'selected';
317
+ }
318
+ if (settings.loadFromBootswatch) {
319
+ base.$element.append('<option ' + optionSelectedMarker + ' value=\'' + value.css + '\'>' + value.name + '</option>');
320
+ } else {
321
+ base.$element.append('<option ' + optionSelectedMarker + ' value=\'' + value.cssCdn + '\'>' + value.name + '</option>');
322
+ }
323
+ });
324
+ this.$element.on('change', function () {
325
+ var optionSelected = $('option:selected', this);
326
+ base.switchTheme(optionSelected.text(), optionSelected.val());
327
+ });
328
+
329
+ } else {
330
+ // no container found to add Theme list
331
+ logger.info('bootstrapThemeSelector: no UL or SELECT element found');
332
+ logger.error('bootstrapThemeSelector: failed');
333
+ // console.warn('bootstrapThemeSelector only works with ul or select elements');
334
+ }
335
+ }, // END addThemesToControl
336
+
337
+ // -------------------------------------------------------------------------
338
+ // getThemes
339
+ // -------------------------------------------------------------------------
340
+ getThemes: function() {
341
+ var base = this;
342
+
343
+ if (this.settings.localFeed !== null && this.settings.localFeed !== '') {
344
+ // Deferred loading themes from local themes (json file)
345
+ $.ajax({
346
+ url: this.settings.localFeed,
347
+ // jadams 2016-10-10: removed the setting for sychronous XMLHttpRequest
348
+ // async: false,
349
+ dataType: 'json',
350
+ success: function (data) {
351
+ base.themesList = data.themes;
352
+ base.addThemesToControl();
353
+ },
354
+ error: function (jqXHR, textStatus, errorThrown) {
355
+ logger.error('Failed to retrieve the local feed from: \'' + base.settings.localFeed + '\'');
356
+ }
357
+ });
358
+ } else {
359
+ // Deferred loading remote themes from Bootswatch API
360
+ // -----------------------------------------------------------------------
361
+ $.ajax({
362
+ url: this.settings.bootswatchApiUrl + '/' + this.settings.bootswatchApiVersion + '.json',
363
+ // jadams 2016-10-10: removed the setting for sychronous XMLHttpRequest
364
+ // async: false,
365
+ dataType: 'json',
366
+ success: function (data) {
367
+ if (typeof data.themes === 'undefined') {
368
+ return null;
369
+ }
370
+ base.themesList = data.themes;
371
+ base.themesList.splice(0,0, {name: 'default', css: base.settings.defaultCssFile});
372
+ base.addThemesToControl();
373
+ }
374
+ });
375
+ }
376
+ }, // END getThemes
377
+
378
+ // -------------------------------------------------------------------------
379
+ // themes
380
+ // -------------------------------------------------------------------------
381
+ themes : function (newThemeList) {
382
+ if (typeof newThemeList === 'undefined') {
383
+ return this.themesList;
384
+ }
385
+ else {
386
+ // TODO: Set the associated control.
387
+ this.themesList = newThemeList;
388
+ }
389
+ } // END themes
390
+
391
+ }; // END prototype
392
+
393
+ // Plugin definition
394
+ // ---------------------------------------------------------------------------
395
+ $.fn.bootstrapThemeSwitcher = function (option) {
396
+ var methodReturn;
397
+ var args = Array.prototype.slice.call(arguments, 1);
398
+ var $this = $(this);
399
+ var data = $this.data('bootstrapThemeSwitcher');
400
+ var options = typeof option === 'object' && option;
401
+
402
+ if (!data) {
403
+ $this.data('bootstrapThemeSwitcher', (data = new BootstrapThemeSwitcher(this, options) ));
404
+ }
405
+ if (typeof option === 'string') {
406
+ methodReturn = data[ option ].apply(data, args);
407
+ }
408
+ return ( typeof methodReturn === 'undefined' ) ? $this : methodReturn;
409
+ };
410
+
411
+ $.fn.bootstrapThemeSwitcher.defaults = {
412
+ debug: false,
413
+ saveToCookie: true,
414
+ cssThemeLink: 'bootstrapTheme',
415
+ cookieThemeName: 'bootstrapTheme.name',
416
+ cookieThemeCss: 'boostrapTheme.css',
417
+ cookieExpiration: 365,
418
+ cookiePath: '/',
419
+ defaultCssFile: 'https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css',
420
+ bootswatchApiUrl: 'https://bootswatch.com/api/',
421
+ bootswatchApiVersion: '4',
422
+ loadFromBootswatch: true,
423
+ localFeed: '',
424
+ excludeBootswatch: ''
425
+ };
426
+
427
+ $.fn.bootstrapThemeSwitcher.Constructor = BootstrapThemeSwitcher;
428
+
429
+ $.fn.bootstrapThemeSwitcher.noConflict = function () {
430
+ $.fn.BootstrapThemeSwitcher = old;
431
+ return this;
432
+ };
433
+
434
+ })(jQuery, window, document);