376d2bc3c4b7b8c23f8cbc2c26a2d5cf36c6146f
[freeside.git] / httemplate / elements / ckeditor / plugins / blockprotect / plugin.js
1 /**
2  * The "blockprotect" plugin.  Adapted from the "placeholder" plugin.
3  */
4
5 (function() {
6         var delim_o = '{';
7         var delim_c = '}';
8
9         var create_block = function(content, inside) {
10           // fix nbsp's
11           content = content.replace(/ /gi, ' ');
12           // escape the content
13           var el = document.createElement('SPAN');
14           // IE8 compat
15           if( typeof(el.textContent) != 'undefined' ) {
16             el.textContent = content;
17           } else if( typeof(el.innerText) != 'undefined' ) {
18             el.innerText = content;
19           }
20           el.setAttribute('class', 'cke_blockprotect');
21           if (inside) {
22             return el.innerHTML; // escapes the contents but doesn't wrap
23                                  // them in a <span>
24           } else {
25             return el.outerHTML;
26           }
27         };
28         var block_writeHtml = function( element ) {
29           // to unescape the element contents, write it out as HTML,
30           // stick that into a SPAN element, and then extract the text
31           // content of that.
32           var inner_writer = new CKEDITOR.htmlParser.basicWriter;
33           element.writeChildrenHtml(inner_writer);
34
35           var el = document.createElement('SPAN');
36           el.innerHTML = inner_writer.getHtml();
37           if( typeof(el.textContent) != 'undefined' ) {
38             return el.textContent;
39           } else if( typeof(el.innerText) != 'undefined' ) {
40             return el.innerText;
41           }
42         };
43         var to_protected_html = function(data) {
44           var depth = 0;
45           var chunk = '';
46           var out = '';
47           var in_tag = false;
48           var p = 0; // position in the string
49           while( 1 ) {
50             // find the next delimiter of either kind
51             var i = data.indexOf(delim_o, p);
52             var j = data.indexOf(delim_c, p);
53             if (i == -1 && j == -1) {
54               // then there are no more delimiters
55               break;
56             } else if ((i < j || j == -1) && i != -1) {
57               // next delimiter is an open
58               // push everything from current position to 
59               // the delimiter
60               if ( i > p ) chunk += data.substr(p, i - p);
61               p = i + 1;
62               if ( depth == 0 ) {
63                 // we're in document text. find whether an HTML tag starts, 
64                 // or ends, before the next delimiter, so that we know whether
65                 // to output the next block in a SPAN or just as escaped text
66                 for(var q = 0; q < chunk.length; q++ ) {
67                   if (chunk[q] == '<') in_tag = true;
68                   if (chunk[q] == '>') in_tag = false;
69                 }
70
71                 // then output the chunk, and go to the start of the 
72                 // protected block
73                 out += chunk;
74                 chunk = '';
75               }
76               chunk += delim_o;
77               depth++;
78             } else if ((j < i || i == -1) && j != -1) {
79               // next delimiter is a close
80               if ( j > p ) chunk += data.substr(p, j - p);
81               p = j + 1;
82               depth--;
83               chunk += delim_c;
84               if ( depth == 0 ) {
85                 // end of a protected block
86                 out += create_block(chunk, in_tag);
87                 chunk = '';
88               } else if ( depth < 0 ) {
89                 depth = 0;
90               }
91             } else {
92               // can't happen
93             }
94           }
95           // append any text after the last delimiter
96           if ( depth ) {
97             out += create_block(data.substr(p), in_tag);
98           } else {
99             out += data.substr(p);
100           }
101           return out;
102         };
103
104         CKEDITOR.plugins.add( 'blockprotect', {
105                 afterInit: function( editor ) {
106                         CKEDITOR.addCss( '.cke_blockprotect' +
107                         '{' +
108                                         'background-color: #ffff88;' +
109                                         ( CKEDITOR.env.gecko ? 'cursor: default;' : '' ) +
110                                 '}'
111                         );
112                       
113                         // keep these from getting stripped out 
114                         editor.filter.allow('span(cke_blockprotect)',
115                                             'blockprotect', true);
116
117                         // add filter at the front of toHtml
118                         editor.on( 'toHtml',
119                           function( evt ) {
120                             evt.data.dataValue =
121                               to_protected_html(evt.data.dataValue);
122                             return evt;
123                           },
124                           this, null, 0
125                         );
126
127                         editor.dataProcessor.htmlFilter.addRules({
128                           elements: {
129                             span: function( element ) {
130                               if ( element.className = 'cke_blockprotect' ) {
131                                 // defeat HTML escaping
132                                 var content = block_writeHtml(element);
133                                 element.writeHtml = function(writer, filter) {
134                                   writer.text(content);
135                                 }
136                               }
137                             } // span function
138                           } // elements
139                         });
140                 }
141         }); // plugins.add
142 }) ();
143