47c33f41d2314ea1200dda399930b1e83bec1a7b
[odoo/odoo.git] / doc / _themes / odoodoc / static / app.js
1 $(function () {
2     var $body = $(document.body);
3     $body.scrollspy({ target: '.sphinxsidebarwrapper' });
4     $(window).on('load', function () {
5         $body.scrollspy('refresh');
6     });
7
8     // Sidenav affixing
9     setTimeout(function () {
10         var $sideBar = $('.sphinxsidebarwrapper');
11
12         $sideBar.affix({
13             offset: {
14                 top: function () {
15                     var offsetTop = $sideBar.offset().top;
16                     var sideBarMargin = parseInt($sideBar.children(0).css('margin-top'), 10);
17                     var navOuterHeight = $('.docs-nav').height();
18
19                     return (this.top = offsetTop - navOuterHeight - sideBarMargin);
20                 },
21                 bottom: function () {
22                     return (this.bottom = $('div.footer').outerHeight(true));
23                 }
24             }
25         });
26     }, 100);
27
28     /*
29     for clipboard:
30     * add per-language setup code to document, hidden
31     * adds button to each switchable language block except when they're setup
32       stuff because fuck'em
33     * per-language, add clipboard hook to prefix with setup bit on-copy
34     * setup bit is... ?
35     * actually not all blocks because we don't want to add the setup bits to
36       the setup bits, so that's kinda shit
37      */
38
39     document.addEventListener('copy', copyCode);
40
41     ZeroClipboard.config({
42         swfPath: '../_static/zeroclipboard-2.1.6/ZeroClipboard.swf',
43         flashLoadTimeout: 3e3,
44     });
45     var zc = new ZeroClipboard();
46     zc.on('ready', function () {
47         var $highlighted = $('.switchable:not(.setup) .highlight').addClass('with-btn-clipboard');
48         var $clipboard_buttons =
49             $('<button type="button" class="btn-clipboard">Copy</button>')
50             .on('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function () {
51                 $(this).removeClass('active');
52             })
53             .prependTo($highlighted);
54         zc.clip($clipboard_buttons);
55     });
56     zc.on('copy', function (e) {
57         // yellow flash
58         $(e.target).addClass('active');
59         copyCode(e);
60     });
61
62     // stripe page stuff
63     if ($('div.document-super').hasClass('stripe')) { (function () {
64         // iterate on highlighted PL blocks (but not results because that'd
65         // be gross), extract all switchable PLs in the document and add
66         // clipboard-copy buttons
67         var languages = {};
68         $('div.switchable').each(function () {
69             var language = getHighlightLanguage(this);
70             if (language) {
71                 languages[language] = true;
72             }
73         });
74
75         // if can't find CSS where base rule lives something's probably
76         // broken, bail
77         var sheet = findSheet(/style\.css$/);
78         if (!sheet) { return; }
79         // build PL switcher UI and hook toggle event
80         $(buildSwitcher(Object.keys(languages)))
81             .prependTo('div.documentwrapper')
82             .on('click', 'li', function (e) {
83                 $(e.target).addClass('active')
84                     .siblings().removeClass('active');
85                 var id = e.target.textContent;
86                 var lastIndex = sheet.cssRules.length - 1;
87                 var content = sheet.cssRules[lastIndex].style.cssText;
88                 // change rule in CSS because why not (also can add new
89                 // languages without having to e.g. change CSS or anything)
90                 var sel = [
91                     '.stripe .only-', id, ', ',
92                     '.stripe .highlight-', id, ' > .highlight'
93                 ].join('');
94                 sheet.deleteRule(lastIndex);
95                 sheet.insertRule(sel + '{' + content + '}', lastIndex);
96         });
97     })(); }
98
99
100     function copyCode(e) {
101         // works for both C-c and "Copy" button if copy button is injected
102         // inside highlighted code section
103         var target = $(e.target).closest('.switchable:not(.setup)').get(0);
104         // not in a switchable
105         if (!target) { return; }
106         var lang = getHighlightLanguage(target);
107         if (!lang) {
108             // switchable without highlight (e.g. language-specific notes),
109             // don't munge
110             return;
111         }
112
113         // get generic setup code
114         var setup_selector = '.setupcode.highlight-' + lang + ' pre';
115         var setup = document.querySelector(setup_selector).textContent;
116
117         // prepend setup code to current snippet, get all of current snippet
118         // in case only part of it was selected. Ensure we don't get e.g.
119         // button text around snippet itself
120         var data = setup + '\n' + target.querySelector('pre').textContent;
121         // sane browsers & ZeroClipboard
122         e.clipboardData.setData('text/plain', data);
123         // MSIE
124         e.clipboardData.setData('Text', data);
125
126         // no preventDefault on ZC event
127         e.preventDefault && e.preventDefault();
128     }
129     /**
130      * @param {Node} node highlight node to get the language of
131      * @returns {String|null} either the highlight language or null
132      */
133     function getHighlightLanguage(node) {
134         var classes = node.className.split(/\s+/);
135         for (var i = 0; i < classes.length; ++i) {
136             var cls = classes[i];
137             if (/^highlight-/.test(cls)) {
138                 return cls.slice(10);
139             }
140         }
141         return null;
142     }
143     // programming language switcher
144     function findSheet(pattern, fromSheet) {
145         if (fromSheet) {
146             for(var i=0; i<fromSheet.cssRules.length; ++i) {
147                 var rule = fromSheet.cssRules[i];
148                 if (rule.type !== CSSRule.IMPORT_RULE) { continue; }
149                 if (pattern.test(rule.href)) {
150                     return rule.styleSheet;
151                 }
152             }
153             return null;
154         }
155         var sheets = document.styleSheets;
156         for(var j=0; j<sheets.length; ++j) {
157             var sheet = sheets[j];
158             if (pattern.test(sheet.href)) {
159                 return sheet;
160             }
161             var subSheet;
162             if (subSheet = findSheet(pattern, sheet)) {
163                 return subSheet;
164             }
165         }
166         return null;
167     }
168     function buildSwitcher(languages) {
169         var root = document.createElement('ul');
170         root.className = "switcher";
171         for(var i=0; i<languages.length; ++i) {
172             var item = document.createElement('li');
173             item.textContent = languages[i];
174             if (i === 0) {
175                 item.className = "active";
176             }
177             root.appendChild(item);
178         }
179         return root;
180     }
181 });