|
57 | 57 | CKEDITOR.plugins.add( 'elementspath', {
|
58 | 58 | lang: 'af,ar,bg,bn,bs,ca,cs,cy,da,de,el,en,en-au,en-ca,en-gb,eo,es,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
|
59 | 59 | init: function( editor ) {
|
| 60 | + editor._.elementsPath = { |
| 61 | + idBase: 'cke_elementspath_' + CKEDITOR.tools.getNextNumber() + '_', |
| 62 | + filters: [] |
| 63 | + }; |
| 64 | + |
60 | 65 | editor.on( 'uiSpace', function( event ) {
|
61 | 66 | if ( event.data.space == 'bottom' )
|
62 | 67 | initElementsPath( editor, event.data );
|
|
65 | 70 | } );
|
66 | 71 |
|
67 | 72 | function initElementsPath( editor, bottomSpaceData ) {
|
68 |
| - var spaceId = editor.ui.spaceId( 'path' ); |
69 |
| - var spaceElement; |
70 |
| - var getSpaceElement = function() { |
| 73 | + var spaceId = editor.ui.spaceId( 'path' ), |
| 74 | + spaceElement, |
| 75 | + getSpaceElement = function() { |
71 | 76 | if ( !spaceElement )
|
72 | 77 | spaceElement = CKEDITOR.document.getById( spaceId );
|
73 | 78 | return spaceElement;
|
74 |
| - }; |
75 |
| - |
76 |
| - var idBase = 'cke_elementspath_' + CKEDITOR.tools.getNextNumber() + '_'; |
77 |
| - |
78 |
| - editor._.elementsPath = { idBase: idBase, filters: [] }; |
| 79 | + }, |
| 80 | + elementsPath = editor._.elementsPath, |
| 81 | + idBase = elementsPath.idBase; |
79 | 82 |
|
80 | 83 | bottomSpaceData.html += '<span id="' + spaceId + '_label" class="cke_voice_label">' + editor.lang.elementspath.eleLabel + '</span>' +
|
81 | 84 | '<span id="' + spaceId + '" class="cke_path" role="group" aria-labelledby="' + spaceId + '_label">' + emptyHtml + '</span>';
|
|
87 | 90 | } );
|
88 | 91 |
|
89 | 92 | function onClick( elementIndex ) {
|
90 |
| - var element = editor._.elementsPath.list[ elementIndex ]; |
91 |
| - if ( element.equals( editor.editable() ) ) { |
| 93 | + var element = elementsPath.list[ elementIndex ]; |
| 94 | + if ( element.equals( editor.editable() ) || element.getAttribute( 'contenteditable' ) == 'true' ) { |
92 | 95 | var range = editor.createRange();
|
93 | 96 | range.selectNodeContents( element );
|
94 | 97 | range.select();
|
|
100 | 103 | editor.focus();
|
101 | 104 | }
|
102 | 105 |
|
103 |
| - var onClickHanlder = CKEDITOR.tools.addFunction( onClick ); |
104 |
| - |
105 |
| - var onKeyDownHandler = CKEDITOR.tools.addFunction( function( elementIndex, ev ) { |
106 |
| - var idBase = editor._.elementsPath.idBase, |
107 |
| - element; |
108 |
| - |
109 |
| - ev = new CKEDITOR.dom.event( ev ); |
110 |
| - |
111 |
| - var rtl = editor.lang.dir == 'rtl'; |
112 |
| - switch ( ev.getKeystroke() ) { |
113 |
| - case rtl ? 39: |
114 |
| - 37 : // LEFT-ARROW |
115 |
| - case 9: // TAB |
116 |
| - element = CKEDITOR.document.getById( idBase + ( elementIndex + 1 ) ); |
117 |
| - if ( !element ) |
118 |
| - element = CKEDITOR.document.getById( idBase + '0' ); |
119 |
| - element.focus(); |
120 |
| - return false; |
121 |
| - |
122 |
| - case rtl ? 37: |
123 |
| - 39 : // RIGHT-ARROW |
124 |
| - case CKEDITOR.SHIFT + 9: // SHIFT + TAB |
125 |
| - element = CKEDITOR.document.getById( idBase + ( elementIndex - 1 ) ); |
126 |
| - if ( !element ) |
127 |
| - element = CKEDITOR.document.getById( idBase + ( editor._.elementsPath.list.length - 1 ) ); |
128 |
| - element.focus(); |
129 |
| - return false; |
130 |
| - |
131 |
| - case 27: // ESC |
132 |
| - editor.focus(); |
133 |
| - return false; |
134 |
| - |
135 |
| - case 13: // ENTER // Opera |
136 |
| - case 32: // SPACE |
137 |
| - onClick( elementIndex ); |
138 |
| - return false; |
139 |
| - } |
140 |
| - return true; |
141 |
| - } ); |
| 106 | + elementsPath.onClick = onClick; |
| 107 | + |
| 108 | + var onClickHanlder = CKEDITOR.tools.addFunction( onClick ), |
| 109 | + onKeyDownHandler = CKEDITOR.tools.addFunction( function( elementIndex, ev ) { |
| 110 | + var idBase = elementsPath.idBase, |
| 111 | + element; |
| 112 | + |
| 113 | + ev = new CKEDITOR.dom.event( ev ); |
| 114 | + |
| 115 | + var rtl = editor.lang.dir == 'rtl'; |
| 116 | + switch ( ev.getKeystroke() ) { |
| 117 | + case rtl ? 39: |
| 118 | + 37 : // LEFT-ARROW |
| 119 | + case 9: // TAB |
| 120 | + element = CKEDITOR.document.getById( idBase + ( elementIndex + 1 ) ); |
| 121 | + if ( !element ) |
| 122 | + element = CKEDITOR.document.getById( idBase + '0' ); |
| 123 | + element.focus(); |
| 124 | + return false; |
| 125 | + |
| 126 | + case rtl ? 37: |
| 127 | + 39 : // RIGHT-ARROW |
| 128 | + case CKEDITOR.SHIFT + 9: // SHIFT + TAB |
| 129 | + element = CKEDITOR.document.getById( idBase + ( elementIndex - 1 ) ); |
| 130 | + if ( !element ) |
| 131 | + element = CKEDITOR.document.getById( idBase + ( elementsPath.list.length - 1 ) ); |
| 132 | + element.focus(); |
| 133 | + return false; |
| 134 | + |
| 135 | + case 27: // ESC |
| 136 | + editor.focus(); |
| 137 | + return false; |
| 138 | + |
| 139 | + case 13: // ENTER // Opera |
| 140 | + case 32: // SPACE |
| 141 | + onClick( elementIndex ); |
| 142 | + return false; |
| 143 | + } |
| 144 | + return true; |
| 145 | + } ); |
142 | 146 |
|
143 | 147 | editor.on( 'selectionChange', function( ev ) {
|
144 | 148 | var env = CKEDITOR.env,
|
145 | 149 | editable = editor.editable(),
|
146 | 150 | selection = ev.data.selection,
|
147 |
| - element = selection.getStartElement(), |
148 | 151 | html = [],
|
149 |
| - elementsList = editor._.elementsPath.list = [], |
150 |
| - filters = editor._.elementsPath.filters; |
151 |
| - |
152 |
| - while ( element ) { |
153 |
| - var ignore = 0, |
154 |
| - name; |
| 152 | + elementsList = elementsPath.list = [], |
| 153 | + namesList = [], |
| 154 | + filters = elementsPath.filters, |
| 155 | + isContentEditable = true, |
| 156 | + name, |
| 157 | + elementsChain = selection.getStartElement().getParents(), |
| 158 | + chainLength = elementsChain.length; |
| 159 | + |
| 160 | + // Starts iteration from body element, skipping html. |
| 161 | + for ( var j = 1; j < chainLength; j++ ) { |
| 162 | + var element = elementsChain[ j ], |
| 163 | + ignore = 0; |
155 | 164 |
|
156 | 165 | if ( element.data( 'cke-display-name' ) )
|
157 | 166 | name = element.data( 'cke-display-name' );
|
|
160 | 169 | else
|
161 | 170 | name = element.getName();
|
162 | 171 |
|
| 172 | + isContentEditable = element.hasAttribute( 'contenteditable' ) ? |
| 173 | + element.getAttribute( 'contenteditable' ) == 'true' : isContentEditable; |
| 174 | + |
| 175 | + // If elem is non-contenteditable, and it's not specifying contenteditable |
| 176 | + // attribute - then elem should be ignored. |
| 177 | + if ( !isContentEditable && !element.hasAttribute( 'contenteditable' ) ) |
| 178 | + ignore = 1; |
| 179 | + |
163 | 180 | for ( var i = 0; i < filters.length; i++ ) {
|
164 | 181 | var ret = filters[ i ]( element, name );
|
165 | 182 | if ( ret === false ) {
|
|
170 | 187 | }
|
171 | 188 |
|
172 | 189 | if ( !ignore ) {
|
173 |
| - var index = elementsList.push( element ) - 1, |
174 |
| - label = editor.lang.elementspath.eleTitle.replace( /%1/, name ); |
| 190 | + elementsList.unshift( element ); |
| 191 | + namesList.unshift( name ); |
| 192 | + } |
| 193 | + } |
175 | 194 |
|
176 |
| - var item = pathItemTpl.output({ |
| 195 | + for ( var iterationLimit = elementsList.length, index = 0; index < iterationLimit; index++ ) { |
| 196 | + name = namesList[ index ]; |
| 197 | + var label = editor.lang.elementspath.eleTitle.replace( /%1/, name ), |
| 198 | + item = pathItemTpl.output( { |
177 | 199 | id: idBase + index,
|
178 | 200 | label: label,
|
179 | 201 | text: name,
|
|
182 | 204 | keyDownFn: onKeyDownHandler,
|
183 | 205 | clickFn: onClickHanlder
|
184 | 206 | } );
|
185 |
| - html.unshift( item ); |
186 |
| - |
187 |
| - } |
188 |
| - |
189 |
| - if ( element.equals( editable ) ) |
190 |
| - break; |
191 | 207 |
|
192 |
| - element = element.getParent(); |
| 208 | + html.unshift( item ); |
193 | 209 | }
|
194 | 210 |
|
195 | 211 | var space = getSpaceElement();
|
|
199 | 215 |
|
200 | 216 | function empty() {
|
201 | 217 | spaceElement && spaceElement.setHtml( emptyHtml );
|
202 |
| - delete editor._.elementsPath.list; |
| 218 | + delete elementsPath.list; |
203 | 219 | }
|
204 | 220 |
|
205 | 221 | editor.on( 'readOnly', empty );
|
|
0 commit comments