8001164a887285b39bf71318c1cad16013f4c1ac
[lhc/web/wiklou.git] / skins / common / edit.js
1 var currentFocused;
2
3 // this function generates the actual toolbar buttons with localized text
4 // we use it to avoid creating the toolbar where javascript is not enabled
5 function addButton( imageFile, speedTip, tagOpen, tagClose, sampleText, imageId ) {
6 // Don't generate buttons for browsers which don't fully
7 // support it.
8 mwEditButtons.push({
9 'imageId': imageId,
10 'imageFile': imageFile,
11 'speedTip': speedTip,
12 'tagOpen': tagOpen,
13 'tagClose': tagClose,
14 'sampleText': sampleText
15 });
16 }
17
18 // this function generates the actual toolbar buttons with localized text
19 // we use it to avoid creating the toolbar where JavaScript is not enabled
20 function mwInsertEditButton( parent, item ) {
21 var image = document.createElement( 'img' );
22 image.width = 23;
23 image.height = 22;
24 image.className = 'mw-toolbar-editbutton';
25 if ( item.imageId ) {
26 image.id = item.imageId;
27 }
28 image.src = item.imageFile;
29 image.border = 0;
30 image.alt = item.speedTip;
31 image.title = item.speedTip;
32 image.style.cursor = 'pointer';
33 image.onclick = function() {
34 insertTags( item.tagOpen, item.tagClose, item.sampleText );
35 // click tracking
36 if ( ( typeof $j != 'undefined' ) && ( typeof $j.trackAction != 'undefined' ) ) {
37 $j.trackAction( 'oldedit.' + item.speedTip.replace(/ /g, "-") );
38 }
39 return false;
40 };
41
42 parent.appendChild( image );
43 return true;
44 }
45
46 function mwSetupToolbar() {
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 function insertTags( tagOpen, tagClose, sampleText ) {
81 if ( typeof $j != 'undefined' && typeof $j.fn.textSelection != 'undefined' ) {
82 $j( '#wpTextbox1' ).textSelection(
83 'encapsulateSelection', { 'pre': tagOpen, 'peri': sampleText, 'post': tagClose }
84 );
85 return;
86 }
87 var txtarea;
88 if ( document.editform ) {
89 txtarea = currentFocused;
90 } else {
91 // some alternate form? take the first one we can find
92 var areas = document.getElementsByTagName( 'textarea' );
93 txtarea = areas[0];
94 }
95 var selText, isSample = false;
96
97 if ( document.selection && document.selection.createRange ) { // IE/Opera
98 // save window scroll position
99 if ( document.documentElement && document.documentElement.scrollTop ) {
100 var winScroll = document.documentElement.scrollTop
101 } else if ( document.body ) {
102 var winScroll = document.body.scrollTop;
103 }
104 // get current selection
105 txtarea.focus();
106 var range = document.selection.createRange();
107 selText = range.text;
108 // insert tags
109 checkSelectedText();
110 range.text = tagOpen + selText + tagClose;
111 // mark sample text as selected
112 if ( isSample && range.moveStart ) {
113 if ( window.opera ) {
114 tagClose = tagClose.replace(/\n/g,'');
115 }
116 range.moveStart('character', - tagClose.length - selText.length);
117 range.moveEnd('character', - tagClose.length);
118 }
119 range.select();
120 // restore window scroll position
121 if ( document.documentElement && document.documentElement.scrollTop ) {
122 document.documentElement.scrollTop = winScroll;
123 } else if ( document.body ) {
124 document.body.scrollTop = winScroll;
125 }
126
127 } else if ( txtarea.selectionStart || txtarea.selectionStart == '0' ) { // Mozilla
128 // save textarea scroll position
129 var textScroll = txtarea.scrollTop;
130 // get current selection
131 txtarea.focus();
132 var startPos = txtarea.selectionStart;
133 var endPos = txtarea.selectionEnd;
134 selText = txtarea.value.substring( startPos, endPos );
135 // insert tags
136 checkSelectedText();
137 txtarea.value = txtarea.value.substring(0, startPos)
138 + tagOpen + selText + tagClose
139 + txtarea.value.substring(endPos, txtarea.value.length);
140 // set new selection
141 if ( isSample ) {
142 txtarea.selectionStart = startPos + tagOpen.length;
143 txtarea.selectionEnd = startPos + tagOpen.length + selText.length;
144 } else {
145 txtarea.selectionStart = startPos + tagOpen.length + selText.length + tagClose.length;
146 txtarea.selectionEnd = txtarea.selectionStart;
147 }
148 // restore textarea scroll position
149 txtarea.scrollTop = textScroll;
150 }
151
152 function checkSelectedText() {
153 if ( !selText ) {
154 selText = sampleText;
155 isSample = true;
156 } else if ( selText.charAt(selText.length - 1) == ' ' ) { // exclude ending space char
157 selText = selText.substring(0, selText.length - 1);
158 tagClose += ' ';
159 }
160 }
161
162 }
163
164 /**
165 * Restore the edit box scroll state following a preview operation,
166 * and set up a form submission handler to remember this state
167 */
168 function scrollEditBox() {
169 var editBox = document.getElementById( 'wpTextbox1' );
170 var scrollTop = document.getElementById( 'wpScrolltop' );
171 var editForm = document.getElementById( 'editform' );
172 if( editForm && editBox && scrollTop ) {
173 if( scrollTop.value ) {
174 editBox.scrollTop = scrollTop.value;
175 }
176 addHandler( editForm, 'submit', function() {
177 scrollTop.value = editBox.scrollTop;
178 } );
179 }
180 }
181 hookEvent( 'load', scrollEditBox );
182 hookEvent( 'load', mwSetupToolbar );
183 hookEvent( 'load', function() {
184 currentFocused = document.getElementById( 'wpTextbox1' );
185 // http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
186 // focus does not bubble normally, but using a trick we can do event delegation
187 // on the focus event on all text inputs to make the toolbox usable on all of them
188 var editForm = document.getElementById( 'editform' );
189 if ( !editForm ) {
190 return;
191 }
192 function onfocus( e ) {
193 var elm = e.target;
194 if ( !elm ) {
195 return;
196 }
197 var tagName = elm.tagName.toLowerCase();
198 var type = elm.type.toLowerCase();
199 if ( tagName !== 'textarea' && tagName !== 'input' ) {
200 return;
201 }
202 if ( tagName === 'input' && type && type !== 'text' ) {
203 return;
204 }
205
206 currentFocused = elm;
207 }
208
209 if ( editForm.addEventListener ) {
210 // Gecko, WebKit, Opera, etc... (all standards compliant browsers)
211 editForm.addEventListener( 'focus', onfocus, true ); // This MUST be true to work
212 } else if ( editForm.attachEvent ) {
213 // IE needs a specific trick here since it doesn't support the standard
214 editForm.attachEvent( 'onfocusin', function() { onfocus( event ); } );
215 }
216
217 editForm
218 } );
219