~jstys-z/helioviewer.org/timeline

« back to all changes in this revision

Viewing changes to timeline/Highstock-1.3.10/exporting-server/java/highcharts-export/highcharts-export-web/src/main/webapp/resources/lib/codemirror/util/closetag.js

  • Committer: Jeff Stys
  • Date: 2014-04-21 12:46:26 UTC
  • Revision ID: jstys@sesda3.com-20140421124626-2332pb2dyjc33jxi
Proof-of-concept version of Data Coverage Timeline using Highchart/Highstock javascript library.  Changes to getDataCoverage API in order to feed the necessary data to the Timeline

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * Tag-closer extension for CodeMirror.
 
3
 *
 
4
 * This extension adds a "closeTag" utility function that can be used with key bindings to 
 
5
 * insert a matching end tag after the ">" character of a start tag has been typed.  It can
 
6
 * also complete "</" if a matching start tag is found.  It will correctly ignore signal
 
7
 * characters for empty tags, comments, CDATA, etc.
 
8
 *
 
9
 * The function depends on internal parser state to identify tags.  It is compatible with the
 
10
 * following CodeMirror modes and will ignore all others:
 
11
 * - htmlmixed
 
12
 * - xml
 
13
 *
 
14
 * See demos/closetag.html for a usage example.
 
15
 * 
 
16
 * @author Nathan Williams <nathan@nlwillia.net>
 
17
 * Contributed under the same license terms as CodeMirror.
 
18
 */
 
