FormOptions: adds doc & tests
[mediawiki.git] / skins / common / edit.js
blobdd5d13046a564f6b7131cdbe33118f8b669a9bf0
1 window.currentFocused = undefined;
3 // this function adds a toolbar button to the mwEditButtons list
4 window.addButton = function( imageFile, speedTip, tagOpen, tagClose, sampleText, imageId, selectText ) {
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                 'selectText': selectText
15         });
18 // this function adds one toolbar button from a mwEditButtons/mwCustomEditButtons item
19 window.mwInsertEditButton = function( parent, item ) {
20         var image = document.createElement( 'img' );
21         image.width = 23;
22         image.height = 22;
23         image.className = 'mw-toolbar-editbutton';
24         if ( item.imageId ) {
25                 image.id = item.imageId;
26         }
27         image.src = item.imageFile;
28         image.border = 0;
29         image.alt = item.speedTip;
30         image.title = item.speedTip;
31         image.style.cursor = 'pointer';
32         image.onclick = function() {
33                 insertTags( item.tagOpen, item.tagClose, item.sampleText, item.selectText );
34                 // click tracking
35                 if ( ( typeof $ != 'undefined' )  && ( typeof $.trackAction != 'undefined' ) ) {
36                         $.trackAction( 'oldedit.' + item.speedTip.replace(/ /g, "-") );
37                 }
38                 return false;
39         };
41         parent.appendChild( image );
42         return true;
45 // this function generates the actual toolbar buttons with localized text
46 // we use it to avoid creating the toolbar where javascript is not enabled
47 window.mwSetupToolbar = function() {
48         var toolbar = document.getElementById( 'toolbar' );
49         if ( !toolbar ) {
50                 return false;
51         }
53         // Don't generate buttons for browsers which don't fully
54         // support it.
55         // but don't assume wpTextbox1 is always here
56         var textboxes = document.getElementsByTagName( 'textarea' );
57         if ( !textboxes.length ) {
58                 // No toolbar if we can't find any textarea
59                 return false;
60         }
61         // Only check for selection capability if the textarea is visible - errors will occur otherwise - just because
62         // the textarea is not visible, doesn't mean we shouldn't build out the toolbar though - it might have been replaced
63         // with some other kind of control
64         if ( textboxes[0].style.display != 'none' ) {
65                 if ( !( document.selection && document.selection.createRange )
66                         && textboxes[0].selectionStart === null ) {
67                         return false;
68                 }
69         }
70         for ( var i = 0; i < mwEditButtons.length; i++ ) {
71                 mwInsertEditButton( toolbar, mwEditButtons[i] );
72         }
73         for ( var i = 0; i < mwCustomEditButtons.length; i++ ) {
74                 mwInsertEditButton( toolbar, mwCustomEditButtons[i] );
75         }
76         return true;
79 // apply tagOpen/tagClose to selection in textarea,
80 // use sampleText instead of selection if there is none
81 window.insertTags = function( tagOpen, tagClose, sampleText, selectText) {
82         if ( typeof $ != 'undefined' && typeof $.fn.textSelection != 'undefined' && currentFocused &&
83                         ( currentFocused.nodeName.toLowerCase() == 'iframe' || currentFocused.id == 'wpTextbox1' ) ) {
84                 $( '#wpTextbox1' ).textSelection(
85                         'encapsulateSelection', { 'pre': tagOpen, 'peri': sampleText, 'post': tagClose }
86                 );
87                 return;
88         }
89         var txtarea;
90         if ( document.editform ) {
91                 txtarea = currentFocused;
92         } else {
93                 // some alternate form? take the first one we can find
94                 var areas = document.getElementsByTagName( 'textarea' );
95                 txtarea = areas[0];
96         }
97         var selText, isSample = false;
99         if ( document.selection  && document.selection.createRange ) { // IE/Opera
100                 // save window scroll position
101                 if ( document.documentElement && document.documentElement.scrollTop ) {
102                         var winScroll = document.documentElement.scrollTop
103                 } else if ( document.body ) {
104                         var winScroll = document.body.scrollTop;
105                 }
106                 // get current selection
107                 txtarea.focus();
108                 var range = document.selection.createRange();
109                 selText = range.text;
110                 // insert tags
111                 checkSelectedText();
112                 range.text = tagOpen + selText + tagClose;
113                 // mark sample text as selected if not switched off by option
114                 if ( selectText !== false ) {
115                         if ( isSample && range.moveStart ) {
116                                 if ( window.opera ) {
117                                         tagClose = tagClose.replace(/\n/g,'');
118                                 }
119                                 range.moveStart('character', - tagClose.length - selText.length);
120                                 range.moveEnd('character', - tagClose.length);
121                         }
122                         range.select();
123                 }
124                 // restore window scroll position
125                 if ( document.documentElement && document.documentElement.scrollTop ) {
126                         document.documentElement.scrollTop = winScroll;
127                 } else if ( document.body ) {
128                         document.body.scrollTop = winScroll;
129                 }
131         } else if ( txtarea.selectionStart || txtarea.selectionStart == '0' ) { // Mozilla
132                 // save textarea scroll position
133                 var textScroll = txtarea.scrollTop;
134                 // get current selection
135                 txtarea.focus();
136                 var startPos = txtarea.selectionStart;
137                 var endPos = txtarea.selectionEnd;
138                 selText = txtarea.value.substring( startPos, endPos );
139                 // insert tags
140                 checkSelectedText();
141                 txtarea.value = txtarea.value.substring(0, startPos)
142                         + tagOpen + selText + tagClose
143                         + txtarea.value.substring(endPos, txtarea.value.length);
144                 // set new selection
145                 if ( isSample && ( selectText !== false )) {
146                         txtarea.selectionStart = startPos + tagOpen.length;
147                         txtarea.selectionEnd = startPos + tagOpen.length + selText.length;
148                 } else {
149                         txtarea.selectionStart = startPos + tagOpen.length + selText.length + tagClose.length;
150                         txtarea.selectionEnd = txtarea.selectionStart;
151                 }
152                 // restore textarea scroll position
153                 txtarea.scrollTop = textScroll;
154         }
156         function checkSelectedText() {
157                 if ( !selText ) {
158                         selText = sampleText;
159                         isSample = true;
160                 } else if ( selText.charAt(selText.length - 1) == ' ' ) { // exclude ending space char
161                         selText = selText.substring(0, selText.length - 1);
162                         tagClose += ' ';
163                 }
164         }
169  * Restore the edit box scroll state following a preview operation,
170  * and set up a form submission handler to remember this state
171  */
172 window.scrollEditBox = function() {
173         var editBox = document.getElementById( 'wpTextbox1' );
174         var scrollTop = document.getElementById( 'wpScrolltop' );
175         var editForm = document.getElementById( 'editform' );
176         if( editForm && editBox && scrollTop ) {
177                 if( scrollTop.value ) {
178                         editBox.scrollTop = scrollTop.value;
179                 }
180                 addHandler( editForm, 'submit', function() {
181                         scrollTop.value = editBox.scrollTop;
182                 } );
183         }
185 hookEvent( 'load', scrollEditBox );
186 hookEvent( 'load', mwSetupToolbar );
187 hookEvent( 'load', function() {
188         currentFocused = document.getElementById( 'wpTextbox1' );
189         // http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
190         // focus does not bubble normally, but using a trick we can do event delegation
191         // on the focus event on all text inputs to make the toolbox usable on all of them
192         var editForm = document.getElementById( 'editform' );
193         if ( !editForm ) {
194                 return;
195         }
196         function onfocus( e ) {
197                 var elm = e.target || e.srcElement;
198                 if ( !elm ) {
199                         return;
200                 }
201                 var tagName = elm.tagName.toLowerCase();
202                 var type = elm.type || '';
203                 if ( tagName !== 'textarea' && tagName !== 'input' ) {
204                         return;
205                 }
206                 if ( tagName === 'input' && type.toLowerCase() !== 'text' ) {
207                         return;
208                 }
210                 currentFocused = elm;
211         }
213         if ( editForm.addEventListener ) {
214                 // Gecko, WebKit, Opera, etc... (all standards compliant browsers)
215                 editForm.addEventListener( 'focus', onfocus, true ); // This MUST be true to work
216         } else if ( editForm.attachEvent ) {
217                 // IE needs a specific trick here since it doesn't support the standard
218                 editForm.attachEvent( 'onfocusin', function() { onfocus( event ); } );
219         }
220         
221         // HACK: make currentFocused work with the usability iframe
222         // With proper focus detection support (HTML 5!) this'll be much cleaner
223         if ( typeof $ != 'undefined' ) {
224                 var iframe = $( '.wikiEditor-ui-text iframe' );
225                 if ( iframe.length > 0 ) {
226                         $( iframe.get( 0 ).contentWindow.document )
227                                 .add( iframe.get( 0 ).contentWindow.document.body ) // for IE
228                                 .focus( function() { currentFocused = iframe.get( 0 ); } );
229                 }
230         }
232         editForm
233 } );