]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-includes/js/tinymce/plugins/wptextpattern/plugin.js
WordPress 4.3
[autoinstalls/wordpress.git] / wp-includes / js / tinymce / plugins / wptextpattern / plugin.js
1 /**
2  * Text pattern plugin for TinyMCE
3  *
4  * @since 4.3.0
5  *
6  * This plugin can automatically format text patterns as you type. It includes two patterns:
7  *  - Unordered list (`* ` and `- `).
8  *  - Ordered list (`1. ` and `1) `).
9  *
10  * If the transformation in unwanted, the user can undo the change by pressing backspace,
11  * using the undo shortcut, or the undo button in the toolbar.
12  */
13 ( function( tinymce, setTimeout ) {
14         tinymce.PluginManager.add( 'wptextpattern', function( editor ) {
15                 var VK = tinymce.util.VK,
16                         spacePatterns = [
17                                 { regExp: /^[*-]\s/, cmd: 'InsertUnorderedList' },
18                                 { regExp: /^1[.)]\s/, cmd: 'InsertOrderedList' }
19                         ],
20                         enterPatterns = [
21                                 { start: '##', format: 'h2' },
22                                 { start: '###', format: 'h3' },
23                                 { start: '####', format: 'h4' },
24                                 { start: '#####', format: 'h5' },
25                                 { start: '######', format: 'h6' },
26                                 { start: '>', format: 'blockquote' }
27                         ],
28                         canUndo, refNode, refPattern;
29
30                 editor.on( 'selectionchange', function() {
31                         canUndo = null;
32                 } );
33
34                 editor.on( 'keydown', function( event ) {
35                         if ( ( canUndo && event.keyCode === 27 /* ESCAPE */ ) || ( canUndo === 'space' && event.keyCode === VK.BACKSPACE ) ) {
36                                 editor.undoManager.undo();
37                                 event.preventDefault();
38                                 event.stopImmediatePropagation();
39                         }
40
41                         if ( event.keyCode === VK.ENTER && ! VK.modifierPressed( event ) ) {
42                                 watchEnter();
43                         }
44                 }, true );
45
46                 editor.on( 'keyup', function( event ) {
47                         if ( event.keyCode === VK.SPACEBAR && ! event.ctrlKey && ! event.metaKey && ! event.altKey ) {
48                                 space();
49                         } else if ( event.keyCode === VK.ENTER && ! VK.modifierPressed( event ) ) {
50                                 enter();
51                         }
52                 } );
53
54                 function firstTextNode( node ) {
55                         var parent = editor.dom.getParent( node, 'p' ),
56                                 child;
57
58                         if ( ! parent ) {
59                                 return;
60                         }
61
62                         while ( child = parent.firstChild ) {
63                                 if ( child.nodeType !== 3 ) {
64                                         parent = child;
65                                 } else {
66                                         break;
67                                 }
68                         }
69
70                         if ( ! child ) {
71                                 return;
72                         }
73
74                         if ( ! child.data ) {
75                                 if ( child.nextSibling && child.nextSibling.nodeType === 3 ) {
76                                         child = child.nextSibling;
77                                 } else {
78                                         child = null;
79                                 }
80                         }
81
82                         return child;
83                 }
84
85                 function space() {
86                         var rng = editor.selection.getRng(),
87                                 node = rng.startContainer,
88                                 parent,
89                                 text;
90
91                         if ( ! node || firstTextNode( node ) !== node ) {
92                                 return;
93                         }
94
95                         parent = node.parentNode;
96                         text = node.data;
97
98                         tinymce.each( spacePatterns, function( pattern ) {
99                                 var match = text.match( pattern.regExp );
100
101                                 if ( ! match || rng.startOffset !== match[0].length ) {
102                                         return;
103                                 }
104
105                                 editor.undoManager.add();
106
107                                 editor.undoManager.transact( function() {
108                                         node.deleteData( 0, match[0].length );
109
110                                         if ( ! parent.innerHTML ) {
111                                                 parent.appendChild( document.createElement( 'br' ) );
112                                         }
113
114                                         editor.selection.setCursorLocation( parent );
115                                         editor.execCommand( pattern.cmd );
116                                 } );
117
118                                 // We need to wait for native events to be triggered.
119                                 setTimeout( function() {
120                                         canUndo = 'space';
121                                 } );
122
123                                 return false;
124                         } );
125                 }
126
127                 function watchEnter() {
128                         var rng = editor.selection.getRng(),
129                                 start = rng.startContainer,
130                                 node = firstTextNode( start ),
131                                 i = enterPatterns.length,
132                                 text, pattern;
133
134                         if ( ! node ) {
135                                 return;
136                         }
137
138                         text = node.data;
139
140                         while ( i-- ) {
141                                  if ( text.indexOf( enterPatterns[ i ].start ) === 0 ) {
142                                         pattern = enterPatterns[ i ];
143                                         break;
144                                  }
145                         }
146
147                         if ( ! pattern ) {
148                                 return;
149                         }
150
151                         if ( node === start && tinymce.trim( text ) === pattern.start ) {
152                                 return;
153                         }
154
155                         refNode = node;
156                         refPattern = pattern;
157                 }
158
159                 function enter() {
160                         if ( refNode ) {
161                                 editor.undoManager.add();
162
163                                 editor.undoManager.transact( function() {
164                                         editor.formatter.apply( refPattern.format, {}, refNode );
165                                         refNode.replaceData( 0, refNode.data.length, tinymce.trim( refNode.data.slice( refPattern.start.length ) ) );
166                                 } );
167
168                                 // We need to wait for native events to be triggered.
169                                 setTimeout( function() {
170                                         canUndo = 'enter';
171                                 } );
172                         }
173
174                         refNode = null;
175                         refPattern = null;
176                 }
177         } );
178 } )( window.tinymce, window.setTimeout );