(bug 26265) Many semicolons are missing from JavaScript files
[lhc/web/wiklou.git] / skins / common / edit.js
1 window.currentFocused = undefined;
2
3 // this function adds a toolbar button to the mwEditButtons list
4 window.addButton = function( imageFile, speedTip, tagOpen, tagClose, sampleText, imageId ) {
5 // Don't generate buttons for browsers which don't fully
6 // support it.
7 mwEditButtons.push({
8 'imageId': imageId,
9 'imageFile': imageFile,
10 'speedTip': speedTip,
11 'tagOpen': tagOpen,
12 'tagClose': tagClose,
13 'sampleText': sampleText
14 });
15 };
16
17 // this function adds one toolbar button from a mwEditButtons/mwCustomEditButtons item
18 window.mwInsertEditButton = function( parent, item ) {
19 var image = document.createElement( 'img' );
20 image.width = 23;
21 image.height = 22;
22 image.className = 'mw-toolbar-editbutton';
23 if ( item.imageId ) {
24 image.id = item.imageId;
25 }
26 image.src = item.imageFile;
27 image.border = 0;
28 image.alt = item.speedTip;
29 image.title = item.speedTip;
30 image.style.cursor = 'pointer';
31 image.onclick = function() {
32 insertTags( item.tagOpen, item.tagClose, item.sampleText );
33 // click tracking
34 if ( ( typeof $ != 'undefined' ) && ( typeof $.trackAction != 'undefined' ) ) {
35 $.trackAction( 'oldedit.' + item.speedTip.replace(/ /g, "-") );
36 }
37 return false;
38 };
39
40 parent.appendChild( image );
41 return true;
42 };
43
44 // this function generates the actual toolbar buttons with localized text
45 // we use it to avoid creating the toolbar where javascript is not enabled
46 window.mwSetupToolbar = function() {
47 var toolbar = document.getElementById( 'toolbar' );
48 if ( !toolbar ) {
49 return false;
50 }
51
52 // Don't generate buttons for browsers which don't fully
53 // support it.
54 // but don't assume wpTextbox1 is always here
55 var textboxes = document.getElementsByTagName( 'textarea' );
56 if ( !textboxes.length ) {
57 // No toolbar if we can't find any textarea
58 return false;
59 }
60 // Only check for selection capability if the textarea is visible - errors will occur otherwise - just because
61 // the textarea is not visible, doesn't mean we shouldn't build out the toolbar though - it might have been replaced
62 // with some other kind of control
63 if ( textboxes[0].style.display != 'none' ) {
64 if ( !( document.selection && document.selection.createRange )
65 && textboxes[0].selectionStart === null ) {
66 return false;
67 }
68 }
69 for ( var i = 0; i < mwEditButtons.length; i++ ) {
70 mwInsertEditButton( toolbar, mwEditButtons[i] );
71 }
72 for ( var i = 0; i < mwCustomEditButtons.length; i++ ) {
73 mwInsertEditButton( toolbar, mwCustomEditButtons[i] );
74 }
75 return true;
76 };
77
78 // apply tagOpen/tagClose to selection in textarea,
79 // use sampleText instead of selection if there is none
80 window.insertTags = function( tagOpen, tagClose, sampleText ) {
81 if ( typeof $ != 'undefined' && typeof $.fn.textSelection != 'undefined' &&
82 ( currentFocused.nodeName.toLowerCase() == 'iframe' || currentFocused.id == 'wpTextbox1' ) ) {
83 $( '#wpTextbox1' ).textSelection(
84 'encapsulateSelection', { 'pre': tagOpen, 'peri': sampleText, 'post': tagClose }
85 );
86 return;
87 }
88 var txtarea;
89 if ( document.editform ) {
90 txtarea = currentFocused;
91 } else {
92 // some alternate form? take the first one we can find
93 var areas = document.getElementsByTagName( 'textarea' );
94 txtarea = areas[0];
95 }
96 var selText, isSample = false;
97
98 if ( document.selection && document.selection.createRange ) { // IE/Opera
99 // save window scroll position
100 if ( document.documentElement && document.documentElement.scrollTop ) {
101 var winScroll = document.documentElement.scrollTop
102 } else if ( document.body ) {
103 var winScroll = document.body.scrollTop;
104 }
105 // get current selection
106 txtarea.focus();
107 var range = document.selection.createRange();
108 selText = range.text;
109 // insert tags
110 checkSelectedText();
111 range.text = tagOpen + selText + tagClose;
112 // mark sample text as selected
113 if ( isSample && range.moveStart ) {
114 if ( window.opera ) {
115 tagClose = tagClose.replace(/\n/g,'');
116 }
117 range.moveStart('character', - tagClose.length - selText.length);
118 range.moveEnd('character', - tagClose.length);
119 }
120 range.select();
121 // restore window scroll position
122 if ( document.documentElement && document.documentElement.scrollTop ) {
123 document.documentElement.scrollTop = winScroll;
124 } else if ( document.body ) {
125 document.body.scrollTop = winScroll;
126 }
127
128 } else if ( txtarea.selectionStart || txtarea.selectionStart == '0' ) { // Mozilla
129 // save textarea scroll position
130 var textScroll = txtarea.scrollTop;
131 // get current selection
132 txtarea.focus();
133 var startPos = txtarea.selectionStart;
134 var endPos = txtarea.selectionEnd;
135 selText = txtarea.value.substring( startPos, endPos );
136 // insert tags
137 checkSelectedText();
138 txtarea.value = txtarea.value.substring(0, startPos)
139 + tagOpen + selText + tagClose
140 + txtarea.value.substring(endPos, txtarea.value.length);
141 // set new selection
142 if ( isSample ) {
143 txtarea.selectionStart = startPos + tagOpen.length;
144 txtarea.selectionEnd = startPos + tagOpen.length + selText.length;
145 } else {
146 txtarea.selectionStart = startPos + tagOpen.length + selText.length + tagClose.length;
147 txtarea.selectionEnd = txtarea.selectionStart;
148 }
149 // restore textarea scroll position
150 txtarea.scrollTop = textScroll;
151 }
152
153 function checkSelectedText() {
154 if ( !selText ) {
155 selText = sampleText;
156 isSample = true;
157 } else if ( selText.charAt(selText.length - 1) == ' ' ) { // exclude ending space char
158 selText = selText.substring(0, selText.length - 1);
159 tagClose += ' ';
160 }
161 }
162
163 };
164
165 /**
166 * Restore the edit box scroll state following a preview operation,
167 * and set up a form submission handler to remember this state
168 */
169 window.scrollEditBox = function() {
170 var editBox = document.getElementById( 'wpTextbox1' );
171 var scrollTop = document.getElementById( 'wpScrolltop' );
172 var editForm = document.getElementById( 'editform' );
173 if( editForm && editBox && scrollTop ) {
174 if( scrollTop.value ) {
175 editBox.scrollTop = scrollTop.value;
176 }
177 addHandler( editForm, 'submit', function() {
178 scrollTop.value = editBox.scrollTop;
179 } );
180 }
181 };
182 hookEvent( 'load', scrollEditBox );
183 hookEvent( 'load', mwSetupToolbar );
184 hookEvent( 'load', function() {
185 currentFocused = document.getElementById( 'wpTextbox1' );
186 // http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
187 // focus does not bubble normally, but using a trick we can do event delegation
188 // on the focus event on all text inputs to make the toolbox usable on all of them
189 var editForm = document.getElementById( 'editform' );
190 if ( !editForm ) {
191 return;
192 }
193 function onfocus( e ) {
194 var elm = e.target || e.srcElement;
195 if ( !elm ) {
196 return;
197 }
198 var tagName = elm.tagName.toLowerCase();
199 var type = elm.type || '';
200 if ( tagName !== 'textarea' && tagName !== 'input' ) {
201 return;
202 }
203 if ( tagName === 'input' && type.toLowerCase() !== 'text' ) {
204 return;
205 }
206
207 currentFocused = elm;
208 }
209
210 if ( editForm.addEventListener ) {
211 // Gecko, WebKit, Opera, etc... (all standards compliant browsers)
212 editForm.addEventListener( 'focus', onfocus, true ); // This MUST be true to work
213 } else if ( editForm.attachEvent ) {
214 // IE needs a specific trick here since it doesn't support the standard
215 editForm.attachEvent( 'onfocusin', function() { onfocus( event ); } );
216 }
217
218 // HACK: make currentFocused work with the usability iframe
219 // With proper focus detection support (HTML 5!) this'll be much cleaner
220 if ( typeof $ != 'undefined' ) {
221 var iframe = $( '.wikiEditor-ui-text iframe' );
222 if ( iframe.length > 0 ) {
223 $( iframe.get( 0 ).contentWindow.document )
224 .add( iframe.get( 0 ).contentWindow.document.body ) // for IE
225 .focus( function() { currentFocused = iframe.get( 0 ); } );
226 }
227 }
228
229 editForm
230 } );
231
232 //make sure edit summary does not exceed byte limit
233 addOnloadHook(function () {
234 var summary = document.getElementById( 'wpSummary' );
235 if ( !summary ) {
236 return;
237 }
238 summary.maxLength = 250; //L must be capitalized in length.
239
240 checkSummary = function (e) {
241 if (!e) e = window.event; //IE
242
243 //first check to see if this is actually a character key
244 // being pressed.
245 //Based on key-event info from http://unixpapa.com/js/key.html
246 //note === sign, if undefined, still could be a real key
247
248 if (e.which === 0 || e.charCode === 0 || e.ctrlKey || e.altKey || e.metaKey) {
249 return true; //a special key (backspace, etc) so don't interefere.
250 }
251
252 //This basically figures out how many bytes a utf-16 string (which is what js sees) will take in utf-8
253 //by replacing a 2 byte character with 2 *'s, etc, and counting that.
254 //Note, surogate (\uD800-\uDFFF) characters are counted as 2 bytes, since theres two of them
255 //and the actual character takes 4 bytes in utf-8 (2*2=4). might not work perfectly in edge cases such as
256 //such as illegal sequences, but that should never happen.
257
258 len = summary.value.replace(/[\u0080-\u07FF\uD800-\uDFFF]/g, '**').replace(/[\u0800-\uD7FF\uE000-\uFFFF]/g, '***').length;
259 //247 as this doesn't count character about to be inserted.
260 if (len > 247) {
261 if (e.preventDefault) e.preventDefault();
262 e.returnValue = false; //IE
263 return false;
264 }
265 };
266
267 addHandler(summary, 'keypress', checkSummary);
268 });
269