19
(function() {
 
20
        /** Option that allows tag closing behavior to be toggled.  Default is true. */
 
21
        CodeMirror.defaults['closeTagEnabled'] = true;
 
22
        
 
23
        /** Array of tag names to add indentation after the start tag for.  Default is the list of block-level html tags. */
 
24
        CodeMirror.defaults['closeTagIndent'] = ['applet', 'blockquote', 'body', 'button', 'div', 'dl', 'fieldset', 'form', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'html', 'iframe', 'layer', 'legend', 'object', 'ol', 'p', 'select', 'table', 'ul'];
 
25
 
 
26
        /** Array of tag names where an end tag is forbidden. */
 
27
        CodeMirror.defaults['closeTagVoid'] = ['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'];
 
28
 
 
29
        function innerState(cm, state) {
 
30
                return CodeMirror.innerMode(cm.getMode(), state).state;
 
31
        }
 
32
 
 
33
 
 
34
        /**
 
35
         * Call during key processing to close tags.  Handles the key event if the tag is closed, otherwise throws CodeMirror.Pass.
 
36
         * - cm: The editor instance.
 
37
         * - ch: The character being processed.
 
38
         * - indent: Optional.  An array of tag names to indent when closing.  Omit or pass true to use the default indentation tag list defined in the 'closeTagIndent' option.
 
39
         *   Pass false to disable indentation.  Pass an array to override the default list of tag names.
 
40
         * - vd: Optional.  An array of tag names that should not be closed.  Omit to use the default void (end tag forbidden) tag list defined in the 'closeTagVoid' option.  Ignored in xml mode.
 
41
         */
 
42
        CodeMirror.defineExtension("closeTag", function(cm, ch, indent, vd) {
 
43
                if (!cm.getOption('closeTagEnabled')) {
 
44
                        throw CodeMirror.Pass;
 
45
                }
 
46
                
 
47
                /*
 
48
                 * Relevant structure of token:
 
49
                 *
 
50
                 * htmlmixed
 
51
                 *              className
 
52
                 *              state
 
53
                 *                      htmlState
 
54
                 *                              type
 
55
                 *                              tagName
 
56
                 *                              context
 
57
                 *                                      tagName
 
58
                 *                      mode
 
59
                 * 
 
60
                 * xml
 
61
                 *              className
 
62
                 *              state
 
63
                 *                      tagName
 
64
                 *                      type
 
65
                 */
 
66
                
 
67
                var pos = cm.getCursor();
 
68
                var tok = cm.getTokenAt(pos);
 
69
                var state = innerState(cm, tok.state);
 
70
 
 
71
                if (state) {
 
72
                        
 
73
                        if (ch == '>') {
 
74
                                var type = state.type;
 
75
                                
 
76
                                if (tok.className == 'tag' && type == 'closeTag') {
 
77
                                        throw CodeMirror.Pass; // Don't process the '>' at the end of an end-tag.
 
78
                                }
 
79
                        
 
80
                                cm.replaceSelection('>'); // Mode state won't update until we finish the tag.
 
81
                                pos = {line: pos.line, ch: pos.ch + 1};
 
82
                                cm.setCursor(pos);
 
83
                
 
84
                                tok = cm.getTokenAt(cm.getCursor());
 
85
                                state = innerState(cm, tok.state);
 
86
                                if (!state) throw CodeMirror.Pass;
 
87
                                var type = state.type;
 
88
 
 
89
                                if (tok.className == 'tag' && type != 'selfcloseTag') {
 
90
                                        var tagName = state.tagName;
 
91
                                        if (tagName.length > 0 && shouldClose(cm, vd, tagName)) {
 
92
                                                insertEndTag(cm, indent, pos, tagName);
 
93
                                        }
 
94
                                        return;
 
95
                                }
 
96
                                
 
97
                                // Undo the '>' insert and allow cm to handle the key instead.
 
98
                                cm.setSelection({line: pos.line, ch: pos.ch - 1}, pos);
 
99
                                cm.replaceSelection("");
 
100
                        
 
101
                        } else if (ch == '/') {
 
102
                                if (tok.className == 'tag' && tok.string == '<') {
 
103
                                        var ctx = state.context, tagName = ctx ? ctx.tagName : '';
 
104
                                        if (tagName.length > 0) {
 
105
                                                completeEndTag(cm, pos, tagName);
 
106
                                                return;
 
107
                                        }
 
108
                                }
 
109
                        }
 
110
                
 
111
                }
 
112
                
 
113
                throw CodeMirror.Pass; // Bubble if not handled
 
114
        });
 
115
 
 
116
        function insertEndTag(cm, indent, pos, tagName) {
 
117
                if (shouldIndent(cm, indent, tagName)) {
 
118
                        cm.replaceSelection('\n\n</' + tagName + '>', 'end');
 
119
                        cm.indentLine(pos.line + 1);
 
120
                        cm.indentLine(pos.line + 2);
 
121
                        cm.setCursor({line: pos.line + 1, ch: cm.getLine(pos.line + 1).length});
 
122
                } else {
 
123
                        cm.replaceSelection('</' + tagName + '>');
 
124
                        cm.setCursor(pos);
 
125
                }
 
126
        }
 
127
        
 
128
        function shouldIndent(cm, indent, tagName) {
 
129
                if (typeof indent == 'undefined' || indent == null || indent == true) {
 
130
                        indent = cm.getOption('closeTagIndent');
 
131
                }
 
132
                if (!indent) {
 
133
                        indent = [];
 
134
                }
 
135
                return indexOf(indent, tagName.toLowerCase()) != -1;
 
136
        }
 
137
        
 
138
        function shouldClose(cm, vd, tagName) {
 
139
                if (cm.getOption('mode') == 'xml') {
 
140
                        return true; // always close xml tags
 
141
                }
 
142
                if (typeof vd == 'undefined' || vd == null) {
 
143
                        vd = cm.getOption('closeTagVoid');
 
144
                }
 
145
                if (!vd) {
 
146
                        vd = [];
 
147
                }
 
148
                return indexOf(vd, tagName.toLowerCase()) == -1;
 
149
        }
 
150
        
 
151
        // C&P from codemirror.js...would be nice if this were visible to utilities.
 
152
        function indexOf(collection, elt) {
 
153
                if (collection.indexOf) return collection.indexOf(elt);
 
154
                for (var i = 0, e = collection.length; i < e; ++i)
 
155
                        if (collection[i] == elt) return i;
 
156
                return -1;
 
157
        }
 
158
 
 
159
        function completeEndTag(cm, pos, tagName) {
 
160
                cm.replaceSelection('/' + tagName + '>');
 
161
                cm.setCursor({line: pos.line, ch: pos.ch + tagName.length + 2 });
 
162
        }
 
163
        
 
164
})();