xref: /plugin/fontello/script.js (revision e9d41e7da8510f70fdfbcdbad2e81c1515775d3d)
1(function () {
2    'use strict';
3
4    var iconTokenPattern = /<icon:([A-Za-z0-9_-]+)(?:\|(toc|notoc))?>/g;
5
6    function getFontelloInfo() {
7        if (!window.JSINFO || !window.JSINFO.plugin_fontello) return null;
8        return window.JSINFO.plugin_fontello;
9    }
10
11    function tokenShowsInToc(flag, info) {
12        if (flag === 'notoc') return false;
13        if (flag === 'toc') return true;
14
15        return !!info.showInToc;
16    }
17
18    function createIconSpan(cssClass) {
19        var span = document.createElement('span');
20        span.className = 'fontello-icon ' + cssClass;
21        span.setAttribute('aria-hidden', 'true');
22        return span;
23    }
24
25    function replaceTextNodeTokens(textNode, info) {
26        var text = textNode.nodeValue;
27        var fragment = document.createDocumentFragment();
28        var lastIndex = 0;
29        var changed = false;
30        var match;
31
32        iconTokenPattern.lastIndex = 0;
33        while ((match = iconTokenPattern.exec(text)) !== null) {
34            var raw = match[0];
35            var name = match[1];
36            var flag = match[2] || '';
37            var cssClass = info.icons && info.icons[name];
38            var visible = tokenShowsInToc(flag, info);
39
40            if (match.index > lastIndex) {
41                fragment.appendChild(document.createTextNode(text.slice(lastIndex, match.index)));
42            }
43
44            if (cssClass && visible) {
45                fragment.appendChild(createIconSpan(cssClass));
46                changed = true;
47            } else if (cssClass) {
48                changed = true;
49            } else {
50                fragment.appendChild(document.createTextNode(raw));
51            }
52
53            lastIndex = match.index + raw.length;
54        }
55
56        if (!changed) return;
57        if (lastIndex < text.length) {
58            fragment.appendChild(document.createTextNode(text.slice(lastIndex)));
59        }
60
61        textNode.parentNode.replaceChild(fragment, textNode);
62    }
63
64    function replaceTocLinkTokens(link, info) {
65        var walker = document.createTreeWalker(link, NodeFilter.SHOW_TEXT, null, false);
66        var nodes = [];
67        var node;
68
69        while ((node = walker.nextNode()) !== null) {
70            if (node.nodeValue.indexOf('<icon:') !== -1) {
71                nodes.push(node);
72            }
73        }
74
75        nodes.forEach(function (textNode) {
76            replaceTextNodeTokens(textNode, info);
77        });
78    }
79
80    function renderTocIcons() {
81        var info = getFontelloInfo();
82        if (!info || !info.icons) return;
83
84        Array.prototype.forEach.call(document.querySelectorAll('#dw__toc a'), function (link) {
85            replaceTocLinkTokens(link, info);
86        });
87    }
88
89    function scheduleTocIconRendering() {
90        window.setTimeout(renderTocIcons, 0);
91    }
92
93    if (document.readyState === 'loading') {
94        document.addEventListener('DOMContentLoaded', scheduleTocIconRendering);
95    } else {
96        scheduleTocIconRendering();
97    }
98
99    window.addBtnActionFontello = function ($btn, props, edid) {
100        if (!props.list || !props.list.length) return '';
101
102        var pickerid = 'picker' + (pickercounter++);
103        var $picker = jQuery(document.createElement('div'))
104            .addClass('picker a11y pk_fontello')
105            .attr('id', pickerid)
106            .attr('aria-hidden', 'true')
107            .css('position', 'absolute')
108            .removeAttr('hidden');
109
110        jQuery.each(props.list, function (_, icon) {
111            var name = icon.name || '';
112            var cssClass = icon['class'] || '';
113            var insert = icon.insert || '<icon:' + name + '>';
114            if (!name || !cssClass) return;
115
116            jQuery(document.createElement('button'))
117                .addClass('pickerbutton fontello-picker-button')
118                .attr('type', 'button')
119                .attr('title', name)
120                .attr('aria-label', name)
121                .attr('aria-controls', edid)
122                .on('click', function (event) {
123                    insertAtCarret(edid, insert);
124                    pickerClose();
125                    event.preventDefault();
126                })
127                .append(
128                    jQuery(document.createElement('span'))
129                        .addClass('fontello-icon ' + cssClass)
130                        .attr('aria-hidden', 'true')
131                )
132                .appendTo($picker);
133        });
134
135        jQuery('body').append($picker);
136
137        $btn.on('click', function (event) {
138            pickerToggle(pickerid, $btn);
139            $picker.removeAttr('hidden').prop('hidden', false);
140            event.preventDefault();
141        });
142
143        return pickerid;
144    };
145}());
146