PageSourceSearch

https://backtypo.com/backtypo.themes.js

js backtypo.com collected 2026-09-26 16:21:22 UTC 19,027 bytes, 486 lines download raw bytes

1var ThemeChooser = {
2    init: function(){
3        var selected_theme = arguments[0];
4        var me = this;
5        this.hidden = true;
6        this.descriptions = [];
7        if (typeof(themeDescriptions) !== 'undefined')
8            this.descriptions = themeDescriptions;
9        this.element = $('#theme-chooser');
10        if (this.element.length === 0) this.element = $('#themes-container');
11        this.$selected = this.element.find('.selected');
12        if(!selected_theme)
13            selected_theme = this.$selected.attr('data-theme');
14        this.selected = selected_theme;
15        this.active = selected_theme;
16        this.header = $('#theme-chooser-header');
17        this.tabBar = $('ul#theme-tabs');
18        this.tabs = $('ul#theme-tabs li.theme-tab');
19        this.sections = $('#themes-container section.themes');
20        this.activateButton = this.element.find('.activate-theme');
21        this.activateButton.hide();
22        this.editButton = this.element.find('.edit_theme');
23        this.customizeButton = this.element.find('.customize_theme');
24        this.closeButton = this.header.find('.close_dialog');
25        this.themesContainer = $('#themes-container');
26        /* DEPRECATED START */
27        this.previewContainer = $('#theme-preview-container');
28        this.previewPage = this.previewContainer.find('.theme_page');
29        this.previewTitle = this.previewContainer.find('.theme-details h3');
30        this.previewDescription =
31            this.previewContainer.find('p.theme-description');
32        this.previewButton = this.previewContainer.find('.preview_theme');
33        /*DEPRECATED END */
34
35        this.bookFormThemeTab = $('#book-data #theme,#print-data #theme');
36        this.bookFormThemeContainer =
37            this.bookFormThemeTab.find('.theme-container');
38        this.bookFormTheme = this.bookFormThemeContainer.find('.theme');
39        this.bookFormThemeTitle =
40            this.bookFormThemeTab.find('.theme-name');
41        this.bookFormThemeDescription =
42            this.bookFormThemeTab.find('.theme-description');
43        this.bookFormThemeActions =
44            this.bookFormThemeContainer.find('.theme-action');
45        this.bookFormThemeActions =
46            this.bookFormThemeActions.
47                add(this.bookFormThemeTab.find('#theme-actions button'));
48        this.isPrintProduct =
49            (this.bookFormThemeTab.parents('#print-data').length > 0);
50        this.previewButtons = this.element.find('.preview-button');
51        this.activeLabel = this.previewContainer.find('.active-label');
52        this.pagePreviewContainer = $('#theme-container');
53        this.pagePreviewImage = this.pagePreviewContainer.find('.theme');
54        this.pagePreviewTitle = this.pagePreviewContainer.find('.theme-name');
55        this.newThemesButton = this.tabBar.find('.new-theme');
56        this.newThemeDialog = $('#new-theme-dialog');
57        this.themes = this.themesContainer.find('.theme-container');
58        this.themes.click(function(){
59            var $this = $(this);
60            var theme_id = $this.attr('data-theme');
61            me.selectTheme(theme_id, $this);
62        });
63        this.closeButton.click(function(){
64            me.hide();
65        });
66        var getClickHandler = function (targetButton) {
67            return function (e) {
68                var $this = $(this);
69                var $theme = $this.parents('.theme-container');
70                if ($theme.length) {
71                    var theme_id = $theme.attr('data-theme');
72                    me.selectTheme(theme_id, $theme);
73                    var btn = targetButton;
74                    if (typeof(btn) === 'function')
75                        btn = targetButton($theme);
76                    btn.click();
77                }
78            }
79        };
80        this.element.find('.activate-button').
81            click(getClickHandler(this.activateButton));
82        this.element.find('.edit-button').click(getClickHandler(function ($t) {
83            var is_user = $t.data('userTheme');
84            return (is_user ? me.editButton : me.customizeButton);
85        }));
86         this.element.find('.info-button').click(function () {
87            //var $this = $(this);
88            //var $theme = $this.parents('.theme-container');
89            var $details = me.previewContainer;
90            $details.transitionShow({fade:true, duration:300});
91        });
92        this.previewContainer.find('.close_dialog').click(function(){
93            me.previewContainer.transitionHide({fade:true, duration:300});
94        });
95        this.activateButton.click(function () {
96            if (me.isActivating) return;
97            var $this = $(this);
98            me.activateButton.hide();
99            var theme = me.selected;
100            if (!theme) return;
101            if (me.isPrintProduct) {
102                PrintProductForm.save('theme', theme, me.activateButton,
103                                      function (res) {
104                    try {
105                        res = res.theme || {};
106                        if (theme == res.id) {
107                            me.onThemeActivated(theme, res);
108                        }
109                    } catch (e) {
110                        console.error(e); 
111                    }
112                }); 
113                return;
114            }
115            var bookID = me.getBookID();
116            var url = '/ajax/ebook/:id/set_theme/:theme_name';
117            url = url.ajaxUrl({
118                id: bookID,
119                theme_name: theme
120            });
121            me.isActivating = true;
122            $.get(url, '', function(res,xhr,code){
123                me.isActivating = false;
124                if (code.status == 200) {
125                    try {
126                        res = parseBackTypoResponse(res);
127                        if (theme == res.id) {
128                            me.onThemeActivated(theme, res);
129                        }
130                    } catch (e) {
131                        console.error(e); 
132                    }
133                } else {
134                    alert('Error'); 
135                    console.log(res);
136                    $this.show();
137                } 
138            });
139        });
140        this.previewButton.click(function(){
141            var themeName = me.selected;
142            var url = '/ajax/theme/:theme_name/screenshots'.ajaxUrl({
143                theme_name: themeName
144            });
145            openScreenshotsViewer(url);
146        });
147        this.previewButtons.click(function(evt){
148            evt.preventDefault();
149            evt.stopPropagation();
150            var tpl = $(this).parents('.theme-container').data('theme');
151            var url = '/ajax/theme/:theme_name/screenshots'.ajaxUrl({
152                theme_name: tpl
153            });
154            openScreenshotsViewer(url);
155        });
156        this.editButton.click(function () {
157            var theme = me.selected;
158            if(!theme) return;
159            var elem = me.getThemeElement(theme);
160            var url = elem.data('url');
161            if (url) {
162                location.href = url;
163            }
164        });
165        this.customizeButton.click(function () {
166            var theme = me.selected;
167            if(!theme) return;
168            me.openNewThemeDialog({parent: theme});
169        });
170        var safariMatch = navigator.userAgent.match(/Safari/i);
171        var chromeMatch = navigator.userAgent.match(/Chrome/i);
172        this.isSafari = (safariMatch != null && 
173                         safariMatch.length > 0 && !chromeMatch);
174        this.safariBugged = $('#theme-chooser-header,#theme-preview-container');
175        var currentTab = this.tabs.filter('.current');
176        this.currentSection = currentTab.data('section');
177        this.tabs.click(function () {
178            var $tab = $(this);
179            var section = $tab.data('section');
180            if (section) {
181                me.changeSection(section, $tab);
182            }
183        });
184        var noThumbThemes = this.themes.filter('.no-thumb');
185        if (noThumbThemes.length) {
186            noThumbThemes.each(function () {
187                var $theme = $(this);
188                updateThemeThumbnail($theme);
189            });
190        }
191        this.newThemesButton.click(function () {
192            me.openNewThemeDialog();
193        });
194        this.initNewThemeDialog();
195        /*this.element.scroll(function(evt){
196            evt.stopImmediatePropagation();
197            evt.stopPropagation();
198        });*/
199    },
200    onThemeActivated: function (theme_id, theme) {
201        this.active = theme_id;
202        this.themesContainer.find('.active').
203            removeClass('active');
204        var elem = this.getThemeElement(theme_id);
205        elem.addClass('active');
206        this.selectTheme(theme_id);
207        var thumb = theme.thumb;
208        var themeclass = theme_id + '_theme';
209        var do_update = false;
210        if (thumb) {
211            thumb = 'url(' + thumb + ')';
212        } else {
213            thumb = 'none';
214            themeclass += ' no-thumb';
215            do_update = true;
216        }
217        this.bookFormThemeContainer.
218            data('theme', theme_id).
219            attr('data-theme', theme_id);
220        var themeName = theme.name;
221        if (!themeName) {
222            themeName = theme_id.replace(/_/g, ' ');
223            themeName = themeName.capitalize();
224        }
225        this.bookFormThemeTitle.text(themeName);
226        var descr = this.descriptions[theme_id] || '';
227        this.bookFormThemeDescription.text(descr);
228        this.activeLabel.show();
229        $('#bundler-dialog .current-theme span').text(themeName);
230        var is_custom = theme.user_theme;
231        var editBtn = null;
232        var editLbl = null;
233        if (is_custom) {
234            editBtn = $('#customize-theme'); 
235            if (editBtn.length) {
236                editBtn.attr('id', 'edit-theme');
237            } else {
238                editBtn = $('#edit-theme'); 
239            }
240            editLbl = 'edit_theme';
241        } else {
242            editBtn = $('#edit-theme'); 
243            if (editBtn.length) {
244                editBtn.attr('id', 'customize-theme');
245            } else {
246                editBtn = $('#customize-theme'); 
247            }
248            editLbl = 'customize_theme';
249        }
250        if (editBtn && editBtn.length) {
251            editLbl = BackTypoLocalizedString(editLbl);
252            editBtn.data('theme-id', theme_id).
253                    attr('data-theme-id', theme_id).
254                    find('span').
255                    text(editLbl.capitalize());
256            
257        }
258        this.bookFormThemeActions.
259            attr('data-theme-id', theme_id);
260        editBtn =
261            this.bookFormThemeActions.filter('.edit-button');
262        editBtn.attr('data-action',
263                     (is_custom ? 'edit' : 'customize'));
264        if (do_update) 
265            updateThemeThumbnail(this.bookFormTheme);
266        else
267            this.bookFormTheme.css('background-image', thumb);
268    },
269    changeSection: function (section) {
270        var $tab = arguments[1];
271        if (!$tab)
272            $tab = this.tabBar.find('li[data-section="' + section + '"]');
273        if (section == this.currentSection) return;
274        this.tabs.removeClass('current');
275        this.sections.removeClass('current');
276        $tab.addClass('current');
277        $('section#' + section + '-themes').addClass('current');
278        this.currentSection = section;
279    },
280    openNewThemeDialog: function () {
281        var opts = arguments[0] || {};
282        var parentTheme = opts.parent;
283        var dialog = this.newThemeDialog;
284        if (parentTheme) {
285            var parentSelector = dialog.find('select[name="parent-theme"]');
286            parentSelector.val(parentTheme);
287        }
288        dialog.data('book-id', opts.bookID);
289        dialog.css('display','flex').transition({opacity: 1, duration: 400});
290        setTimeout(function () {
291            var nameField = dialog.find('#new-theme-name');
292            nameField.focus();
293        }, 410);
294    },
295    closeNewThemeDialog: function () {
296        var dialog = this.newThemeDialog;
297        dialog.transition({opacity: 0, duration: 400});
298        setTimeout(function () {
299            dialog.hide();
300        }, 410);
301    },
302    initNewThemeDialog: function () {
303        var me = this;
304        var dialog = this.newThemeDialog;
305        dialog.css('opacity', 0);
306        var closeBtn = dialog.find('.close_dialog');
307        closeBtn.click(function () {
308            me.closeNewThemeDialog();
309        });
310        var nameField = dialog.find('#new-theme-name');
311        var parentSelector = dialog.find('select[name="parent-theme"]');
312        var createBtn = dialog.find('.create-button');
313        var createTheme = function () {
314            if (me.isCreatingNewTheme) return;
315            var name = nameField.val();
316            if (!name) {
317                nameField.addClass('required');
318                nameField.focus();
319                return;
320            }
321            nameField.removeClass('required');
322            me.isCreatingNewTheme = true;
323            var par = parentSelector.val();
324            var newTheme = {
325                name: name,
326                parent: par,
327                book_model: me.element.data('model')
328            };
329            var bookID = dialog.data('book-id');
330            if (bookID) newTheme.book_id = bookID;
331            var url = '/ajax/user_themes';
332            $.post(url, JSON.stringify(newTheme), function (r) {
333                try {
334                    me.isCreatingNewTheme = false;
335                    r = parseBackTypoResponse(r);
336                    if (r.error) {
337                        var errmsg = LocalizedString[r.error] || 
338                            r.error.replace('_', ' ').capitalize();
339                        displayErrorDialog(errmsg);
340                        return;
341                    }
342                    var themeUrl = r.url;
343                    if (!themeUrl) {
344                        // TODO: Handle
345                        return;
346                    }
347                    //TODO: Add new theme to theme chooser UI
348                    location.href = themeUrl;
349                } catch (e) {
350                    // TODO: Handle
351                    var errmsg = e.toString();
352                    var btErr = e.backtypoError;
353                    if (btErr) errmsg = btErr.error;
354                    if (btErr == 'authentication_failed') {
355                        onAjaxAuthenticationFailure(e);
356                    }
357                    errmsg = LocalizedString[errmsg] || 
358                        errmsg.replace(/_/g, ' ').capitalize()
359                    displayErrorDialog(errmsg || 'error');
360                }
361            });
362        };
363        createBtn.click(createTheme);
364        nameField.keypress(function(e){
365            if(e.which == 13){
366                createTheme();
367            }
368        });
369
370    },
371    selectTheme: function(theme_id){
372        this.selected = theme_id;
373        var sel = this.element.find('.selected')
374        sel.removeClass('selected');
375        var elem = arguments[1]; 
376        if (!elem) {
377            elem = this.getThemeElement(theme_id);
378        }
379        elem.addClass('selected');
380        var bgimg = 'url(/images/' + theme_id + '.example.png)';
381        var themeName = elem.data('name');
382        var isUserTheme = elem.data('user-theme');
383        var section = elem.data('section');
384        if (section) this.changeSection(section);
385        themeName = themeName || theme_id.replace(/_/g, ' ');
386        this.previewPage.css('background-image', bgimg);
387        this.previewTitle.text(themeName.capitalizeAll());
388        this.previewDescription.text(this.descriptions[theme_id] || '');
389        this.$selected = elem;
390        if(!this.isActivating){
391            if(this.active != theme_id){
392                this.activateButton.show();
393                this.previewButton.show();
394                this.activeLabel.hide();
395            } 
396            else {
397                this.previewButton.show();
398                this.activateButton.hide();
399                this.activeLabel.show();
400            } 
401        } else {
402            this.activateButton.hide();
403            this.activeLabel.hide();
404        }
405        if (isUserTheme) {
406            this.customizeButton.hide();
407            this.editButton.show();
408        } else {
409            this.customizeButton.show();
410            this.editButton.hide();
411        }
412    },
413    getThemeElement: function (themeId) {
414        return $('#' + themeId.replace(/:/g, '-') +'-theme');
415    },
416    getBookID: function(){
417        if(!this.bookID){
418            if(typeof(BookForm) != 'undefined'){
419                this.bookID = BookForm.bookID;
420            }
421            else if(typeof(authoringTool) != 'undefined'){
422                this.bookID = authoringTool.bookID;
423            }
424        }
425        return this.bookID;
426    },
427    show: function(){
428        var opts = arguments[0] || {};
429        var $el = this.element;
430        disableWindowScroll();
431        if(opts.animate === false){
432            $el.css('translate', '0,0');
433            $el.show();
434            return;
435        }
436        if(this.isSafari) this.safariBugged.css('opacity',0);
437        var redactorDisabler = $('#redactor-disabler');
438        if(redactorDisabler.length > 0){
439            this.redactorDisabledZIndex = redactorDisabler.css('z-index');
440            redactorDisabler.css('z-index', 1);
441        }
442        $el.css('translate', '0,-100%');
443        $el.show();
444        $el.transition({x: 0, y: 0, duration: 400});
445        var _this = this;
446        // Workaround for Webkit and mouse-over after translate
447        _this.element.find('.selected').removeClass('selected');
448        setTimeout(function(){
449            $el.css('transform','');
450            if(_this.isSafari) 
451                _this.safariBugged.transition({opacity: 1, duration:100});
452            // Workaround for Webkit and mouse-over after translate
453            _this.selectTheme(_this.selected,_this.$selected);  
454            $('#ebook-data, #main, body').css('overflow-y', 'hidden');
455            $el.removeClass('hidden');
456        }, 450);
457        this.hidden = false;
458        $('#choose_theme').addClass('active');
459    },
460    hide: function(){
461        var $el = this.element;
462        if(this.isSafari) 
463            this.safariBugged.css({opacity: 0});
464        if(this.redactorDisabledZIndex){
465            var redactorDisabler = $('#redactor-disabler');
466            redactorDisabler.css('z-index', this.redactorDisabledZIndex);
467        }
468        $el.transition({x: 0, y: '-100%', duration: 400});
469        setTimeout(function(){
470            $el.hide();
471            $('#ebook-data, #main, body').css('overflow-y', '');
472            $el.addClass('hidden');
473        },430);
474        this.hidden = true;
475        $('#choose_theme').removeClass('active');
476        enableWindowScroll();
477    }
478};
479
480$(document).ready(function(){
481    ThemeChooser.init();
482    var params = parseQueryString() || {};
483    if(params.choose_theme){
484        ThemeChooser.show({animate: false});
485    }
486});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.