r61828 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r61827‎ | r61828 | r61829 >
Date:22:39, 1 February 2010
Author:catrope
Status:ok
Tags:
Comment:
wmf-deployment: Update UsabilityInitiative_alpha to trunk state
Modified paths:
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/ClickTracking/ClickTracking.i18n.php (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/PrefStats/PrefStats.i18n.php (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/UsabilityInitiative.hooks.php (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/WikiEditor/Modules/TemplateEditor/TemplateEditor.i18n.php (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/WikiEditor/Modules/Toolbar/Toolbar.i18n.php (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/WikiEditor/Modules/Toolbar/Toolbar.js (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/WikiEditor/WikiEditor.combined.js (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/WikiEditor/WikiEditor.combined.min.js (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/WikiEditor/WikiEditor.hooks.php (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/css/combined.css (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/css/combined.min.css (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/css/wikiEditor.css (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/css/wikiEditor.dialogs.css (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/images/wikiEditor/dialogs/button_disabled.png (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/images/wikiEditor/dialogs/button_down.png (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/images/wikiEditor/dialogs/button_off.png (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/images/wikiEditor/dialogs/button_over.png (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/js/plugins.combined.js (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/js/plugins.combined.min.js (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/js/plugins/jquery.wikiEditor.highlight.js (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/js/plugins/jquery.wikiEditor.js (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/js/plugins/jquery.wikiEditor.templateEditor.js (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/js/plugins/jquery.wikiEditor.toc.js (modified) (history)
  • /branches/wmf-deployment/extensions/UsabilityInitiative_alpha/js/plugins/jquery.wikiEditor.toolbar.js (modified) (history)

Diff [purge]

Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/images/wikiEditor/dialogs/button_disabled.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/images/wikiEditor/dialogs/button_down.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/images/wikiEditor/dialogs/button_off.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/images/wikiEditor/dialogs/button_over.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/ClickTracking/ClickTracking.i18n.php
@@ -539,6 +539,7 @@
540540
541541 /** Basque (Euskara)
542542 * @author An13sa
 543+ * @author Unai Fdz. de Betoño
543544 */
544545 $messages['eu'] = array(
545546 'ct-event-name' => 'Ekintzaren izena',
@@ -553,6 +554,7 @@
554555 'ct-intermediate' => 'Maila ertainekoa',
555556 'ct-expert' => 'Aditua',
556557 'ct-anon-users' => 'Lankide anonimoak',
 558+ 'ct-user-contribs' => 'Lankidearen ekarpen guztiak',
557559 'ct-and' => 'eta',
558560 'ct-update-table' => 'Taula eguneratu',
559561 );
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/css/combined.css
@@ -137,7 +137,6 @@
138138 position: relative;
139139 clear: both;
140140 width: 100%;
141 - line-height: 1em;
142141 background-color: #f3f3f3;
143142 border: solid silver 1px;
144143 }
@@ -222,40 +221,38 @@
223222 .wikiEditor-ui-tabs div.current a:hover {
224223 text-decoration: none;
225224 }
 225+
 226+.wikiEditor-view-wikitext {
 227+ line-height: 1em;
 228+}
226229 /* wikiEditor dialogs module */
227230
228 -.ui-widget table {
 231+.wikiEditor-toolbar-dialog table {
229232 margin-top: 0.75em;
230233 }
231 -.ui-widget table td {
 234+.wikiEditor-toolbar-dialog table td {
232235 padding: 0.5em;
233236 height: 3em;
234237 overflow: visible;
235238 }
236 -
237 -
238 -
239239 /* Put suggestions (default z-index 99) on top of dialogs (z-index 1002) */
240240 div.suggestions {
241241 z-index: 1099;
242242 }
243 -
244 -.ui-dialog .ui-dialog-titlebar-close:hover {
 243+.wikiEditor-toolbar-dialog .ui-dialog-titlebar-close:hover {
245244 text-decoration: none;
246245 }
247 -.ui-dialog-content .status-invalid input {
 246+.wikiEditor-toolbar-dialog .ui-dialog-content .status-invalid input {
248247 border: 2px solid red;
249248 padding: 2px 1px;
250249 }
251 -
252 -
253 -.ui-dialog .ui-dialog-titlebar {
 250+.wikiEditor-toolbar-dialog .ui-dialog-titlebar {
254251 padding: 0.9em 1.4em 0.6em !important;
255252 }
256 -.ui-widget table td {
 253+.wikiEditor-toolbar-dialog table td {
257254 padding: 0 !important;
258255 }
259 -.ui-dialog .ui-dialog-buttonpane button {
 256+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button {
260257 -moz-border-radius: 4px;
261258 -webkit-border-radius: 4px;
262259 padding: 0.2em 0.6em 0.15em !important;
@@ -263,54 +260,55 @@
264261 border: 1px solid #a6a6a6 !important;
265262 background: #f2f2f2 url( ../images/wikiEditor/dialogs/button_off.png ) repeat-x scroll 50% 100% !important;
266263 }
267 -.ui-dialog .ui-dialog-buttonpane button:hover {
268 - background: #ebf2f9 url( ../images/wikiEditor/dialogs/button_over.png ) repeat-x scroll 50% 100% !important;
 264+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button:hover {
 265+ border-color: #6e7273;
 266+ background: #e1e1e1 url( ../images/wikiEditor/dialogs/button_over.png ) repeat-x scroll 50% 100% !important;
269267 }
270 -.ui-dialog .ui-dialog-buttonpane button:active,
271 -.ui-dialog .ui-dialog-buttonpane button:focus {
272 -
 268+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button:active,
 269+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button:focus {
 270+ border-color: #707271;
273271 background: #bfbfbf url( ../images/wikiEditor/dialogs/button_down.png ) repeat-x scroll 50% 100% !important;
274272 }
275 -.ui-dialog .ui-dialog-buttonpane button.disabled {
 273+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button.disabled {
276274 color: #7f7f7f;
277275 border-color: #cccccc;
278276 background: #f2f2f2 url( ../images/wikiEditor/dialogs/button_disabled.png ) repeat-x scroll 50% 100% !important;
279277 }
280278 /* Disables the annoying dashed border Firefox puts on active buttons */
281 -.ui-dialog .ui-dialog-buttonpane button::-moz-focus-inner {
 279+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button::-moz-focus-inner {
282280 border: 0;
283281 }
284 -.ui-widget-header {
 282+.wikiEditor-toolbar-dialog .ui-widget-header {
285283 background: #f0f0f0 url( ../images/wikiEditor/dialogs/titlebar_fade.png ) repeat-x scroll 50% 100% !important;
286284 }
287285 /* FIXME: Should just update the icon sprite if we're keeping this X */
288 -.ui-icon-closethick {
 286+.wikiEditor-toolbar-dialog .ui-icon-closethick {
289287 background: url( ../images/wikiEditor/dialogs/close_x.png ) no-repeat 50% 50% !important;
290288 }
291 -.ui-dialog .ui-dialog-buttonpane {
 289+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane {
292290 margin-top: 0 !important;
293291 padding:0.3em 1.4em 0.5em 1.4em !important;
294292 }
295293
296 -.ui-dialog-content fieldset{
 294+.wikiEditor-toolbar-dialog .ui-dialog-content fieldset{
297295 border: none !important;
298296 margin: 0 !important;
299297 padding: 0 !important;
300298 }
301 -.ui-widget-header {
 299+.wikiEditor-toolbar-dialog .ui-widget-header {
302300 border-bottom:1px solid #6bc8f3 !important;
303301 }
304 -.ui-dialog-content input[type=text] {
 302+.wikiEditor-toolbar-dialog .ui-dialog-content input[type=text] {
305303 -moz-box-sizing: border-box;
306304 -ms-box-sizing: border-box;
307305 -webkit-box-sizing: border-box;
308306 -khtml-box-sizing: border-box;
309307 }
310 -.ui-dialog-content input[type="radio"],
311 -.ui-dialog-content input[type="checkbox"] {
 308+.wikiEditor-toolbar-dialog .ui-dialog-content input[type="radio"],
 309+.wikiEditor-toolbar-dialog .ui-dialog-content input[type="checkbox"] {
312310 margin-left: 0;
313311 }
314 -body.ltr .ui-dialog .ui-dialog-titlebar-close {
 312+body.ltr .wikiEditor-toolbar-dialog .ui-dialog-titlebar-close {
315313 right: 0.9em;
316314 }
317315 .wikieditor-toolbar-field-wrapper {
@@ -340,21 +338,21 @@
341339 body.rtl #wikieditor-toolbar-table-dialog .wikieditor-toolbar-table-preview-wrapper {
342340 float: left;
343341 }
344 -body.rtl .ui-widget .wikieditor-toolbar-table-preview-wrapper table {
 342+body.rtl .wikiEditor-toolbar-dialog .wikieditor-toolbar-table-preview-wrapper table {
345343 margin-left: 1em;
346344 margin-right: 0;
347345 }
348346 .wikieditor-toolbar-table-preview-content * {
349347 cursor: default;
350348 }
351 -.ui-widget .wikieditor-toolbar-table-preview-wrapper table {
 349+.wikiEditor-toolbar-dialog .wikieditor-toolbar-table-preview-wrapper table {
352350 width: 100% !important;
353351 }
354 -.ui-widget .wikieditor-toolbar-table-preview-content table td {
 352+.wikiEditor-toolbar-dialog .wikieditor-toolbar-table-preview-content table td {
355353 padding: 10px 4px !important;
356354 height: auto !important;
357355 }
358 -.ui-widget .wikieditor-toolbar-table-preview-content table th {
 356+.wikiEditor-toolbar-dialog .wikieditor-toolbar-table-preview-content table th {
359357 padding: 7px 3px !important;
360358 }
361359 .wikieditor-toolbar-table-dimension-fields .wikieditor-toolbar-field-wrapper {
@@ -367,7 +365,7 @@
368366 margin-right: 0px;
369367 margin-left: 20px;
370368 }
371 -.ui-dialog .ui-dialog-content {
 369+.wikiEditor-toolbar-dialog .ui-dialog-content {
372370 padding: 30px 20px 0 !important;
373371 }
374372 .wikieditor-toolbar-dialog-wrapper {
@@ -376,15 +374,15 @@
377375 /* REPLACE Dialog */
378376
379377 /* RTL Changes */
380 -body.rtl .ui-dialog .ui-dialog-buttonpane button {
 378+body.rtl .wikiEditor-toolbar-dialog .ui-dialog-buttonpane button {
381379 float: left;
382380 margin: 0.5em 0.4em 0.5em 0 !important;
383381 }
384 -body.rtl .ui-dialog .ui-dialog-titlebar-close {
 382+body.rtl .wikiEditor-toolbar-dialog .ui-dialog-titlebar-close {
385383 left: 0.9em;
386384 right: auto;
387385 }
388 -body.rtl .ui-dialog .ui-dialog-title {
 386+body.rtl .wikiEditor-toolbar-dialog .ui-dialog-title {
389387 float:right;
390388 }
391389 /* Self Clearing Floats */
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/css/combined.min.css
@@ -129,7 +129,6 @@
130130 position:relative;
131131 clear:both;
132132 width:100%;
133 -line-height:1em;
134133 background-color:#f3f3f3;
135134 border:solid silver 1px;
136135 }
@@ -213,10 +212,13 @@
214213 .wikiEditor-ui-tabs div.current a:hover{
215214 text-decoration:none;
216215 }
217 -.ui-widget table{
 216+.wikiEditor-view-wikitext{
 217+line-height:1em;
 218+}
 219+.wikiEditor-toolbar-dialog table{
218220 margin-top:0.75em;
219221 }
220 -.ui-widget table td{
 222+.wikiEditor-toolbar-dialog table td{
221223 padding:0.5em;
222224 height:3em;
223225 overflow:visible;
@@ -224,20 +226,20 @@
225227 div.suggestions{
226228 z-index:1099;
227229 }
228 -.ui-dialog .ui-dialog-titlebar-close:hover{
 230+.wikiEditor-toolbar-dialog .ui-dialog-titlebar-close:hover{
229231 text-decoration:none;
230232 }
231 -.ui-dialog-content .status-invalid input{
 233+.wikiEditor-toolbar-dialog .ui-dialog-content .status-invalid input{
232234 border:2px solid red;
233235 padding:2px 1px;
234236 }
235 -.ui-dialog .ui-dialog-titlebar{
 237+.wikiEditor-toolbar-dialog .ui-dialog-titlebar{
236238 padding:0.9em 1.4em 0.6em !important;
237239 }
238 -.ui-widget table td{
 240+.wikiEditor-toolbar-dialog table td{
239241 padding:0 !important;
240242 }
241 -.ui-dialog .ui-dialog-buttonpane button{
 243+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button{
242244 -moz-border-radius:4px;
243245 -webkit-border-radius:4px;
244246 padding:0.2em 0.6em 0.15em !important;
@@ -245,50 +247,52 @@
246248 border:1px solid #a6a6a6 !important;
247249 background:#f2f2f2 url( ../images/wikiEditor/dialogs/button_off.png ) repeat-x scroll 50% 100% !important;
248250 }
249 -.ui-dialog .ui-dialog-buttonpane button:hover{
250 -background:#ebf2f9 url( ../images/wikiEditor/dialogs/button_over.png ) repeat-x scroll 50% 100% !important;
 251+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button:hover{
 252+border-color:#6e7273;
 253+background:#e1e1e1 url( ../images/wikiEditor/dialogs/button_over.png ) repeat-x scroll 50% 100% !important;
251254 }
252 -.ui-dialog .ui-dialog-buttonpane button:active,
253 -.ui-dialog .ui-dialog-buttonpane button:focus{
 255+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button:active,
 256+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button:focus{
 257+border-color:#707271;
254258 background:#bfbfbf url( ../images/wikiEditor/dialogs/button_down.png ) repeat-x scroll 50% 100% !important;
255259 }
256 -.ui-dialog .ui-dialog-buttonpane button.disabled{
 260+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button.disabled{
257261 color:#7f7f7f;
258262 border-color:#cccccc;
259263 background:#f2f2f2 url( ../images/wikiEditor/dialogs/button_disabled.png ) repeat-x scroll 50% 100% !important;
260264 }
261 -.ui-dialog .ui-dialog-buttonpane button::-moz-focus-inner{
 265+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button::-moz-focus-inner{
262266 border:0;
263267 }
264 -.ui-widget-header{
 268+.wikiEditor-toolbar-dialog .ui-widget-header{
265269 background:#f0f0f0 url( ../images/wikiEditor/dialogs/titlebar_fade.png ) repeat-x scroll 50% 100% !important;
266270 }
267 -.ui-icon-closethick{
 271+.wikiEditor-toolbar-dialog .ui-icon-closethick{
268272 background:url( ../images/wikiEditor/dialogs/close_x.png ) no-repeat 50% 50% !important;
269273 }
270 -.ui-dialog .ui-dialog-buttonpane{
 274+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane{
271275 margin-top:0 !important;
272276 padding:0.3em 1.4em 0.5em 1.4em !important;
273277 }
274 -.ui-dialog-content fieldset{
 278+.wikiEditor-toolbar-dialog .ui-dialog-content fieldset{
275279 border:none !important;
276280 margin:0 !important;
277281 padding:0 !important;
278282 }
279 -.ui-widget-header{
 283+.wikiEditor-toolbar-dialog .ui-widget-header{
280284 border-bottom:1px solid #6bc8f3 !important;
281285 }
282 -.ui-dialog-content input[type=text]{
 286+.wikiEditor-toolbar-dialog .ui-dialog-content input[type=text]{
283287 -moz-box-sizing:border-box;
284288 -ms-box-sizing:border-box;
285289 -webkit-box-sizing:border-box;
286290 -khtml-box-sizing:border-box;
287291 }
288 -.ui-dialog-content input[type="radio"],
289 -.ui-dialog-content input[type="checkbox"]{
 292+.wikiEditor-toolbar-dialog .ui-dialog-content input[type="radio"],
 293+.wikiEditor-toolbar-dialog .ui-dialog-content input[type="checkbox"]{
290294 margin-left:0;
291295 }
292 -body.ltr .ui-dialog .ui-dialog-titlebar-close{
 296+body.ltr .wikiEditor-toolbar-dialog .ui-dialog-titlebar-close{
293297 right:0.9em;
294298 }
295299 .wikieditor-toolbar-field-wrapper{
@@ -316,21 +320,21 @@
317321 body.rtl #wikieditor-toolbar-table-dialog .wikieditor-toolbar-table-preview-wrapper{
318322 float:left;
319323 }
320 -body.rtl .ui-widget .wikieditor-toolbar-table-preview-wrapper table{
 324+body.rtl .wikiEditor-toolbar-dialog .wikieditor-toolbar-table-preview-wrapper table{
321325 margin-left:1em;
322326 margin-right:0;
323327 }
324328 .wikieditor-toolbar-table-preview-content *{
325329 cursor:default;
326330 }
327 -.ui-widget .wikieditor-toolbar-table-preview-wrapper table{
 331+.wikiEditor-toolbar-dialog .wikieditor-toolbar-table-preview-wrapper table{
328332 width:100% !important;
329333 }
330 -.ui-widget .wikieditor-toolbar-table-preview-content table td{
 334+.wikiEditor-toolbar-dialog .wikieditor-toolbar-table-preview-content table td{
331335 padding:10px 4px !important;
332336 height:auto !important;
333337 }
334 -.ui-widget .wikieditor-toolbar-table-preview-content table th{
 338+.wikiEditor-toolbar-dialog .wikieditor-toolbar-table-preview-content table th{
335339 padding:7px 3px !important;
336340 }
337341 .wikieditor-toolbar-table-dimension-fields .wikieditor-toolbar-field-wrapper{
@@ -343,21 +347,21 @@
344348 margin-right:0px;
345349 margin-left:20px;
346350 }
347 -.ui-dialog .ui-dialog-content{
 351+.wikiEditor-toolbar-dialog .ui-dialog-content{
348352 padding:30px 20px 0 !important;
349353 }
350354 .wikieditor-toolbar-dialog-wrapper{
351355 width:100%;
352356 }
353 -body.rtl .ui-dialog .ui-dialog-buttonpane button{
 357+body.rtl .wikiEditor-toolbar-dialog .ui-dialog-buttonpane button{
354358 float:left;
355359 margin:0.5em 0.4em 0.5em 0 !important;
356360 }
357 -body.rtl .ui-dialog .ui-dialog-titlebar-close{
 361+body.rtl .wikiEditor-toolbar-dialog .ui-dialog-titlebar-close{
358362 left:0.9em;
359363 right:auto;
360364 }
361 -body.rtl .ui-dialog .ui-dialog-title{
 365+body.rtl .wikiEditor-toolbar-dialog .ui-dialog-title{
362366 float:right;
363367 }
364368 .wikieditor-toolbar-table-dimension-fields:after,
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/css/wikiEditor.css
@@ -24,7 +24,6 @@
2525 position: relative;
2626 clear: both;
2727 width: 100%;
28 - line-height: 1em;
2928 background-color: #f3f3f3;
3029 border: solid silver 1px;
3130 }
@@ -109,3 +108,7 @@
110109 .wikiEditor-ui-tabs div.current a:hover {
111110 text-decoration: none;
112111 }
 112+
 113+.wikiEditor-view-wikitext {
 114+ line-height: 1em;
 115+}
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/css/wikiEditor.dialogs.css
@@ -1,37 +1,31 @@
22 /* wikiEditor dialogs module */
33
4 -.ui-widget table {
 4+.wikiEditor-toolbar-dialog table {
55 margin-top: 0.75em;
66 }
7 -.ui-widget table td {
 7+.wikiEditor-toolbar-dialog table td {
88 padding: 0.5em;
99 height: 3em;
1010 overflow: visible;
1111 }
12 -
13 -
14 -
1512 /* Put suggestions (default z-index 99) on top of dialogs (z-index 1002) */
1613 div.suggestions {
1714 z-index: 1099;
1815 }
19 -
20 -.ui-dialog .ui-dialog-titlebar-close:hover {
 16+.wikiEditor-toolbar-dialog .ui-dialog-titlebar-close:hover {
2117 text-decoration: none;
2218 }
23 -.ui-dialog-content .status-invalid input {
 19+.wikiEditor-toolbar-dialog .ui-dialog-content .status-invalid input {
2420 border: 2px solid red;
2521 padding: 2px 1px;
2622 }
27 -
28 -
29 -.ui-dialog .ui-dialog-titlebar {
 23+.wikiEditor-toolbar-dialog .ui-dialog-titlebar {
3024 padding: 0.9em 1.4em 0.6em !important;
3125 }
32 -.ui-widget table td {
 26+.wikiEditor-toolbar-dialog table td {
3327 padding: 0 !important;
3428 }
35 -.ui-dialog .ui-dialog-buttonpane button {
 29+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button {
3630 -moz-border-radius: 4px;
3731 -webkit-border-radius: 4px;
3832 padding: 0.2em 0.6em 0.15em !important;
@@ -39,54 +33,55 @@
4034 border: 1px solid #a6a6a6 !important;
4135 background: #f2f2f2 url( ../images/wikiEditor/dialogs/button_off.png ) repeat-x scroll 50% 100% !important;
4236 }
43 -.ui-dialog .ui-dialog-buttonpane button:hover {
44 - background: #ebf2f9 url( ../images/wikiEditor/dialogs/button_over.png ) repeat-x scroll 50% 100% !important;
 37+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button:hover {
 38+ border-color: #6e7273;
 39+ background: #e1e1e1 url( ../images/wikiEditor/dialogs/button_over.png ) repeat-x scroll 50% 100% !important;
4540 }
46 -.ui-dialog .ui-dialog-buttonpane button:active,
47 -.ui-dialog .ui-dialog-buttonpane button:focus {
48 -
 41+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button:active,
 42+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button:focus {
 43+ border-color: #707271;
4944 background: #bfbfbf url( ../images/wikiEditor/dialogs/button_down.png ) repeat-x scroll 50% 100% !important;
5045 }
51 -.ui-dialog .ui-dialog-buttonpane button.disabled {
 46+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button.disabled {
5247 color: #7f7f7f;
5348 border-color: #cccccc;
5449 background: #f2f2f2 url( ../images/wikiEditor/dialogs/button_disabled.png ) repeat-x scroll 50% 100% !important;
5550 }
5651 /* Disables the annoying dashed border Firefox puts on active buttons */
57 -.ui-dialog .ui-dialog-buttonpane button::-moz-focus-inner {
 52+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button::-moz-focus-inner {
5853 border: 0;
5954 }
60 -.ui-widget-header {
 55+.wikiEditor-toolbar-dialog .ui-widget-header {
6156 background: #f0f0f0 url( ../images/wikiEditor/dialogs/titlebar_fade.png ) repeat-x scroll 50% 100% !important;
6257 }
6358 /* FIXME: Should just update the icon sprite if we're keeping this X */
64 -.ui-icon-closethick {
 59+.wikiEditor-toolbar-dialog .ui-icon-closethick {
6560 background: url( ../images/wikiEditor/dialogs/close_x.png ) no-repeat 50% 50% !important;
6661 }
67 -.ui-dialog .ui-dialog-buttonpane {
 62+.wikiEditor-toolbar-dialog .ui-dialog-buttonpane {
6863 margin-top: 0 !important;
6964 padding:0.3em 1.4em 0.5em 1.4em !important;
7065 }
7166
72 -.ui-dialog-content fieldset{
 67+.wikiEditor-toolbar-dialog .ui-dialog-content fieldset{
7368 border: none !important;
7469 margin: 0 !important;
7570 padding: 0 !important;
7671 }
77 -.ui-widget-header {
 72+.wikiEditor-toolbar-dialog .ui-widget-header {
7873 border-bottom:1px solid #6bc8f3 !important;
7974 }
80 -.ui-dialog-content input[type=text] {
 75+.wikiEditor-toolbar-dialog .ui-dialog-content input[type=text] {
8176 -moz-box-sizing: border-box;
8277 -ms-box-sizing: border-box;
8378 -webkit-box-sizing: border-box;
8479 -khtml-box-sizing: border-box;
8580 }
86 -.ui-dialog-content input[type="radio"],
87 -.ui-dialog-content input[type="checkbox"] {
 81+.wikiEditor-toolbar-dialog .ui-dialog-content input[type="radio"],
 82+.wikiEditor-toolbar-dialog .ui-dialog-content input[type="checkbox"] {
8883 margin-left: 0;
8984 }
90 -body.ltr .ui-dialog .ui-dialog-titlebar-close {
 85+body.ltr .wikiEditor-toolbar-dialog .ui-dialog-titlebar-close {
9186 right: 0.9em;
9287 }
9388 .wikieditor-toolbar-field-wrapper {
@@ -116,21 +111,21 @@
117112 body.rtl #wikieditor-toolbar-table-dialog .wikieditor-toolbar-table-preview-wrapper {
118113 float: left;
119114 }
120 -body.rtl .ui-widget .wikieditor-toolbar-table-preview-wrapper table {
 115+body.rtl .wikiEditor-toolbar-dialog .wikieditor-toolbar-table-preview-wrapper table {
121116 margin-left: 1em;
122117 margin-right: 0;
123118 }
124119 .wikieditor-toolbar-table-preview-content * {
125120 cursor: default;
126121 }
127 -.ui-widget .wikieditor-toolbar-table-preview-wrapper table {
 122+.wikiEditor-toolbar-dialog .wikieditor-toolbar-table-preview-wrapper table {
128123 width: 100% !important;
129124 }
130 -.ui-widget .wikieditor-toolbar-table-preview-content table td {
 125+.wikiEditor-toolbar-dialog .wikieditor-toolbar-table-preview-content table td {
131126 padding: 10px 4px !important;
132127 height: auto !important;
133128 }
134 -.ui-widget .wikieditor-toolbar-table-preview-content table th {
 129+.wikiEditor-toolbar-dialog .wikieditor-toolbar-table-preview-content table th {
135130 padding: 7px 3px !important;
136131 }
137132 .wikieditor-toolbar-table-dimension-fields .wikieditor-toolbar-field-wrapper {
@@ -143,7 +138,7 @@
144139 margin-right: 0px;
145140 margin-left: 20px;
146141 }
147 -.ui-dialog .ui-dialog-content {
 142+.wikiEditor-toolbar-dialog .ui-dialog-content {
148143 padding: 30px 20px 0 !important;
149144 }
150145 .wikieditor-toolbar-dialog-wrapper {
@@ -152,15 +147,15 @@
153148 /* REPLACE Dialog */
154149
155150 /* RTL Changes */
156 -body.rtl .ui-dialog .ui-dialog-buttonpane button {
 151+body.rtl .wikiEditor-toolbar-dialog .ui-dialog-buttonpane button {
157152 float: left;
158153 margin: 0.5em 0.4em 0.5em 0 !important;
159154 }
160 -body.rtl .ui-dialog .ui-dialog-titlebar-close {
 155+body.rtl .wikiEditor-toolbar-dialog .ui-dialog-titlebar-close {
161156 left: 0.9em;
162157 right: auto;
163158 }
164 -body.rtl .ui-dialog .ui-dialog-title {
 159+body.rtl .wikiEditor-toolbar-dialog .ui-dialog-title {
165160 float:right;
166161 }
167162 /* Self Clearing Floats */
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/WikiEditor/WikiEditor.hooks.php
@@ -16,14 +16,14 @@
1717 array( 'src' => 'Modules/Preview/Preview.js', 'version' => 6 ),
1818 array( 'src' => 'Modules/Publish/Publish.js', 'version' => 6 ),
1919 array( 'src' => 'Modules/Toc/Toc.js', 'version' => 7 ),
20 - array( 'src' => 'Modules/Toolbar/Toolbar.js', 'version' => 37 ),
 20+ array( 'src' => 'Modules/Toolbar/Toolbar.js', 'version' => 40 ),
2121 array( 'src' => 'Modules/TemplateEditor/TemplateEditor.js', 'version' => 4 ),
2222 ),
2323 'combined' => array(
24 - array( 'src' => 'WikiEditor.combined.js', 'version' => 39 ),
 24+ array( 'src' => 'WikiEditor.combined.js', 'version' => 42 ),
2525 ),
2626 'minified' => array(
27 - array( 'src' => 'WikiEditor.combined.min.js', 'version' => 39 ),
 27+ array( 'src' => 'WikiEditor.combined.min.js', 'version' => 42 ),
2828 ),
2929 );
3030 static $messages = array(
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/WikiEditor/WikiEditor.combined.js
@@ -929,26 +929,27 @@
930930 }
931931 return s.match( arguments.callee.regex );
932932 }
 933+ // Updates the status indicator above the target link
 934+ function updateWidget( status ) {
 935+ $j( '#wikieditor-toolbar-link-int-target-status' ).children().hide();
 936+ $j( '#wikieditor-toolbar-link-int-target' ).parent()
 937+ .removeClass( 'status-invalid status-external status-notexists status-exists status-loading' );
 938+ if ( status ) {
 939+ $j( '#wikieditor-toolbar-link-int-target-status-' + status ).show();
 940+ $j( '#wikieditor-toolbar-link-int-target' ).parent().addClass( 'status-' + status );
 941+ }
 942+ if ( status == 'invalid' ) {
 943+ $j( '.ui-dialog:visible .ui-dialog-buttonpane button:first' )
 944+ .attr( 'disabled', true )
 945+ .addClass( 'disabled' );
 946+ } else {
 947+ $j( '.ui-dialog:visible .ui-dialog-buttonpane button:first' )
 948+ .removeAttr('disabled')
 949+ .removeClass('disabled');
 950+ }
 951+ }
933952 // Updates the UI to show if the page title being inputed by the user exists or not
934953 function updateExistence() {
935 - function updateWidget( status ) {
936 - $j( '#wikieditor-toolbar-link-int-target-status' ).children().hide();
937 - $j( '#wikieditor-toolbar-link-int-target' ).parent()
938 - .removeClass( 'status-invalid status-external status-notexists status-exists status-loading' );
939 - if ( status ) {
940 - $j( '#wikieditor-toolbar-link-int-target-status-' + status ).show();
941 - $j( '#wikieditor-toolbar-link-int-target' ).parent().addClass( 'status-' + status );
942 - }
943 - if ( status == 'invalid' ) {
944 - $j( '.ui-dialog:visible .ui-dialog-buttonpane button:first' )
945 - .attr( 'disabled', true )
946 - .addClass( 'disabled' );
947 - } else {
948 - $j( '.ui-dialog:visible .ui-dialog-buttonpane button:first' )
949 - .removeAttr('disabled')
950 - .removeClass('disabled');
951 - }
952 - }
953954 // Abort previous request
954955 var request = $j( '#wikieditor-toolbar-link-int-target-status' ).data( 'request' );
955956 if ( request ) {
@@ -1008,6 +1009,12 @@
10091010 } )
10101011 );
10111012 }
 1013+ $j( '#wikieditor-toolbar-link-type-int, #wikieditor-toolbar-link-type-ext' ).click( function() {
 1014+ if( $j( '#wikieditor-toolbar-link-type-ext' ).is( ':checked' ) )
 1015+ updateWidget( 'external' );
 1016+ if( $j( '#wikieditor-toolbar-link-type-int' ).is( ':checked' ) )
 1017+ updateExistence();
 1018+ });
10121019 // Set labels of tabs based on rel values
10131020 var u = mw.usability;
10141021 $j(this).find( '[rel]' ).each( function() {
@@ -1173,16 +1180,20 @@
11741181 },
11751182 dialog: {
11761183 width: 500,
 1184+ dialogClass: 'wikiEditor-toolbar-dialog',
11771185 buttons: {
11781186 'wikieditor-toolbar-tool-link-insert': function() {
11791187 function escapeInternalText( s ) {
 1188+ // FIXME: Should this escape [[ too? Seems to work without that
11801189 return s.replace( /(]{2,})/g, '<nowiki>$1</nowiki>' );
11811190 }
11821191 function escapeExternalTarget( s ) {
11831192 return s.replace( / /g, '%20' )
 1193+ .replace( /\[/g, '%5B' )
11841194 .replace( /]/g, '%5D' );
11851195 }
11861196 function escapeExternalText( s ) {
 1197+ // FIXME: Should this escape [ too? Seems to work without that
11871198 return s.replace( /(]+)/g, '<nowiki>$1</nowiki>' );
11881199 }
11891200 var insertText = '';
@@ -1450,6 +1461,7 @@
14511462 },
14521463 dialog: {
14531464 resizable: false,
 1465+ dialogClass: 'wikiEditor-toolbar-dialog',
14541466 width: 590,
14551467 buttons: {
14561468 'wikieditor-toolbar-tool-table-insert': function() {
@@ -1682,6 +1694,7 @@
16831695 },
16841696 dialog: {
16851697 width: 500,
 1698+ dialogClass: 'wikiEditor-toolbar-dialog',
16861699 buttons: {
16871700 'wikieditor-toolbar-tool-replace-button-findnext': function( e ) {
16881701 $j(this).closest( '.ui-dialog' ).data( 'dialogaction', e.target );
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/WikiEditor/WikiEditor.combined.min.js
@@ -27,9 +27,9 @@
2828 </div>\
2929 </fieldset>',init:function(){function isExternalLink(s){if(typeof arguments.callee.regex=='undefined'){arguments.callee.regex=new RegExp("(^("+wgUrlProtocols+"))|(^www\\.)|([^.]\\.[a-z]{2,}($|\\/))",'i');}
3030 return s.match(arguments.callee.regex);}
31 -function updateExistence(){function updateWidget(status){$j('#wikieditor-toolbar-link-int-target-status').children().hide();$j('#wikieditor-toolbar-link-int-target').parent().removeClass('status-invalid status-external status-notexists status-exists status-loading');if(status){$j('#wikieditor-toolbar-link-int-target-status-'+status).show();$j('#wikieditor-toolbar-link-int-target').parent().addClass('status-'+status);}
 31+function updateWidget(status){$j('#wikieditor-toolbar-link-int-target-status').children().hide();$j('#wikieditor-toolbar-link-int-target').parent().removeClass('status-invalid status-external status-notexists status-exists status-loading');if(status){$j('#wikieditor-toolbar-link-int-target-status-'+status).show();$j('#wikieditor-toolbar-link-int-target').parent().addClass('status-'+status);}
3232 if(status=='invalid'){$j('.ui-dialog:visible .ui-dialog-buttonpane button:first').attr('disabled',true).addClass('disabled');}else{$j('.ui-dialog:visible .ui-dialog-buttonpane button:first').removeAttr('disabled').removeClass('disabled');}}
33 -var request=$j('#wikieditor-toolbar-link-int-target-status').data('request');if(request){request.abort();}
 33+function updateExistence(){var request=$j('#wikieditor-toolbar-link-int-target-status').data('request');if(request){request.abort();}
3434 var target=$j('#wikieditor-toolbar-link-int-target').val();var cache=$j('#wikieditor-toolbar-link-int-target-status').data('existencecache');if(cache[target]){updateWidget(cache[target]);return;}
3535 if(target==''){updateWidget(false);return;}
3636 if(isExternalLink(target)){updateWidget('external');return;}
@@ -38,7 +38,9 @@
3939 status='notexists';else if(typeof page.invalid!='undefined')
4040 status='invalid';}
4141 cache[target]=status;updateWidget(status);}}));}
42 -var u=mw.usability;$j(this).find('[rel]').each(function(){$j(this).text(u.getMsg($j(this).attr('rel')));});$j('#wikieditor-toolbar-link-int-target').data('tooltip',u.getMsg('wikieditor-toolbar-tool-link-int-target-tooltip'));$j('#wikieditor-toolbar-link-int-text').data('tooltip',u.getMsg('wikieditor-toolbar-tool-link-int-text-tooltip'));$j('#wikieditor-toolbar-link-int-target, #wikieditor-toolbar-link-int-text').each(function(){var tooltip=u.getMsg($j(this).attr('id')+'-tooltip');if($j(this).val()=='')
 42+$j('#wikieditor-toolbar-link-type-int, #wikieditor-toolbar-link-type-ext').click(function(){if($j('#wikieditor-toolbar-link-type-ext').is(':checked'))
 43+updateWidget('external');if($j('#wikieditor-toolbar-link-type-int').is(':checked'))
 44+updateExistence();});var u=mw.usability;$j(this).find('[rel]').each(function(){$j(this).text(u.getMsg($j(this).attr('rel')));});$j('#wikieditor-toolbar-link-int-target').data('tooltip',u.getMsg('wikieditor-toolbar-tool-link-int-target-tooltip'));$j('#wikieditor-toolbar-link-int-text').data('tooltip',u.getMsg('wikieditor-toolbar-tool-link-int-text-tooltip'));$j('#wikieditor-toolbar-link-int-target, #wikieditor-toolbar-link-int-text').each(function(){var tooltip=u.getMsg($j(this).attr('id')+'-tooltip');if($j(this).val()=='')
4345 $j(this).val($j(this).data('tooltip')).addClass('wikieditor-toolbar-dialog-hint');}).focus(function(){$j(this).removeClass('wikieditor-toolbar-dialog-hint');if($j(this).val()==$j(this).data('tooltip'))
4446 $j(this).val('');}).bind('blur change',function(){if($j(this).val()=='')
4547 $j(this).val($j(this).data('tooltip')).addClass('wikieditor-toolbar-dialog-hint');else
@@ -51,8 +53,8 @@
5254 updateExistence();});$j('#wikieditor-toolbar-link-int-target').data('suggcache',{}).suggestions({fetch:function(query){var that=this;var title=$j(this).val();if(isExternalLink(title)||title.indexOf('|')!=-1||title==''){$j(this).suggestions('suggestions',[]);return;}
5355 var cache=$j(this).data('suggcache');if(typeof cache[title]!='undefined'){$j(this).suggestions('suggestions',cache[title]);return;}
5456 var request=$j.ajax({url:wgScriptPath+'/api.php',data:{'action':'opensearch','search':title,'namespace':0,'suggest':'','format':'json'},dataType:'json',success:function(data){cache[title]=data[1];$j(that).suggestions('suggestions',data[1]);}});$j(this).data('request',request);},cancel:function(){var request=$j(this).data('request');if(request)
55 -request.abort();}});},dialog:{width:500,buttons:{'wikieditor-toolbar-tool-link-insert':function(){function escapeInternalText(s){return s.replace(/(]{2,})/g,'<nowiki>$1</nowiki>');}
56 -function escapeExternalTarget(s){return s.replace(/ /g,'%20').replace(/]/g,'%5D');}
 57+request.abort();}});},dialog:{width:500,dialogClass:'wikiEditor-toolbar-dialog',buttons:{'wikieditor-toolbar-tool-link-insert':function(){function escapeInternalText(s){return s.replace(/(]{2,})/g,'<nowiki>$1</nowiki>');}
 58+function escapeExternalTarget(s){return s.replace(/ /g,'%20').replace(/\[/g,'%5B').replace(/]/g,'%5D');}
5759 function escapeExternalText(s){return s.replace(/(]+)/g,'<nowiki>$1</nowiki>');}
5860 var insertText='';var whitespace=$j('#wikieditor-toolbar-link-dialog').data('whitespace');var target=$j('#wikieditor-toolbar-link-int-target').val();var text=$j('#wikieditor-toolbar-link-int-text').val();var u=mw.usability;if(target==''){alert(u.getMsg('wikieditor-toolbar-tool-link-empty'));return;}
5961 if($j.trim(text)==''){text='';}
@@ -129,7 +131,7 @@
130132 </div>\
131133 </div></div>',init:function(){$j(this).find('[rel]').each(function(){$j(this).text(mw.usability.getMsg($j(this).attr('rel')));});$j('#wikieditor-toolbar-table-dimensions-rows').val(4);$j('#wikieditor-toolbar-table-dimensions-columns').val(3);$j('#wikieditor-toolbar-table-wikitable').click(function(){$j('.wikieditor-toolbar-table-preview').toggleClass('wikitable');});$j('#wikieditor-toolbar-table-preview').clone().attr('id','wikieditor-toolbar-table-preview2').addClass('sortable').insertAfter($j('#wikieditor-toolbar-table-preview')).hide();if(typeof ts_makeSortable=='function')
132134 ts_makeSortable($j('#wikieditor-toolbar-table-preview2').get(0));$j('#wikieditor-toolbar-table-sortable').click(function(){$j('#wikieditor-toolbar-table-preview').hide().attr('id','wikieditor-toolbar-table-preview3');$j('#wikieditor-toolbar-table-preview2').attr('id','wikieditor-toolbar-table-preview').show();$j('#wikieditor-toolbar-table-preview3').attr('id','wikieditor-toolbar-table-preview2');});$j('#wikieditor-toolbar-table-dimensions-header').click(function(){var headerHTML=$j('.wikieditor-toolbar-table-preview-header').html();var hiddenHTML=$j('.wikieditor-toolbar-table-preview-hidden').html();$j('.wikieditor-toolbar-table-preview-header').html(hiddenHTML);$j('.wikieditor-toolbar-table-preview-hidden').html(headerHTML);if(typeof ts_makeSortable=='function')
133 -ts_makeSortable($j('#wikieditor-toolbar-table-preview, #wikieditor-toolbar-table-preview2').filter('.sortable').get(0));});},dialog:{resizable:false,width:590,buttons:{'wikieditor-toolbar-tool-table-insert':function(){var rowsVal=$j('#wikieditor-toolbar-table-dimensions-rows').val();var colsVal=$j('#wikieditor-toolbar-table-dimensions-columns').val();var rows=parseInt(rowsVal,10);var cols=parseInt(colsVal,10);var header=Math.min(1,$j('#wikieditor-toolbar-table-dimensions-header:checked').size());var u=mw.usability;if(isNaN(rows)||isNaN(cols)||rows!=rowsVal||cols!=colsVal){alert(u.getMsg('wikieditor-toolbar-tool-table-invalidnumber'));return;}
 135+ts_makeSortable($j('#wikieditor-toolbar-table-preview, #wikieditor-toolbar-table-preview2').filter('.sortable').get(0));});},dialog:{resizable:false,dialogClass:'wikiEditor-toolbar-dialog',width:590,buttons:{'wikieditor-toolbar-tool-table-insert':function(){var rowsVal=$j('#wikieditor-toolbar-table-dimensions-rows').val();var colsVal=$j('#wikieditor-toolbar-table-dimensions-columns').val();var rows=parseInt(rowsVal,10);var cols=parseInt(colsVal,10);var header=Math.min(1,$j('#wikieditor-toolbar-table-dimensions-header:checked').size());var u=mw.usability;if(isNaN(rows)||isNaN(cols)||rows!=rowsVal||cols!=colsVal){alert(u.getMsg('wikieditor-toolbar-tool-table-invalidnumber'));return;}
134136 if(rows+header==0||cols==0){alert(u.getMsg('wikieditor-toolbar-tool-table-zero'));return;}
135137 if(rows*cols>1000){alert(u.getMsg('wikieditor-toolbar-tool-table-toomany',1000));return;}
136138 var headerText=u.getMsg('wikieditor-toolbar-tool-table-example-header');var normalText=u.getMsg('wikieditor-toolbar-tool-table-example');var table="";for(var r=0;r<rows+header;r++){table+="|-\n";for(var c=0;c<cols;c++){var isHeader=(r+1==header);var delim=isHeader?'!':'|';if(c>0){delim+=delim;}
@@ -174,6 +176,6 @@
175177 if(!match){$j('#wikieditor-toolbar-replace-nomatch').show();}else if(mode=='replaceAll'){var index;for(var i=0;i<match.length;i++){index=s.indexOf(match[i]);if(index==-1){break;}
176178 s=s.substr(index+match[i].length);var start=index+offset;var end=start+match[i].length;var newEnd=start+replaceStr.length;$textarea.textSelection('setSelection',{'start':start,'end':end}).textSelection('encapsulateSelection',{'peri':replaceStr,'replace':true}).textSelection('setSelection',{'start':start,'end':newEnd});offset=newEnd;}
177179 $j('#wikieditor-toolbar-replace-success').text(u.getMsg('wikieditor-toolbar-tool-replace-success',match.length)).show();$j(this).data('offset',0);}else{var start=match.index+offset;var end=start+match[0].length;var newEnd=start+replaceStr.length;$textarea.textSelection('setSelection',{'start':start,'end':end});if(mode=='replace'){$textarea.textSelection('encapsulateSelection',{'peri':replaceStr,'replace':true}).textSelection('setSelection',{'start':start,'end':newEnd});}
178 -$textarea.textSelection('scrollToCaretPosition');$j(this).data('offset',mode=='replace'?newEnd:end);}});},dialog:{width:500,buttons:{'wikieditor-toolbar-tool-replace-button-findnext':function(e){$j(this).closest('.ui-dialog').data('dialogaction',e.target);$j(this).data('replaceCallback').call(this,'find');},'wikieditor-toolbar-tool-replace-button-replacenext':function(e){$j(this).closest('.ui-dialog').data('dialogaction',e.target);$j(this).data('replaceCallback').call(this,'replace');},'wikieditor-toolbar-tool-replace-button-replaceall':function(e){$j(this).closest('.ui-dialog').data('dialogaction',e.target);$j(this).data('replaceCallback').call(this,'replaceAll');},'wikieditor-toolbar-tool-replace-close':function(){$j(this).dialog('close');}},open:function(){$j(this).data('offset',0);$j('#wikieditor-toolbar-replace-search').focus();$j('#wikieditor-toolbar-replace-nomatch, #wikieditor-toolbar-replace-success, #wikieditor-toolbar-replace-emptysearch, #wikieditor-toolbar-replace-invalidregex').hide();if(!($j(this).data('onetimeonlystuff'))){$j(this).data('onetimeonlystuff',true);$j(this).closest('.ui-dialog').keypress(function(e){if((e.keyCode||e.which)==13){var button=$j(this).data('dialogaction')||$j(this).find('button:first');button.click();e.preventDefault();}});$j(this).closest('.ui-dialog').find('button').focus(function(){$j(this).closest('.ui-dialog').data('dialogaction',this);});}
 180+$textarea.textSelection('scrollToCaretPosition');$j(this).data('offset',mode=='replace'?newEnd:end);}});},dialog:{width:500,dialogClass:'wikiEditor-toolbar-dialog',buttons:{'wikieditor-toolbar-tool-replace-button-findnext':function(e){$j(this).closest('.ui-dialog').data('dialogaction',e.target);$j(this).data('replaceCallback').call(this,'find');},'wikieditor-toolbar-tool-replace-button-replacenext':function(e){$j(this).closest('.ui-dialog').data('dialogaction',e.target);$j(this).data('replaceCallback').call(this,'replace');},'wikieditor-toolbar-tool-replace-button-replaceall':function(e){$j(this).closest('.ui-dialog').data('dialogaction',e.target);$j(this).data('replaceCallback').call(this,'replaceAll');},'wikieditor-toolbar-tool-replace-close':function(){$j(this).dialog('close');}},open:function(){$j(this).data('offset',0);$j('#wikieditor-toolbar-replace-search').focus();$j('#wikieditor-toolbar-replace-nomatch, #wikieditor-toolbar-replace-success, #wikieditor-toolbar-replace-emptysearch, #wikieditor-toolbar-replace-invalidregex').hide();if(!($j(this).data('onetimeonlystuff'))){$j(this).data('onetimeonlystuff',true);$j(this).closest('.ui-dialog').keypress(function(e){if((e.keyCode||e.which)==13){var button=$j(this).data('dialogaction')||$j(this).find('button:first');button.click();e.preventDefault();}});$j(this).closest('.ui-dialog').find('button').focus(function(){$j(this).closest('.ui-dialog').data('dialogaction',this);});}
179181 var dialog=$j(this).closest('.ui-dialog');var that=this;$j($j(this).data('context').$iframe[0].contentWindow.document).bind('keypress.srdialog',function(e){if((e.keyCode||e.which)==13){var button=dialog.data('dialogaction')||dialog.find('button:first');button.click();e.preventDefault();}else if((e.keyCode||e.which)==27){$j(that).dialog('close');}});},close:function(){$j($j(this).data('context').$iframe[0].contentWindow.document).unbind('keypress.srdialog');$j(this).data('context').$iframe[0].contentWindow.focus();$j(this).closest('.ui-dialog').data('dialogaction',false);}}}}});}});$j(document).ready(function(){if(!wgWikiEditorEnabledModules.templateEditor){return true;}
180182 if($j.fn.wikiEditor){$j('textarea#wpTextbox1').wikiEditor('addModule','templateEditor');}});
\ No newline at end of file
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/WikiEditor/Modules/TemplateEditor/TemplateEditor.i18n.php
@@ -195,7 +195,7 @@
196196 * @author Robby
197197 */
198198 $messages['lb'] = array(
199 - 'wikieditor-template-editor-preference' => "D'Änner vu Wiki-Schablounen op der Basis vu Formulairen aschalten",
 199+ 'wikieditor-template-editor-preference' => "D'Ännere vu Wiki-Schablounen op der Basis vu Formulairen aschalten",
200200 );
201201
202202 /** Macedonian (Македонски)
@@ -333,15 +333,17 @@
334334
335335 /** Simplified Chinese (‪中文(简体)‬)
336336 * @author Gaoxuewei
 337+ * @author Liangent
337338 */
338339 $messages['zh-hans'] = array(
339 - 'wikieditor-template-editor-preference' => '启用维基模板的表单式编辑',
 340+ 'wikieditor-template-editor-preference' => '启用wiki模板的表单式编辑',
340341 );
341342
342343 /** Traditional Chinese (‪中文(繁體)‬)
343344 * @author Gaoxuewei
 345+ * @author Liangent
344346 */
345347 $messages['zh-hant'] = array(
346 - 'wikieditor-template-editor-preference' => '啟用維基模板的表單式編輯',
 348+ 'wikieditor-template-editor-preference' => '啟用wiki模板的表單式編輯',
347349 );
348350
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/WikiEditor/Modules/Toolbar/Toolbar.i18n.php
@@ -1757,7 +1757,7 @@
17581758 'wikieditor-toolbar-tool-link-title' => 'Ubaci link',
17591759 'wikieditor-toolbar-tool-link-int' => 'Na wiki stranicu',
17601760 'wikieditor-toolbar-tool-link-int-target' => 'Naslov stranice:',
1761 - 'wikieditor-toolbar-tool-link-int-target-tooltip' => 'Unesite naslov stranice',
 1761+ 'wikieditor-toolbar-tool-link-int-target-tooltip' => 'Naslov stranice ili URL',
17621762 'wikieditor-toolbar-tool-link-int-text' => 'Tekst linka:',
17631763 'wikieditor-toolbar-tool-link-int-text-tooltip' => 'Unesite tekst koji bi trebao biti prikazan',
17641764 'wikieditor-toolbar-tool-link-ext' => 'Na vanjsku web stranicu',
@@ -2794,7 +2794,7 @@
27952795 'wikieditor-toolbar-tool-link-title' => 'Link einfügen',
27962796 'wikieditor-toolbar-tool-link-int' => 'Zu einer Wiki-Seite',
27972797 'wikieditor-toolbar-tool-link-int-target' => 'Seitentitel:',
2798 - 'wikieditor-toolbar-tool-link-int-target-tooltip' => 'Seitentitel eingeben',
 2798+ 'wikieditor-toolbar-tool-link-int-target-tooltip' => 'Titel der Seite oder URL',
27992799 'wikieditor-toolbar-tool-link-int-text' => 'Linktitel:',
28002800 'wikieditor-toolbar-tool-link-int-text-tooltip' => 'Text eingeben, der angezeigt werden soll',
28012801 'wikieditor-toolbar-tool-link-ext' => 'Zu einer externen Internetseite',
@@ -4173,7 +4173,7 @@
41744174 'wikieditor-toolbar-tool-link-title' => 'Sartu lotura',
41754175 'wikieditor-toolbar-tool-link-int' => 'Wiki orrialde batera',
41764176 'wikieditor-toolbar-tool-link-int-target' => 'Orrialdearen izenburua:',
4177 - 'wikieditor-toolbar-tool-link-int-target-tooltip' => 'Idatzi orriaren izenburua',
 4177+ 'wikieditor-toolbar-tool-link-int-target-tooltip' => 'Orriaren izenburua edo URL',
41784178 'wikieditor-toolbar-tool-link-int-text' => 'Lotutako testua:',
41794179 'wikieditor-toolbar-tool-link-int-text-tooltip' => 'Idatzi erakutsi beharreko testua',
41804180 'wikieditor-toolbar-tool-link-ext' => 'Kanpoko orrialde batera',
@@ -4405,7 +4405,7 @@
44064406 'wikieditor-toolbar-tool-link-title' => 'Lisää linkki',
44074407 'wikieditor-toolbar-tool-link-int' => 'Wikisivuun',
44084408 'wikieditor-toolbar-tool-link-int-target' => 'Artikkelin otsikko:',
4409 - 'wikieditor-toolbar-tool-link-int-target-tooltip' => 'Syötä sivun otsikko',
 4409+ 'wikieditor-toolbar-tool-link-int-target-tooltip' => 'Sivun otsikko tai URL',
44104410 'wikieditor-toolbar-tool-link-int-text' => 'Linkin teksti:',
44114411 'wikieditor-toolbar-tool-link-int-text-tooltip' => 'Syötä näytettävä teksti',
44124412 'wikieditor-toolbar-tool-link-ext' => 'Ulkoiseen sivustoon',
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/WikiEditor/Modules/Toolbar/Toolbar.js
@@ -880,26 +880,27 @@
881881 }
882882 return s.match( arguments.callee.regex );
883883 }
 884+ // Updates the status indicator above the target link
 885+ function updateWidget( status ) {
 886+ $j( '#wikieditor-toolbar-link-int-target-status' ).children().hide();
 887+ $j( '#wikieditor-toolbar-link-int-target' ).parent()
 888+ .removeClass( 'status-invalid status-external status-notexists status-exists status-loading' );
 889+ if ( status ) {
 890+ $j( '#wikieditor-toolbar-link-int-target-status-' + status ).show();
 891+ $j( '#wikieditor-toolbar-link-int-target' ).parent().addClass( 'status-' + status );
 892+ }
 893+ if ( status == 'invalid' ) {
 894+ $j( '.ui-dialog:visible .ui-dialog-buttonpane button:first' )
 895+ .attr( 'disabled', true )
 896+ .addClass( 'disabled' );
 897+ } else {
 898+ $j( '.ui-dialog:visible .ui-dialog-buttonpane button:first' )
 899+ .removeAttr('disabled')
 900+ .removeClass('disabled');
 901+ }
 902+ }
884903 // Updates the UI to show if the page title being inputed by the user exists or not
885904 function updateExistence() {
886 - function updateWidget( status ) {
887 - $j( '#wikieditor-toolbar-link-int-target-status' ).children().hide();
888 - $j( '#wikieditor-toolbar-link-int-target' ).parent()
889 - .removeClass( 'status-invalid status-external status-notexists status-exists status-loading' );
890 - if ( status ) {
891 - $j( '#wikieditor-toolbar-link-int-target-status-' + status ).show();
892 - $j( '#wikieditor-toolbar-link-int-target' ).parent().addClass( 'status-' + status );
893 - }
894 - if ( status == 'invalid' ) {
895 - $j( '.ui-dialog:visible .ui-dialog-buttonpane button:first' )
896 - .attr( 'disabled', true )
897 - .addClass( 'disabled' );
898 - } else {
899 - $j( '.ui-dialog:visible .ui-dialog-buttonpane button:first' )
900 - .removeAttr('disabled')
901 - .removeClass('disabled');
902 - }
903 - }
904905 // Abort previous request
905906 var request = $j( '#wikieditor-toolbar-link-int-target-status' ).data( 'request' );
906907 if ( request ) {
@@ -959,6 +960,12 @@
960961 } )
961962 );
962963 }
 964+ $j( '#wikieditor-toolbar-link-type-int, #wikieditor-toolbar-link-type-ext' ).click( function() {
 965+ if( $j( '#wikieditor-toolbar-link-type-ext' ).is( ':checked' ) )
 966+ updateWidget( 'external' );
 967+ if( $j( '#wikieditor-toolbar-link-type-int' ).is( ':checked' ) )
 968+ updateExistence();
 969+ });
963970 // Set labels of tabs based on rel values
964971 var u = mw.usability;
965972 $j(this).find( '[rel]' ).each( function() {
@@ -1124,16 +1131,20 @@
11251132 },
11261133 dialog: {
11271134 width: 500,
 1135+ dialogClass: 'wikiEditor-toolbar-dialog',
11281136 buttons: {
11291137 'wikieditor-toolbar-tool-link-insert': function() {
11301138 function escapeInternalText( s ) {
 1139+ // FIXME: Should this escape [[ too? Seems to work without that
11311140 return s.replace( /(]{2,})/g, '<nowiki>$1</nowiki>' );
11321141 }
11331142 function escapeExternalTarget( s ) {
11341143 return s.replace( / /g, '%20' )
 1144+ .replace( /\[/g, '%5B' )
11351145 .replace( /]/g, '%5D' );
11361146 }
11371147 function escapeExternalText( s ) {
 1148+ // FIXME: Should this escape [ too? Seems to work without that
11381149 return s.replace( /(]+)/g, '<nowiki>$1</nowiki>' );
11391150 }
11401151 var insertText = '';
@@ -1401,6 +1412,7 @@
14021413 },
14031414 dialog: {
14041415 resizable: false,
 1416+ dialogClass: 'wikiEditor-toolbar-dialog',
14051417 width: 590,
14061418 buttons: {
14071419 'wikieditor-toolbar-tool-table-insert': function() {
@@ -1633,6 +1645,7 @@
16341646 },
16351647 dialog: {
16361648 width: 500,
 1649+ dialogClass: 'wikiEditor-toolbar-dialog',
16371650 buttons: {
16381651 'wikieditor-toolbar-tool-replace-button-findnext': function( e ) {
16391652 $j(this).closest( '.ui-dialog' ).data( 'dialogaction', e.target );
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/PrefStats/PrefStats.i18n.php
@@ -1392,12 +1392,12 @@
13931393 Кликнете на едно од нив за да ги видите статистиките за него.',
13941394 'prefstats-noprefs' => 'Моментално не се следите никакви прилагодувања.
13951395 Конфигурирајте го $wgPrefStatsTrackPrefs за да следите прилагодувања.',
1396 - 'prefstats-counters' => '* $1 {{PLURAL:$1|корисник ја има|корисници ја имаат}} вклучено оваа можност од кога е активирана статистиката на прилагодувања
1397 -** $2 {{PLURAL:$2|корисник сеуште ја чува вклучена|корисници сеуште ја чуваат вклучена}}
1398 -** $3 {{PLURAL:$3|корисникот во меѓувреме ја оневозможил|корисниците во меѓувреме ја оневозможиле}}',
 1396+ 'prefstats-counters' => '* $1 {{PLURAL:$1|корисник ја има|корисници ја имаат}} вклучено оваа можност откога се активирани статистиките за прилагодувања
 1397+** $2 {{PLURAL:$2|корисник сè уште ја чува вклучена|корисници сè уште ја чуваат вклучена}}
 1398+** $3 {{PLURAL:$3|корисник во меѓувреме ја оневозможил|корисници во меѓувреме ја оневозможиле}}',
13991399 'prefstats-counters-expensive' => '* $1 {{PLURAL:$1|корисник ја има|корисници ја имаат}} вклучено оваа можност од кога е активирана статистиката на прилагодувања
14001400 ** $2 {{PLURAL:$2|корисник сè уште ја чува вклучена|корисници сè уште ја чуваат вклучена}}
1401 -** $3 {{PLURAL:$3|корисникот во меѓувреме ја оневозможил|корисниците во меѓувреме ја оневозможиле}}
 1401+** $3 {{PLURAL:$3|корисник во меѓувреме ја оневозможил|корисници во меѓувреме ја оневозможиле}}
14021402 * Вкупно $4 {{PLURAL:$4|корисник ја има вклучено оваа можност|корисници ја имаат вклучено оваа можност}}',
14031403 'prefstats-xaxis' => 'Времетрање (часови)',
14041404 'prefstats-factors' => 'Поглед по: $1',
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/js/plugins.combined.js
@@ -6513,7 +6513,7 @@
65146514 }
65156515 // Check over each browser condition to determine if we are running in a compatible client
65166516 var browser = $.wikiEditor.browsers[$( 'body' ).is( '.rtl' ) ? 'rtl' : 'ltr'][$.browser.name];
6517 - for ( condition in browser ) {
 6517+ for ( var condition in browser ) {
65186518 var op = browser[condition][0];
65196519 var val = browser[condition][1];
65206520 if ( typeof val == 'string' ) {
@@ -6542,7 +6542,7 @@
65436543 'autoMsg': function( object, property ) {
65446544 // Accept array of possible properties, of which the first one found will be used
65456545 if ( typeof property == 'object' ) {
6546 - for ( i in property ) {
 6546+ for ( var i in property ) {
65476547 if ( property[i] in object || property[i] + 'Msg' in object ) {
65486548 property = property[i];
65496549 break;
@@ -6623,7 +6623,13 @@
66246624 // Unique numeric ID of this instance used both for looking up and differentiating instances of wikiEditor
66256625 'instance': $.wikiEditor.instances.push( $(this) ) - 1,
66266626 // Array mapping elements in the textarea to character offsets
6627 - 'offsets': null
 6627+ 'offsets': null,
 6628+ // Cache for context.fn.htmlToText()
 6629+ 'htmlToTextMap': {},
 6630+ // The previous HTML of the iframe, stored to detect whether something really changed.
 6631+ 'oldHTML': null,
 6632+ // Same for delayedChange()
 6633+ 'oldDelayedHTML': null
66286634 };
66296635
66306636 /*
@@ -6647,12 +6653,12 @@
66486654 } else if ( typeof data == 'object' ) {
66496655 modules = data;
66506656 }
6651 - for ( module in modules ) {
 6657+ for ( var module in modules ) {
66526658 // Check for the existance of an available module with a matching name and a create function
66536659 if ( typeof module == 'string' && module in $.wikiEditor.modules ) {
66546660 // Extend the context's core API with this module's own API calls
66556661 if ( 'api' in $.wikiEditor.modules[module] ) {
6656 - for ( call in $.wikiEditor.modules[module].api ) {
 6662+ for ( var call in $.wikiEditor.modules[module].api ) {
66576663 // Modules may not overwrite existing API functions - first come, first serve
66586664 if ( !( call in context.api ) ) {
66596665 context.api[call] = $.wikiEditor.modules[module].api[call];
@@ -6686,12 +6692,23 @@
66876693 */
66886694 'change': function( event ) {
66896695 event.data.scope = 'division';
6690 - context.fn.purgeOffsets();
 6696+ var newHTML = context.$content.html();
 6697+ if ( context.oldHTML != newHTML ) {
 6698+ context.fn.purgeOffsets();
 6699+ context.oldHTML = newHTML;
 6700+ event.data.scope = 'realchange';
 6701+ }
66916702 return true;
66926703 },
66936704 'delayedChange': function( event ) {
6694 - // Redirect - since we want the same functionality
6695 - return context.evt.change( event );
 6705+ event.data.scope = 'division';
 6706+ var newHTML = context.$content.html();
 6707+ if ( context.oldDelayedHTML != newHTML ) {
 6708+ context.fn.purgeOffsets();
 6709+ context.oldDelayedHTML = newHTML;
 6710+ event.data.scope = 'realchange';
 6711+ }
 6712+ return true;
66966713 }
66976714 };
66986715
@@ -6717,7 +6734,7 @@
67186735 }
67196736 }
67206737 // Pass the event around to all modules activated on this context
6721 - for ( module in context.modules ) {
 6738+ for ( var module in context.modules ) {
67226739 if (
67236740 module in $.wikiEditor.modules &&
67246741 'evt' in $.wikiEditor.modules[module] &&
@@ -6784,22 +6801,71 @@
67856802 .appendTo( context.$ui );
67866803 },
67876804 'htmlToText': function( html ) {
 6805+ // This function is slow for large inputs, so aggressively cache input/output pairs
 6806+ if ( html in context.htmlToTextMap ) {
 6807+ return context.htmlToTextMap[html];
 6808+ }
 6809+ var origHTML = html;
 6810+
67886811 // We use this elaborate trickery for cross-browser compatibility
67896812 // IE does overzealous whitespace collapsing for $( '<pre />' ).html( html );
6790 - var $pre = $( '<pre>' +
6791 - html
 6813+ // We also do <br> and easy cases for <p> conversion here, complicated cases are handled later
 6814+ html = html
67926815 .replace( /\r?\n/g, "" ) // IE7 inserts newlines before block elements
6793 - .replace( /\<br[^\>]*\>/gi, "\n" )
67946816 .replace( /&nbsp;/g, " " ) // We inserted these to prevent IE from collapsing spaces
6795 - .replace( /\<p[^\>]*\>/gi, "\n" ) // IE uses </p><p> for user-inserted line breaks
6796 - .replace( /\<\/p[^\>]*\>/gi, "" )
6797 - .replace( /\<div[^\>]*\>/gi, "\n" ) // Webkit uses </p><p> for user-inserted line breaks
6798 - .replace( /\<\/div[^\>]*\>/gi, "" )
6799 - + '</pre>' );
6800 - // Get rid of the noincludes when getting text
 6817+ .replace( /\<br[^\>]*\>/gi, "\n" ) // <br> conversion
 6818+ .replace( /\<\/p\>\<p\>/gi, "\n" ) // Easy case for <p> conversion
 6819+ .replace( /\<\/p\>(\n*)\<p\>/gi, "$1\n" );
 6820+ // Save leading and trailing whitespace now and restore it later. IE eats it all, and even Firefox
 6821+ // won't leave everything alone
 6822+ var leading = html.match( /^\s*/ )[0];
 6823+ var trailing = html.match( /\s*$/ )[0];
 6824+ html = html.substr( leading.length, html.length - leading.length - trailing.length );
 6825+ var $pre = $( '<pre>' + html + '</pre>' );
68016826 $pre.find( '.wikiEditor-noinclude' ).each( function() { $( this ).remove(); } );
6802 - $pre.find( '.wikiEditor-tab' ).each( function() { $( this ).text( "\t" ) } );
6803 - return $pre.text();
 6827+ // Convert tabs, <p>s and <br>s back
 6828+ $pre.find( '.wikiEditor-tab' ).each( function() { $( this ).text( "\t" ); } );
 6829+ $pre.find( 'br' ).each( function() { $( this ).replaceWith( "\n" ); } );
 6830+ // Converting <p>s is wrong if there's nothing before them, so check that.
 6831+ // .find( '* + p' ) isn't good enough because textnodes aren't considered
 6832+ $pre.find( 'p' ).each( function() {
 6833+ if ( this.previousSibling || this.parentNode != $pre.get( 0 ) ) {
 6834+ var text = $( this ).text();
 6835+ // If this <p> is preceded by some text, add a \n at the beginning, and if
 6836+ // it's followed by a textnode, add a \n at the end
 6837+ // We need the traverser because there can be other weird stuff in between
 6838+
 6839+ // Check for preceding text
 6840+ // FIXME: Add an option to disable depth checking, -10 is a hack
 6841+ var t = new context.fn.rawTraverser( this.firstChild, -10, this ).prev();
 6842+ while ( t && t.node.nodeName != '#text' && t.node.nodeName != 'BR' && t.node.nodeName != 'P' ) {
 6843+ t = t.prev();
 6844+ }
 6845+ if ( t ) {
 6846+ text = "\n" + text;
 6847+ }
 6848+
 6849+ // Check for following text
 6850+ t = new context.fn.rawTraverser( this.lastChild, -10, this ).next();
 6851+ while ( t && t.node.nodeName != '#text' && t.node.nodeName != 'BR' && t.node.nodeName != 'P' ) {
 6852+ t = t.next();
 6853+ }
 6854+ if ( t && !t.inP && t.node.nodeName == '#text' && t.node.nodeValue.charAt( 0 ) != '\n'
 6855+ && t.node.nodeValue.charAt( 0 ) != '\r' ) {
 6856+ text += "\n";
 6857+ }
 6858+ $( this ).text( text );
 6859+ }
 6860+ } );
 6861+ var retval;
 6862+ if ( $.browser.msie ) {
 6863+ // IE aggressively collapses whitespace in .text() after having done DOM manipulation,
 6864+ // but for some crazy reason this does work. Also convert \r back to \n
 6865+ retval = $( '<pre>' + $pre.html() + '</pre>' ).text().replace( /\r/g, '\n' );
 6866+ } else {
 6867+ retval = $pre.text();
 6868+ }
 6869+ return context.htmlToTextMap[origHTML] = leading + retval + trailing;
68046870 },
68056871
68066872 /*
@@ -6824,6 +6890,17 @@
68256891 if ( context.$iframe[0].contentWindow.getSelection ) {
68266892 // Firefox and Opera
68276893 retval = context.$iframe[0].contentWindow.getSelection();
 6894+ if ( $.browser.opera ) {
 6895+ // Opera strips newlines in getSelection(), so we need something more sophisticated
 6896+ if ( retval.rangeCount > 0 ) {
 6897+ retval = context.fn.htmlToText( $( '<pre />' )
 6898+ .append( retval.getRangeAt( 0 ).cloneContents() )
 6899+ .html()
 6900+ );
 6901+ } else {
 6902+ retval = '';
 6903+ }
 6904+ }
68286905 } else if ( context.$iframe[0].contentWindow.document.selection ) { // should come last; Opera!
68296906 // IE
68306907 retval = context.$iframe[0].contentWindow.document.selection.createRange();
@@ -6867,25 +6944,47 @@
68686945 // Firefox and Opera
68696946 var range = context.$iframe[0].contentWindow.getSelection().getRangeAt( 0 );
68706947 if ( options.ownline ) {
 6948+ // We need to figure out if the cursor is at the start or end of a line
 6949+ var atStart = false, atEnd = false;
68716950 var body = context.$content.get( 0 );
6872 - // TODO: This'll probably break with syntax highlighting
6873 - // When the selection starts at the beginning of a line, it'll have either
6874 - // startOffset == 0 or startContainer == body
6875 - if ( range.startOffset != 0 && range.startContainer != body ) {
 6951+ if ( range.startOffset == 0 ) {
 6952+ // Start of a line
 6953+ // FIXME: Not necessarily the case with syntax highlighting or
 6954+ // template collapsing
 6955+ atStart = true;
 6956+ } else if ( range.startContainer == body ) {
 6957+ // Look up the node just before the start of the selection
 6958+ // If it's a <BR>, we're at the start of a line that starts with a
 6959+ // block element; if not, we're at the end of a line
 6960+ var n = body.firstChild;
 6961+ for ( var i = 0; i < range.startOffset - 1 && n; i++ ) {
 6962+ n = n.nextSibling;
 6963+ }
 6964+ if ( n && n.nodeName == 'BR' ) {
 6965+ atStart = true;
 6966+ } else {
 6967+ atEnd = true;
 6968+ }
 6969+ } else if ( range.startContainer.nodeName == '#text' &&
 6970+ range.startOffset == range.startContainer.nodeValue.length ) {
 6971+ // Apparently this happens when splitting text nodes
 6972+ atEnd = true;
 6973+ }
 6974+
 6975+ if ( !atStart ) {
68766976 pre = "\n" + options.pre;
68776977 }
6878 - // TODO: Will this still work with syntax highlighting?
6879 - // When the selection ends at the end of a line, it'll have endContainer == body
6880 - // and endOffset != 0
6881 - if ( range.endContainer != body || range.endOffset == 0 ) {
 6978+ if ( !atEnd ) {
68826979 post += "\n";
68836980 }
68846981 }
68856982 var insertText = "";
68866983 if ( options.splitlines ) {
6887 - for( var i = 0; i < selTextArr.length; i++ ) {
6888 - insertText = insertText + pre + selTextArr[i] + post;
6889 - if( i != selTextArr.length - 1 ) insertText += "\n";
 6984+ for( var j = 0; j < selTextArr.length; j++ ) {
 6985+ insertText = insertText + pre + selTextArr[j] + post;
 6986+ if( j != selTextArr.length - 1 ) {
 6987+ insertText += "\n";
 6988+ }
68906989 }
68916990 } else {
68926991 insertText = pre + selText + post;
@@ -6931,9 +7030,9 @@
69327031 // TODO: Clean this up. Duplicate code due to the pre-existing browser specific structure of this function
69337032 var insertText = "";
69347033 if ( options.splitlines ) {
6935 - for( var i = 0; i < selTextArr.length; i++ ) {
6936 - insertText = insertText + pre + selTextArr[i] + post;
6937 - if( i != selTextArr.length - 1 ) {
 7034+ for( var j = 0; j < selTextArr.length; j++ ) {
 7035+ insertText = insertText + pre + selTextArr[j] + post;
 7036+ if( j != selTextArr.length - 1 ) {
69387037 insertText += "\n";
69397038 }
69407039 }
@@ -7058,14 +7157,14 @@
70597158 */
70607159
70617160 /**
7062 - * Get the first element before the selection matching a certain selector.
7063 - * @param selector Selector to match. Defaults to '*'
 7161+ * Get the first element before the selection that's in a certain class
 7162+ * @param classname Class to match. Defaults to '', meaning any class
70647163 * @param strict If true, the element the selection starts in cannot match (default: false)
70657164 * @return jQuery object
70667165 */
7067 - 'beforeSelection': function( selector, strict ) {
7068 - if ( typeof selector == 'undefined' ) {
7069 - selector = '*';
 7166+ 'beforeSelection': function( classname, strict ) {
 7167+ if ( typeof classname == 'undefined' ) {
 7168+ classname = '';
70707169 }
70717170 var e, offset;
70727171 if ( context.$iframe[0].contentWindow.getSelection ) {
@@ -7076,7 +7175,7 @@
70777176 // Start at the selection's start and traverse the DOM backwards
70787177 // This is done by traversing an element's children first, then the element itself, then its parent
70797178 e = selection.getRangeAt( 0 ).startContainer;
7080 - offset = selection.startOffset;
 7179+ offset = selection.getRangeAt( 0 ).startOffset;
70817180 } else {
70827181 return $( [] );
70837182 }
@@ -7091,7 +7190,7 @@
70927191 // not in the iframe
70937192 try {
70947193 range2.setEndPoint( 'EndToStart', range );
7095 - } catch ( e ) {
 7194+ } catch ( ex ) {
70967195 return $( [] );
70977196 }
70987197 var seekPos = context.fn.htmlToText( range2.htmlText ).length;
@@ -7115,9 +7214,14 @@
71167215 }
71177216 e = newE || e;
71187217 }
 7218+
 7219+ // We'd normally use if( $( e ).hasClass( class ) in the while loop, but running the jQuery
 7220+ // constructor thousands of times is very inefficient
 7221+ var classStr = ' ' + classname + ' ';
71197222 while ( e ) {
7120 - if ( $( e ).is( selector ) && !strict )
 7223+ if ( !strict && ( !classname || ( ' ' + e.className + ' ' ).indexOf( classStr ) != -1 ) ) {
71217224 return $( e );
 7225+ }
71227226 var next = e.previousSibling;
71237227 while ( next && next.lastChild ) {
71247228 next = next.lastChild;
@@ -7128,8 +7232,88 @@
71297233 return $( [] );
71307234 },
71317235 /**
 7236+ * Object used by traverser(). Don't use this unless you know what you're doing
 7237+ */
 7238+ 'rawTraverser': function( node, depth, inP ) {
 7239+ this.node = node;
 7240+ this.depth = depth;
 7241+ this.inP = inP;
 7242+ this.next = function() {
 7243+ var p = this.node;
 7244+ var nextDepth = this.depth;
 7245+ var nextInP = this.inP;
 7246+ while ( p && !p.nextSibling ) {
 7247+ p = p.parentNode;
 7248+ nextDepth--;
 7249+ if ( nextDepth == 0 ) {
 7250+ // We're back at the start node
 7251+ p = null;
 7252+ }
 7253+ if ( p && p.nodeName == "P" ) {
 7254+ nextInP = null;
 7255+ }
 7256+ }
 7257+ p = p ? p.nextSibling : null;
 7258+ if ( p && p.nodeName == "P" ) {
 7259+ nextInP = p;
 7260+ }
 7261+ do {
 7262+ // Filter nodes with the wikiEditor-noinclude class
 7263+ // Don't use $( p ).hasClass( 'wikiEditor-noinclude' ) because
 7264+ // $() is slow in a tight loop
 7265+ while ( p && ( ' ' + p.className + ' ' ).indexOf( ' wikiEditor-noinclude ' ) != -1 ) {
 7266+ p = p.nextSibling;
 7267+ }
 7268+ if ( p && p.firstChild ) {
 7269+ p = p.firstChild;
 7270+ nextDepth++;
 7271+ if ( p.nodeName == "P" ) {
 7272+ nextInP = p;
 7273+ }
 7274+ }
 7275+ } while ( p && p.firstChild );
 7276+ return p ? new context.fn.rawTraverser( p, nextDepth, nextInP ) : null;
 7277+ };
 7278+ this.prev = function() {
 7279+ var p = this.node;
 7280+ var prevDepth = this.depth;
 7281+ var prevInP = this.inP;
 7282+ while ( p && !p.previousSibling ) {
 7283+ p = p.parentNode;
 7284+ prevDepth--;
 7285+ if ( prevDepth == 0 ) {
 7286+ // We're back at the start node
 7287+ p = null;
 7288+ }
 7289+ if ( p && p.nodeName == "P" ) {
 7290+ prevInP = null;
 7291+ }
 7292+ }
 7293+ p = p ? p.previousSibling : null;
 7294+ if ( p && p.nodeName == "P" ) {
 7295+ prevInP = p;
 7296+ }
 7297+ do {
 7298+ // Filter nodes with the wikiEditor-noinclude class
 7299+ // Don't use $( p ).hasClass( 'wikiEditor-noinclude' ) because
 7300+ // $() is slow in a tight loop
 7301+ while ( p && ( ' ' + p.className + ' ' ).indexOf( ' wikiEditor-noinclude ' ) != -1 ) {
 7302+ p = p.previousSibling;
 7303+ }
 7304+ if ( p && p.lastChild ) {
 7305+ p = p.lastChild;
 7306+ prevDepth++;
 7307+ if ( p.nodeName == "P" ) {
 7308+ prevInP = p;
 7309+ }
 7310+ }
 7311+ } while ( p && p.lastChild );
 7312+ return p ? new context.fn.rawTraverser( p, prevDepth, prevInP ) : null;
 7313+ };
 7314+ },
 7315+ /**
71327316 * Get an object used to traverse the leaf nodes in the iframe DOM. This traversal skips leaf nodes
7133 - * inside an element with the wikiEditor-noinclude class.
 7317+ * inside an element with the wikiEditor-noinclude class. This basically wraps rawTraverser
71347318 *
71357319 * Usage:
71367320 * var t = context.fn.traverser( context.$content );
@@ -7139,48 +7323,10 @@
71407324 * // Trying to advance past the end will set t.node to null
71417325 */
71427326 'traverser': function( start ) {
7143 - function Traverser( node, depth, inP ) {
7144 - this.node = node;
7145 - this.depth = depth;
7146 - this.inP = inP;
7147 - this.next = function() {
7148 - var p = this.node;
7149 - var nextDepth = this.depth;
7150 - var nextInP = this.inP;
7151 - while ( p && !p.nextSibling ) {
7152 - if ( p.nodeName == "P" ) {
7153 - nextInP = false;
7154 - }
7155 - p = p.parentNode;
7156 - nextDepth--;
7157 - if ( nextDepth == 0 ) {
7158 - // We're back at the start node
7159 - p = null;
7160 - }
7161 - }
7162 - p = p ? p.nextSibling : null;
7163 - do {
7164 - // Filter nodes with the wikiEditor-noinclude class
7165 - // Don't use $( p ).hasClass( 'wikiEditor-noinclude' ) because
7166 - // $() is slow in a tight loop
7167 - while ( p && ( ' ' + p.className + ' ' ).indexOf( ' wikiEditor-noinclude ' ) != -1 ) {
7168 - p = p.nextSibling;
7169 - }
7170 - if ( p && p.firstChild ) {
7171 - p = p.firstChild;
7172 - nextDepth++;
7173 - if ( p.nodeName == "P" ) {
7174 - nextInP = true;
7175 - }
7176 - }
7177 - } while ( p && p.firstChild );
7178 - return p ? new Traverser( p, nextDepth, nextInP ) : null;
7179 - };
7180 - }
71817327 // Find the leftmost leaf node in the tree
71827328 var node = start.jquery ? start.get( 0 ) : start;
71837329 var depth = 0;
7184 - var inP = node.nodeName == "P";
 7330+ var inP = node.nodeName == "P" ? node : null;
71857331 do {
71867332 // Filter nodes with the wikiEditor-noinclude class
71877333 // Don't use $( p ).hasClass( 'wikiEditor-noinclude' ) because
@@ -7192,11 +7338,11 @@
71937339 node = node.firstChild;
71947340 depth++;
71957341 if ( node.nodeName == "P" ) {
7196 - inP = true;
 7342+ inP = node;
71977343 }
71987344 }
71997345 } while ( node && node.firstChild );
7200 - return new Traverser( node, depth, inP );
 7346+ return new context.fn.rawTraverser( node, depth, inP );
72017347 },
72027348 'getOffset': function( offset ) {
72037349 if ( !context.offsets ) {
@@ -7220,7 +7366,7 @@
72217367 var base = context.offsets[lowerBound];
72227368 return context.offsets[offset] = {
72237369 'node': base.node,
7224 - 'offset': base.offset + offset - o,
 7370+ 'offset': base.offset + offset - lowerBound,
72257371 'length': base.length,
72267372 'depth': base.depth,
72277373 'lastTextNode': base.lastTextNode,
@@ -7235,13 +7381,13 @@
72367382 var t = context.fn.traverser( context.$content );
72377383 var pos = 0, lastTextNode = null, lastTextNodeDepth = null;
72387384 while ( t ) {
7239 - if ( t.node.nodeName != '#text' && t.node.nodeName != 'BR' ) {
 7385+ if ( t.node.nodeName != '#text' && t.node.nodeName != 'BR' && t.node.nodeName != 'P' ) {
72407386 t = t.next();
72417387 continue;
72427388 }
72437389 var nextPos = t.node.nodeName == '#text' ? pos + t.node.nodeValue.length : pos + 1;
72447390 var nextT = t.next();
7245 - var leavingP = t.inP && nextT && !nextT.inP;
 7391+ var leavingP = t.node.nodeName != 'P' && t.inP && nextT && ( !nextT.inP || nextT.inP != t.inP );
72467392 context.offsets[pos] = {
72477393 'node': t.node,
72487394 'offset': 0,
@@ -7311,7 +7457,7 @@
73127458 // Setup the intial view
73137459 context.view = 'wikitext';
73147460 // Trigger the "resize" event anytime the window is resized
7315 - $( window ).resize( function( event ) { context.fn.trigger( 'resize', event ) } );
 7461+ $( window ).resize( function( event ) { context.fn.trigger( 'resize', event ); } );
73167462 // Create an iframe in place of the text area
73177463 context.$iframe = $( '<iframe></iframe>' )
73187464 .attr( {
@@ -7347,7 +7493,13 @@
73487494 // If we just do "context.$content.text( context.$textarea.val() )", Internet Explorer will strip out the
73497495 // whitespace charcters, specifically "\n" - so we must manually encode the text and append it
73507496 // TODO: Refactor this into a textToHtml() function
7351 - var html = context.$textarea.val();
 7497+ // Because we're gonna insert instances of <br>, &nbsp; and <span class="wikiEditor-tab"></span>,
 7498+ // we have to escape existing instances first. This'll cause them to be double-escaped, which we
 7499+ // fix later on
 7500+ var html = context.$textarea.val()
 7501+ .replace( /&nbsp;/g, '&amp;nbsp;' )
 7502+ .replace( /\<br\>/g, '&lt;br&gt;' )
 7503+ .replace( /\<span class="wikiEditor-tab"\>\<\/span\>/g, '&lt;span class=&quot;wikiEditor-tab&quot;&gt;&lt;/span&gt;' );
73527504 // We must do some extra processing on IE to avoid dirty diffs, specifically IE will collapse leading spaces
73537505 if ( $.browser.msie ) {
73547506 // Browser sniffing is not ideal, but executing this code on a non-broken browser doesn't cause harm
@@ -7363,11 +7515,20 @@
73647516 }
73657517 // Use a dummy div to escape all entities
73667518 // This'll also escape <br>, <span> and &nbsp; , so we unescape those after
7367 - html = $( '<div />' ).text( html.replace( /\r?\n/g, '<br>' ) ).html()
 7519+ // We also need to unescape the doubly-escaped things mentioned above
 7520+ html = $( '<div />' ).text( '<p>' + html.replace( /\r?\n/g, '</p><p>' ) + '</p>' ).html()
73687521 .replace( /&amp;nbsp;/g, '&nbsp;' )
7369 - .replace( /&lt;br&gt;/g, '<br>' )
7370 - .replace( /&lt;span class=&quot;wikiEditor-tab&quot;&gt;&lt;\/span&gt;/g, '<span class="wikiEditor-tab"></span>' );
 7522+ // Allow p tags to survive encoding
 7523+ .replace( /&lt;p&gt;/g, '<p>' )
 7524+ .replace( /&lt;\/p&gt;/g, '</p>' )
 7525+ // Empty p tags should just be br tags
 7526+ .replace( /<p><\/p>/g, '<br>' )
 7527+ .replace( /&lt;span class=&quot;wikiEditor-tab&quot;&gt;&lt;\/span&gt;/g, '<span class="wikiEditor-tab"></span>' )
 7528+ .replace( /&amp;amp;nbsp;/g, '&amp;nbsp;' )
 7529+ .replace( /&amp;lt;br&amp;gt;/g, '&lt;br&gt;' )
 7530+ .replace( /&amp;lt;span class=&amp;quot;wikiEditor-tab&amp;quot;&amp;gt;&amp;lt;\/span&amp;gt;/g, '&lt;span class=&quot;wikiEditor-tab&quot;&gt;&lt;/span&gt;' );
73717531 context.$content.html( html );
 7532+ context.oldHTML = html;
73727533
73737534 // Reflect direction of parent frame into child
73747535 if ( $( 'body' ).is( '.rtl' ) ) {
@@ -7400,19 +7561,19 @@
74017562 window.onbeforeunload = function() {
74027563 context.$textarea.val( context.$textarea.textSelection( 'getContents' ) );
74037564 return context.fallbackWindowOnBeforeUnload ? context.fallbackWindowOnBeforeUnload() : null;
7404 - }
 7565+ };
74057566 }
74067567
74077568 /* API Execution */
74087569
74097570 // Since javascript gives arguments as an object, we need to convert them so they can be used more easily
7410 -arguments = $.makeArray( arguments );
 7571+var args = $.makeArray( arguments );
74117572 // There would need to be some arguments if the API is being called
7412 -if ( arguments.length > 0 ) {
 7573+if ( args.length > 0 ) {
74137574 // Handle API calls
7414 - var call = arguments.shift();
 7575+ var call = args.shift();
74157576 if ( call in context.api ) {
7416 - context.api[call]( context, typeof arguments[0] == 'undefined' ? {} : arguments[0] );
 7577+ context.api[call]( context, typeof args[0] == 'undefined' ? {} : args[0] );
74177578 }
74187579 }
74197580
@@ -7607,7 +7768,7 @@
76087769 * ; Definition
76097770 * : Definition
76107771 */
7611 - if ( event.data.scope == 'division' ) {
 7772+ if ( event.data.scope == 'realchange' ) {
76127773 $.wikiEditor.modules.highlight.fn.scan( context, "" );
76137774 $.wikiEditor.modules.highlight.fn.mark( context, "", "" );
76147775 }
@@ -7628,7 +7789,7 @@
76297790 * @param config Configuration object to create module from
76307791 */
76317792 create: function( context, config ) {
7632 - // hook $.wikiEditor.modules.highlight.evt.change to context.evt.change
 7793+ context.modules.highlight.markersStr = '';
76337794 },
76347795 /**
76357796 * Divides text into divisions
@@ -7717,6 +7878,7 @@
77187879 * @param tokens
77197880 */
77207881 // FIXME: What do division and tokens do?
 7882+ // TODO: Document the scan() and mark() APIs somewhere
77217883 mark: function( context, division, tokens ) {
77227884 // Reset markers
77237885 var markers = context.modules.highlight.markers = [];
@@ -7724,7 +7886,21 @@
77257887 context.fn.trigger( 'mark' );
77267888 markers.sort( function( a, b ) { return a.start - b.start || a.end - b.end; } );
77277889
 7890+ // Serialize the markers array to a string and compare it with the one stored in the previous run
 7891+ // If they're equal, there's no markers to change
 7892+ var markersStr = '';
 7893+ for ( var i = 0; i < markers.length; i++ ) {
 7894+ markersStr += markers[i].start + ',' + markers[i].end + ',' + markers[i].type + ',';
 7895+ }
 7896+ if ( context.modules.highlight.markersStr == markersStr ) {
 7897+ // No change, bail out
 7898+ return;
 7899+ }
 7900+ context.modules.highlight.markersStr = markersStr;
 7901+
77287902 // Traverse the iframe DOM, inserting markers where they're needed.
 7903+ // Store visited markers here so we know which markers should be removed
 7904+ var visited = [];
77297905 for ( var i = 0; i < markers.length; i++ ) {
77307906 // We want to isolate each marker, so we may need to split textNodes
77317907 // if a marker starts or ends halfway one.
@@ -7736,23 +7912,27 @@
77377913 }
77387914 var startNode = s.node;
77397915 var startDepth = s.depth;
7740 - // The next marker starts somewhere in this textNode or at this BR
7741 - if ( s.offset > 0 ) {
7742 - // t.node must be a textnode at this point because
7743 - // only textnodes can have offset > 0
7744 -
7745 - // Split off the prefix
7746 - // This leaves the prefix in the current node and puts
7747 - // the rest in a new node which is our start node
7748 - startNode = startNode.splitText( s.offset );
7749 - }
 7916+
77507917 // Don't wrap leading BRs, produces undesirable results
7751 - while ( startNode.nodeName == 'BR' ) {
 7918+ // FIXME: It's also possible that the offset is a bit high because getOffset() has incremented
 7919+ // .length to fake the newline caused by startNode being in a P. In this case, prevent
 7920+ // the textnode splitting below from making startNode an empty textnode, IE barfs on that
 7921+ while ( startNode.nodeName == 'BR' || s.offset == startNode.nodeValue.length ) {
77527922 start++;
77537923 s = context.fn.getOffset( start );
77547924 startNode = s.node;
77557925 startDepth = s.depth;
77567926 }
 7927+
 7928+ // The next marker starts somewhere in this textNode or at this BR
 7929+ if ( s.offset > 0 && s.node.nodeName == '#text' ) {
 7930+ // Split off the prefix
 7931+ // This leaves the prefix in the current node and puts
 7932+ // the rest in a new node which is our start node
 7933+ startNode = startNode.splitText( s.offset );
 7934+ // This also invalidates cached offset objects
 7935+ context.fn.purgeOffsets(); // TODO: Optimize better, get end offset object earlier
 7936+ }
77577937
77587938 var end = markers[i].end;
77597939 var e = context.fn.getOffset( end );
@@ -7762,14 +7942,13 @@
77637943 }
77647944 var endNode = e.node;
77657945 var endDepth = e.depth;
7766 - if ( e.offset < e.length - 1 ) {
7767 - // t.node must be a textnode at this point because
7768 - // .length is 1 for BRs and offset can't be < 0
7769 -
 7946+ if ( e.offset < e.length - 1 && e.node.nodeName == '#text' ) {
77707947 // Split off the suffix - This puts the suffix in a new node and leaves the rest in the current
77717948 // node.
77727949 // endNode.nodeValue.length - ( newPos - markers[i].end )
77737950 endNode.splitText( e.offset + 1 );
 7951+ // This also invalidates cached offset objects
 7952+ context.fn.purgeOffsets(); // TODO: Optimize better, get end offset object earlier
77747953 }
77757954
77767955 // Don't wrap trailing BRs, doing that causes weird issues
@@ -7809,13 +7988,19 @@
78107989 ca1 = ca1.parentNode.firstChild == ca1 ? ca1.parentNode : null;
78117990 ca2 = ca2.parentNode.lastChild == ca2 ? ca2.parentNode : null;
78127991 }
7813 - if ( ca1 && ca2 && ca1.parentNode && ca2.nextSibling ) {
 7992+ if ( ca1 && ca2 && ca1.parentNode ) {
78147993 var anchor = markers[i].getAnchor( ca1, ca2 );
78157994 if ( !anchor ) {
78167995 // We have to store things like .parentNode and .nextSibling because appendChild() changes these
78177996 // properties
78187997 var newNode = ca1.ownerDocument.createElement( 'div' );
78197998 var commonAncestor = ca1.parentNode;
 7999+ // Special case: can't put block elements in a <p>
 8000+ if ( commonAncestor.nodeName == 'P' && commonAncestor.parentNode ) {
 8001+ commonAncestor = commonAncestor.parentNode;
 8002+ ca1 = ca1.parentNode;
 8003+ ca2 = ca2.parentNode;
 8004+ }
78208005 var nextNode = ca2.nextSibling;
78218006 if ( markers[i].anchor == 'wrap' ) {
78228007 // Append all nodes between ca1 and ca2 (inclusive) to newNode
@@ -7842,22 +8027,32 @@
78438028 }
78448029
78458030 $( newNode ).data( 'marker', markers[i] )
7846 - .addClass( 'wikiEditor-highlight wikiEditor-highlight-tmp' );
 8031+ .addClass( 'wikiEditor-highlight' );
 8032+ visited[i] = newNode;
78478033
78488034 // Allow the module adding this marker to manipulate it
78498035 markers[i].afterWrap( newNode, markers[i] );
78508036 } else {
7851 - // Temporarily add a class for bookkeeping purposes
7852 - $( anchor )
7853 - .addClass( 'wikiEditor-highlight-tmp' )
7854 - .data( 'marker', markers[i] );
 8037+ visited[i] = anchor;
 8038+ // Update the marker object
 8039+ $( anchor ).data( 'marker', markers[i] );
78558040 markers[i].onSkip( anchor );
78568041 }
78578042 }
78588043 }
78598044
78608045 // Remove markers that were previously inserted but weren't passed to this function
7861 - context.$content.find( 'div.wikiEditor-highlight:not(.wikiEditor-highlight-tmp)' ).each( function() {
 8046+ // This function works because visited[] contains the visited elements in order and find() and each()
 8047+ // preserve order
 8048+ var j = 0;
 8049+ context.$content.find( 'div.wikiEditor-highlight' ).each( function() {
 8050+ if ( visited[j] == this ) {
 8051+ // This marker is legit, leave it in
 8052+ j++;
 8053+ return true;
 8054+ }
 8055+
 8056+ // Remove this marker
78628057 if ( $(this).data( 'marker' ) && typeof $(this).data( 'marker' ).unwrap == 'function' )
78638058 $(this).data( 'marker' ).unwrap( this );
78648059 if ( $(this).children().size() > 0 ) {
@@ -7866,8 +8061,6 @@
78678062 $(this).replaceWith( $(this).html() );
78688063 }
78698064 });
7870 - // Remove temporary class
7871 - context.$content.find( 'div.wikiEditor-highlight-tmp' ).removeClass( 'wikiEditor-highlight-tmp' );
78728065 }
78738066 }
78748067
@@ -8172,6 +8365,7 @@
81738366 markers.push( {
81748367 start: tokenArray[beginIndex].offset,
81758368 end: tokenArray[endIndex].offset,
 8369+ type: 'template',
81768370 anchor: 'wrap',
81778371 afterWrap: $.wikiEditor.modules.templateEditor.fn.stylize,
81788372 beforeUnwrap: function( node ) {
@@ -8822,6 +9016,7 @@
88239017 context.modules.toc.$toc.data( 'previousWidth', context.$wikitext.width() );
88249018 },
88259019 mark: function( context, event ) {
 9020+ var hash = '';
88269021 var markers = context.modules.highlight.markers;
88279022 var tokenArray = context.modules.highlight.tokenArray;
88289023 var outline = context.data.outline = [];
@@ -8835,6 +9030,7 @@
88369031 index: h,
88379032 start: tokenArray[i].tokenStart,
88389033 end: tokenArray[i].offset,
 9034+ type: 'toc',
88399035 anchor: 'before',
88409036 afterWrap: function( node ) {
88419037 var marker = $( node ).data( 'marker' );
@@ -8844,24 +9040,32 @@
88459041 },
88469042 onSkip: function( node ) {
88479043 var marker = $( node ).data( 'marker' );
8848 - $( node )
8849 - .removeClass( 'wikiEditor-toc-section-' + $( node ).data( 'section' ) )
8850 - .addClass( 'wikiEditor-toc-section-' + marker.index )
8851 - .data( 'section', marker.index );
 9044+ if ( $( node ).data( 'section' ) != marker.index ) {
 9045+ $( node )
 9046+ .removeClass( 'wikiEditor-toc-section-' + $( node ).data( 'section' ) )
 9047+ .addClass( 'wikiEditor-toc-section-' + marker.index )
 9048+ .data( 'section', marker.index );
 9049+ }
88529050 },
88539051 getAnchor: function( ca1, ca2 ) {
8854 - return $( ca1.previousSibling ).is( 'div.wikiEditor-toc-header' ) ?
8855 - ca1.previousSibling : null;
 9052+ return $( ca1.parentNode.previousSibling ).is( 'div.wikiEditor-toc-header' ) ?
 9053+ ca1.parentNode.previousSibling : null;
88569054 }
88579055 } );
 9056+ hash += tokenArray[i].match[2] + '\n';
88589057 outline.push ( {
88599058 'text': tokenArray[i].match[2],
88609059 'level': tokenArray[i].match[1].length,
88619060 'index': h
88629061 } );
88639062 }
8864 - $.wikiEditor.modules.toc.fn.build( context );
8865 - $.wikiEditor.modules.toc.fn.update( context );
 9063+ // Only update the TOC if it's been changed - we do this by comparing a hash of the headings this time to last
 9064+ if ( typeof context.modules.toc.lastHash == 'undefined' || context.modules.toc.lastHash !== hash ) {
 9065+ $.wikiEditor.modules.toc.fn.build( context );
 9066+ $.wikiEditor.modules.toc.fn.update( context );
 9067+ // Remember the changed version
 9068+ context.modules.toc.lastHash = hash;
 9069+ }
88669070 }
88679071 },
88689072 exp: [
@@ -8998,7 +9202,7 @@
89999203 update: function( context ) {
90009204 $.wikiEditor.modules.toc.fn.unhighlight( context );
90019205
9002 - var div = context.fn.beforeSelection( 'div.wikiEditor-toc-header' );
 9206+ var div = context.fn.beforeSelection( 'wikiEditor-toc-header' );
90039207 var section = div.data( 'section' ) || 0;
90049208 if ( context.data.outline.length > 0 ) {
90059209 var sectionLink = context.modules.toc.$toc.find( 'div.section-' + section );
@@ -9132,17 +9336,18 @@
91339337 function buildList( structure ) {
91349338 var list = $( '<ul />' );
91359339 for ( i in structure ) {
9136 - var wrapper = context.$content.find( '.wikiEditor-toc-section-' + structure[i].index );
9137 - if ( wrapper.size() == 0 )
9138 - wrapper = context.$content;
91399340 var div = $( '<div />' )
91409341 .addClass( 'section-' + structure[i].index )
9141 - .data( 'wrapper', wrapper )
 9342+ .data( 'index', structure[i].index )
91429343 .click( function( event ) {
9143 - context.fn.scrollToTop( $( this ).data( 'wrapper' ), true );
 9344+ var wrapper = context.$content.find(
 9345+ '.wikiEditor-toc-section-' + $( this ).data( 'index' ) );
 9346+ if ( wrapper.size() == 0 )
 9347+ wrapper = context.$content;
 9348+ context.fn.scrollToTop( wrapper, true );
91449349 context.$textarea.textSelection( 'setSelection', {
91459350 'start': 0,
9146 - 'startContainer': $(this).data( 'wrapper' )
 9351+ 'startContainer': wrapper
91479352 } );
91489353 // Highlight the clicked link
91499354 $.wikiEditor.modules.toc.fn.unhighlight( context );
@@ -9237,7 +9442,9 @@
92389443 if( ui.size.width <= parseFloat( $.wikiEditor.modules.toc.cfg.minimumWidth ) ) {
92399444 context.modules.toc.$toc.trigger( 'collapse.wikiEditor-toc' );
92409445 } else {
9241 - context.modules.toc.$toc.find( 'div' ).autoEllipsis( { 'position': 'right', 'tooltip': true, 'restoreText': true } );
 9446+ context.modules.toc.$toc.find( 'div' ).autoEllipsis(
 9447+ { 'position': 'right', 'tooltip': true, 'restoreText': true }
 9448+ );
92429449 context.modules.toc.$toc.data( 'openWidth', ui.size.width );
92439450 $.cookie( 'wikiEditor-' + context.instance + '-toc-width', ui.size.width );
92449451 }
@@ -9301,7 +9508,9 @@
93029509 buildResizeControls();
93039510 buildCollapseControls();
93049511 }
9305 - context.modules.toc.$toc.find( 'div' ).autoEllipsis( { 'position': 'right', 'tooltip': true, 'restoreText': true } );
 9512+ context.modules.toc.$toc.find( 'div' ).autoEllipsis(
 9513+ { 'position': 'right', 'tooltip': true, 'restoreText': true }
 9514+ );
93069515 }
93079516 }
93089517 }
@@ -9429,7 +9638,7 @@
94309639 $( $.wikiEditor.modules.toolbar.fn.buildCharacter( data[type][character], actions ) )
94319640 .click( function() {
94329641 $.wikiEditor.modules.toolbar.fn.doAction( $(this).parent().data( 'context' ),
9433 - $(this).parent().data( 'actions' )[$(this).attr( 'rel' )] );
 9642+ $(this).parent().data( 'actions' )[$(this).attr( 'rel' )] );
94349643 return false;
94359644 } )
94369645 );
@@ -9525,7 +9734,7 @@
95269735 doAction : function( context, action, source ) {
95279736 // Verify that this has been called from a source that's within the toolbar
95289737 // 'trackAction' defined in click tracking
9529 - if ($.trackAction != undefined && source.closest( '.wikiEditor-ui-toolbar' ).size() ) {
 9738+ if ( $.trackAction != undefined && source.closest( '.wikiEditor-ui-toolbar' ).size() ) {
95309739 // Build a unique id for this action by tracking the parent rel attributes up to the toolbar level
95319740 var rels = [];
95329741 var step = source;
@@ -9543,7 +9752,7 @@
95449753 }
95459754 rels.reverse();
95469755 var id = rels.join( '.' );
9547 - $.trackAction(id);
 9756+ $.trackAction( id );
95489757 }
95499758 switch ( action.type ) {
95509759 case 'replace':
@@ -9569,6 +9778,7 @@
95709779 'encapsulateSelection',
95719780 $.extend( {}, action.options, parts, { 'replace': action.type == 'replace' } )
95729781 );
 9782+ context.$iframe[0].contentWindow.focus();
95739783 break;
95749784 case 'callback':
95759785 if ( typeof action.execute == 'function' ) {
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/js/plugins.combined.min.js
@@ -436,31 +436,39 @@
437437 options.endContainer=options.startContainer;break;case'scrollToCaretPosition':options=$.extend({'force':false},options);break;}
438438 var context=$(this).data('wikiEditor-context');var hasIframe=context!==undefined&&context.$iframe!==undefined;return(hasIframe?context.fn:fn)[command].call(this,options);};})(jQuery);(function($){$.wikiEditor={'modules':{},'instances':[],'browsers':{'ltr':{'msie':[['>=',7]],'firefox':[['>=',2],['!=','2.0'],['!=','2.0.0.1'],['!=','2.0.0.2'],['!=','2.0.0.3'],['!=','2.0.0.4']],'opera':[['>=',9.6]],'safari':[['>=',3.1]]},'rtl':{'msie':[['>=',8]],'firefox':[['>=',2],['!=','2.0'],['!=','2.0.0.1'],['!=','2.0.0.2'],['!=','2.0.0.3'],['!=','2.0.0.4']],'opera':[['>=',9.6]],'safari':[['>=',3.1]]}},'imgPath':wgScriptPath+'/extensions/UsabilityInitiative_alpha/images/wikiEditor/','isSupported':function(){if(typeof $.wikiEditor.supported!='undefined'){return $.wikiEditor.supported;}
439439 if(!($.browser.name in $.wikiEditor.browsers[$('body').is('.rtl')?'rtl':'ltr'])){return $.wikiEditor.supported=true;}
440 -var browser=$.wikiEditor.browsers[$('body').is('.rtl')?'rtl':'ltr'][$.browser.name];for(condition in browser){var op=browser[condition][0];var val=browser[condition][1];if(typeof val=='string'){if(!(eval('$.browser.version'+op+'"'+val+'"'))){return $.wikiEditor.supported=false;}}else if(typeof val=='number'){if(!(eval('$.browser.versionNumber'+op+val))){return $.wikiEditor.supported=false;}}}
441 -return $.wikiEditor.supported=true;},'autoMsg':function(object,property){if(typeof property=='object'){for(i in property){if(property[i]in object||property[i]+'Msg'in object){property=property[i];break;}}}
 440+var browser=$.wikiEditor.browsers[$('body').is('.rtl')?'rtl':'ltr'][$.browser.name];for(var condition in browser){var op=browser[condition][0];var val=browser[condition][1];if(typeof val=='string'){if(!(eval('$.browser.version'+op+'"'+val+'"'))){return $.wikiEditor.supported=false;}}else if(typeof val=='number'){if(!(eval('$.browser.versionNumber'+op+val))){return $.wikiEditor.supported=false;}}}
 441+return $.wikiEditor.supported=true;},'autoMsg':function(object,property){if(typeof property=='object'){for(var i in property){if(property[i]in object||property[i]+'Msg'in object){property=property[i];break;}}}
442442 if(property in object){return object[property];}else if(property+'Msg'in object){if(typeof object[property+'Msg']=='object'){return mw.usability.getMsg.apply(mw.usability,object[property+'Msg']);}else{return mw.usability.getMsg(object[property+'Msg']);}}else{return'';}},'autoLang':function(object,lang){return object[lang||wgUserLanguage]||object['default']||object;},'autoIcon':function(icon,path,lang){var src=$.wikiEditor.autoLang(icon,lang);path=path||$.wikiEditor.imgPath;if(src.substr(0,7)!='http://'&&src.substr(0,8)!='https://'&&src[0]!='/'){src=path+src;}
443443 return src+'?'+wgWikiEditorIconVersion;}};$.fn.wikiEditor=function(){if(!$j.wikiEditor.isSupported()){return $(this);}
444 -var context=$(this).data('wikiEditor-context');if(typeof context=='undefined'){context={'$textarea':$(this),'views':{},'modules':{},'data':{},'instance':$.wikiEditor.instances.push($(this))-1,'offsets':null};context.api={'addModule':function(context,data){var modules={};if(typeof data=='string'){modules[data]={};}else if(typeof data=='object'){modules=data;}
445 -for(module in modules){if(typeof module=='string'&&module in $.wikiEditor.modules){if('api'in $.wikiEditor.modules[module]){for(call in $.wikiEditor.modules[module].api){if(!(call in context.api)){context.api[call]=$.wikiEditor.modules[module].api[call];}}}
446 -if('fn'in $.wikiEditor.modules[module]&&'create'in $.wikiEditor.modules[module].fn){context.modules[module]={};$.wikiEditor.modules[module].fn.create(context,modules[module]);}}}}};context.evt={'change':function(event){event.data.scope='division';context.fn.purgeOffsets();return true;},'delayedChange':function(event){return context.evt.change(event);}};context.fn={'trigger':function(name,event){if(typeof event=='undefined'){event={'type':'custom'};}
 444+var context=$(this).data('wikiEditor-context');if(typeof context=='undefined'){context={'$textarea':$(this),'views':{},'modules':{},'data':{},'instance':$.wikiEditor.instances.push($(this))-1,'offsets':null,'htmlToTextMap':{},'oldHTML':null,'oldDelayedHTML':null};context.api={'addModule':function(context,data){var modules={};if(typeof data=='string'){modules[data]={};}else if(typeof data=='object'){modules=data;}
 445+for(var module in modules){if(typeof module=='string'&&module in $.wikiEditor.modules){if('api'in $.wikiEditor.modules[module]){for(var call in $.wikiEditor.modules[module].api){if(!(call in context.api)){context.api[call]=$.wikiEditor.modules[module].api[call];}}}
 446+if('fn'in $.wikiEditor.modules[module]&&'create'in $.wikiEditor.modules[module].fn){context.modules[module]={};$.wikiEditor.modules[module].fn.create(context,modules[module]);}}}}};context.evt={'change':function(event){event.data.scope='division';var newHTML=context.$content.html();if(context.oldHTML!=newHTML){context.fn.purgeOffsets();context.oldHTML=newHTML;event.data.scope='realchange';}
 447+return true;},'delayedChange':function(event){event.data.scope='division';var newHTML=context.$content.html();if(context.oldDelayedHTML!=newHTML){context.fn.purgeOffsets();context.oldDelayedHTML=newHTML;event.data.scope='realchange';}
 448+return true;}};context.fn={'trigger':function(name,event){if(typeof event=='undefined'){event={'type':'custom'};}
447449 if(typeof event.data=='undefined'){event.data={};}
448450 if(name in context.evt){if(!context.evt[name](event)){return false;}}
449 -for(module in context.modules){if(module in $.wikiEditor.modules&&'evt'in $.wikiEditor.modules[module]&&name in $.wikiEditor.modules[module].evt){$.wikiEditor.modules[module].evt[name](context,event);}}},'addButton':function(options){context.$controls.show();context.$buttons.show();return $('<button />').text($.wikiEditor.autoMsg(options,'caption')).click(options.action).appendTo(context.$buttons);},'addView':function(options){function addTab(options){context.$controls.show();context.$tabs.show();return $('<div></div>').attr('rel','wikiEditor-ui-view-'+options.name).addClass(context.view==options.name?'current':null).append($('<a></a>').attr('href','#').click(function(event){context.$ui.find('.wikiEditor-ui-view').hide();context.$ui.find('.'+$(this).parent().attr('rel')).show();context.$tabs.find('div').removeClass('current');$(this).parent().addClass('current');$(this).blur();if('init'in options&&typeof options.init=='function'){options.init(context);}
 451+for(var module in context.modules){if(module in $.wikiEditor.modules&&'evt'in $.wikiEditor.modules[module]&&name in $.wikiEditor.modules[module].evt){$.wikiEditor.modules[module].evt[name](context,event);}}},'addButton':function(options){context.$controls.show();context.$buttons.show();return $('<button />').text($.wikiEditor.autoMsg(options,'caption')).click(options.action).appendTo(context.$buttons);},'addView':function(options){function addTab(options){context.$controls.show();context.$tabs.show();return $('<div></div>').attr('rel','wikiEditor-ui-view-'+options.name).addClass(context.view==options.name?'current':null).append($('<a></a>').attr('href','#').click(function(event){context.$ui.find('.wikiEditor-ui-view').hide();context.$ui.find('.'+$(this).parent().attr('rel')).show();context.$tabs.find('div').removeClass('current');$(this).parent().addClass('current');$(this).blur();if('init'in options&&typeof options.init=='function'){options.init(context);}
450452 event.preventDefault();return false;}).text($.wikiEditor.autoMsg(options,'title'))).appendTo(context.$tabs);}
451453 if(!context.$tabs.children().size()){addTab({'name':'wikitext','titleMsg':'wikieditor-wikitext-tab'});}
452 -addTab(options);return $('<div></div>').addClass('wikiEditor-ui-view wikiEditor-ui-view-'+options.name).hide().appendTo(context.$ui);},'htmlToText':function(html){var $pre=$('<pre>'+
453 -html.replace(/\r?\n/g,"").replace(/\<br[^\>]*\>/gi,"\n").replace(/&nbsp;/g," ").replace(/\<p[^\>]*\>/gi,"\n").replace(/\<\/p[^\>]*\>/gi,"").replace(/\<div[^\>]*\>/gi,"\n").replace(/\<\/div[^\>]*\>/gi,"")
454 -+'</pre>');$pre.find('.wikiEditor-noinclude').each(function(){$(this).remove();});$pre.find('.wikiEditor-tab').each(function(){$(this).text("\t")});return $pre.text();},'getContents':function(){return context.fn.htmlToText(context.$content.html());},'getSelection':function(){var retval;if(context.$iframe[0].contentWindow.getSelection){retval=context.$iframe[0].contentWindow.getSelection();}else if(context.$iframe[0].contentWindow.document.selection){retval=context.$iframe[0].contentWindow.document.selection.createRange();}
 454+addTab(options);return $('<div></div>').addClass('wikiEditor-ui-view wikiEditor-ui-view-'+options.name).hide().appendTo(context.$ui);},'htmlToText':function(html){if(html in context.htmlToTextMap){return context.htmlToTextMap[html];}
 455+var origHTML=html;html=html.replace(/\r?\n/g,"").replace(/&nbsp;/g," ").replace(/\<br[^\>]*\>/gi,"\n").replace(/\<\/p\>\<p\>/gi,"\n").replace(/\<\/p\>(\n*)\<p\>/gi,"$1\n");var leading=html.match(/^\s*/)[0];var trailing=html.match(/\s*$/)[0];html=html.substr(leading.length,html.length-leading.length-trailing.length);var $pre=$('<pre>'+html+'</pre>');$pre.find('.wikiEditor-noinclude').each(function(){$(this).remove();});$pre.find('.wikiEditor-tab').each(function(){$(this).text("\t");});$pre.find('br').each(function(){$(this).replaceWith("\n");});$pre.find('p').each(function(){if(this.previousSibling||this.parentNode!=$pre.get(0)){var text=$(this).text();var t=new context.fn.rawTraverser(this.firstChild,-10,this).prev();while(t&&t.node.nodeName!='#text'&&t.node.nodeName!='BR'&&t.node.nodeName!='P'){t=t.prev();}
 456+if(t){text="\n"+text;}
 457+t=new context.fn.rawTraverser(this.lastChild,-10,this).next();while(t&&t.node.nodeName!='#text'&&t.node.nodeName!='BR'&&t.node.nodeName!='P'){t=t.next();}
 458+if(t&&!t.inP&&t.node.nodeName=='#text'&&t.node.nodeValue.charAt(0)!='\n'&&t.node.nodeValue.charAt(0)!='\r'){text+="\n";}
 459+$(this).text(text);}});var retval;if($.browser.msie){retval=$('<pre>'+$pre.html()+'</pre>').text().replace(/\r/g,'\n');}else{retval=$pre.text();}
 460+return context.htmlToTextMap[origHTML]=leading+retval+trailing;},'getContents':function(){return context.fn.htmlToText(context.$content.html());},'getSelection':function(){var retval;if(context.$iframe[0].contentWindow.getSelection){retval=context.$iframe[0].contentWindow.getSelection();if($.browser.opera){if(retval.rangeCount>0){retval=context.fn.htmlToText($('<pre />').append(retval.getRangeAt(0).cloneContents()).html());}else{retval='';}}}else if(context.$iframe[0].contentWindow.document.selection){retval=context.$iframe[0].contentWindow.document.selection.createRange();}
455461 if(typeof retval.text!='undefined'){retval=context.fn.htmlToText(retval.htmlText);}else if(retval.toString){retval=retval.toString();}
456462 return retval;},'encapsulateSelection':function(options){var selText=$(this).textSelection('getSelection');var selTextArr;var selectAfter=false;var pre=options.pre,post=options.post;if(!selText){selText=options.peri;selectAfter=true;}else if(options.replace){selText=options.peri;}else if(selText.charAt(selText.length-1)==' '){selText=selText.substring(0,selText.length-1);post+=' ';}
457463 if(options.splitlines){selTextArr=selText.split(/\n/);}
458 -if(context.$iframe[0].contentWindow.getSelection){var range=context.$iframe[0].contentWindow.getSelection().getRangeAt(0);if(options.ownline){var body=context.$content.get(0);if(range.startOffset!=0&&range.startContainer!=body){pre="\n"+options.pre;}
459 -if(range.endContainer!=body||range.endOffset==0){post+="\n";}}
460 -var insertText="";if(options.splitlines){for(var i=0;i<selTextArr.length;i++){insertText=insertText+pre+selTextArr[i]+post;if(i!=selTextArr.length-1)insertText+="\n";}}else{insertText=pre+selText+post;}
 464+if(context.$iframe[0].contentWindow.getSelection){var range=context.$iframe[0].contentWindow.getSelection().getRangeAt(0);if(options.ownline){var atStart=false,atEnd=false;var body=context.$content.get(0);if(range.startOffset==0){atStart=true;}else if(range.startContainer==body){var n=body.firstChild;for(var i=0;i<range.startOffset-1&&n;i++){n=n.nextSibling;}
 465+if(n&&n.nodeName=='BR'){atStart=true;}else{atEnd=true;}}else if(range.startContainer.nodeName=='#text'&&range.startOffset==range.startContainer.nodeValue.length){atEnd=true;}
 466+if(!atStart){pre="\n"+options.pre;}
 467+if(!atEnd){post+="\n";}}
 468+var insertText="";if(options.splitlines){for(var j=0;j<selTextArr.length;j++){insertText=insertText+pre+selTextArr[j]+post;if(j!=selTextArr.length-1){insertText+="\n";}}}else{insertText=pre+selText+post;}
461469 var insertLines=insertText.split("\n");range.extractContents();var lastNode;for(var i=insertLines.length-1;i>=0;i--){range.insertNode(context.$iframe[0].contentWindow.document.createTextNode(insertLines[i]));if(i>0){lastNode=range.insertNode(context.$iframe[0].contentWindow.document.createElement('br'));}}
462470 if(lastNode){context.fn.scrollToTop(lastNode);}}else if(context.$iframe[0].contentWindow.document.selection){context.$iframe[0].contentWindow.focus();var range=context.$iframe[0].contentWindow.document.selection.createRange();if(options.ownline&&range.moveStart){var range2=context.$iframe[0].contentWindow.document.selection.createRange();range2.collapse();range2.moveStart('character',-1);if(range2.text!="\r"&&range2.text!="\n"&&range2.text!=""){pre="\n"+pre;}
463471 var range3=context.$iframe[0].contentWindow.document.selection.createRange();range3.collapse(false);range3.moveEnd('character',1);if(range3.text!="\r"&&range3.text!="\n"&&range3.text!=""){post+="\n";}}
464 -var insertText="";if(options.splitlines){for(var i=0;i<selTextArr.length;i++){insertText=insertText+pre+selTextArr[i]+post;if(i!=selTextArr.length-1){insertText+="\n";}}}else{insertText=pre+selText+post;}
 472+var insertText="";if(options.splitlines){for(var j=0;j<selTextArr.length;j++){insertText=insertText+pre+selTextArr[j]+post;if(j!=selTextArr.length-1){insertText+="\n";}}}else{insertText=pre+selText+post;}
465473 range.pasteHTML(insertText.replace(/\</g,'&lt;').replace(/>/g,'&gt;').replace(/\r?\n/g,'<br />'));}
466474 $(context.$iframe[0].contentWindow.document).trigger('encapsulateSelection',[pre,options.peri,post,options.ownline,options.replace]);return context.$textarea;},'getCaretPosition':function(options){},'setSelection':function(options){var sc=options.startContainer,ec=options.endContainer;sc=sc&&sc.jquery?sc[0]:sc;ec=ec&&ec.jquery?ec[0]:ec;if(context.$iframe[0].contentWindow.getSelection){var start=options.start,end=options.end;if(!sc||!ec){var s=context.fn.getOffset(start);var e=context.fn.getOffset(end);sc=s?s.node:null;ec=e?e.node:null;start=s?s.offset:null;end=e?e.offset:null;}
467475 if(!sc||!ec){return context.$textarea;}
@@ -471,57 +479,65 @@
472480 range2.collapse();range2.moveEnd('character',options.end);range.setEndPoint('EndToEnd',range2);range.select();}
473481 return context.$textarea;},'scrollToCaretPosition':function(options){},'scrollToTop':function($element,force){var html=context.$content.closest('html'),body=context.$content.closest('body'),parentHtml=$('html'),parentBody=$('body');var y=$element.offset().top;if(!$.browser.msie&&!$element.is('body')){y=parentHtml.scrollTop()>0?y+html.scrollTop()-parentHtml.scrollTop():y;y=parentBody.scrollTop()>0?y+body.scrollTop()-parentBody.scrollTop():y;}
474482 var topBound=html.scrollTop()>body.scrollTop()?html.scrollTop():body.scrollTop(),bottomBound=topBound+context.$iframe.height();if(force||y<topBound||y>bottomBound){html.scrollTop(y);body.scrollTop(y);}
475 -$element.trigger('scrollToTop');},'beforeSelection':function(selector,strict){if(typeof selector=='undefined'){selector='*';}
476 -var e,offset;if(context.$iframe[0].contentWindow.getSelection){var selection=context.$iframe[0].contentWindow.getSelection();if(selection.baseNode!==null){e=selection.getRangeAt(0).startContainer;offset=selection.startOffset;}else{return $([]);}}else if(context.$iframe[0].contentWindow.document.selection){var range=context.$iframe[0].contentWindow.document.selection.createRange();var range2=context.$iframe[0].contentWindow.document.body.createTextRange();try{range2.setEndPoint('EndToStart',range);}catch(e){return $([]);}
 483+$element.trigger('scrollToTop');},'beforeSelection':function(classname,strict){if(typeof classname=='undefined'){classname='';}
 484+var e,offset;if(context.$iframe[0].contentWindow.getSelection){var selection=context.$iframe[0].contentWindow.getSelection();if(selection.baseNode!==null){e=selection.getRangeAt(0).startContainer;offset=selection.getRangeAt(0).startOffset;}else{return $([]);}}else if(context.$iframe[0].contentWindow.document.selection){var range=context.$iframe[0].contentWindow.document.selection.createRange();var range2=context.$iframe[0].contentWindow.document.body.createTextRange();try{range2.setEndPoint('EndToStart',range);}catch(ex){return $([]);}
477485 var seekPos=context.fn.htmlToText(range2.htmlText).length;var offset=context.fn.getOffset(seekPos);e=offset?offset.node:null;offset=offset?offset.offset:null;if(!e){return $([]);}}
478486 if(e.nodeName!='#text'){var newE=e.firstChild;for(var i=0;i<offset-1&&newE;i++){newE=newE.nextSibling;}
479487 while(newE&&newE.lastChild){newE=newE.lastChild;}
480488 e=newE||e;}
481 -while(e){if($(e).is(selector)&&!strict)
482 -return $(e);var next=e.previousSibling;while(next&&next.lastChild){next=next.lastChild;}
 489+var classStr=' '+classname+' ';while(e){if(!strict&&(!classname||(' '+e.className+' ').indexOf(classStr)!=-1)){return $(e);}
 490+var next=e.previousSibling;while(next&&next.lastChild){next=next.lastChild;}
483491 e=next||e.parentNode;strict=false;}
484 -return $([]);},'traverser':function(start){function Traverser(node,depth,inP){this.node=node;this.depth=depth;this.inP=inP;this.next=function(){var p=this.node;var nextDepth=this.depth;var nextInP=this.inP;while(p&&!p.nextSibling){if(p.nodeName=="P"){nextInP=false;}
485 -p=p.parentNode;nextDepth--;if(nextDepth==0){p=null;}}
486 -p=p?p.nextSibling:null;do{while(p&&(' '+p.className+' ').indexOf(' wikiEditor-noinclude ')!=-1){p=p.nextSibling;}
487 -if(p&&p.firstChild){p=p.firstChild;nextDepth++;if(p.nodeName=="P"){nextInP=true;}}}while(p&&p.firstChild);return p?new Traverser(p,nextDepth,nextInP):null;};}
488 -var node=start.jquery?start.get(0):start;var depth=0;var inP=node.nodeName=="P";do{while(node&&(' '+node.className+' ').indexOf(' wikiEditor-noinclude ')!=-1){node=node.nextSibling;}
489 -if(node&&node.firstChild){node=node.firstChild;depth++;if(node.nodeName=="P"){inP=true;}}}while(node&&node.firstChild);return new Traverser(node,depth,inP);},'getOffset':function(offset){if(!context.offsets){context.fn.refreshOffsets();}
 492+return $([]);},'rawTraverser':function(node,depth,inP){this.node=node;this.depth=depth;this.inP=inP;this.next=function(){var p=this.node;var nextDepth=this.depth;var nextInP=this.inP;while(p&&!p.nextSibling){p=p.parentNode;nextDepth--;if(nextDepth==0){p=null;}
 493+if(p&&p.nodeName=="P"){nextInP=null;}}
 494+p=p?p.nextSibling:null;if(p&&p.nodeName=="P"){nextInP=p;}
 495+do{while(p&&(' '+p.className+' ').indexOf(' wikiEditor-noinclude ')!=-1){p=p.nextSibling;}
 496+if(p&&p.firstChild){p=p.firstChild;nextDepth++;if(p.nodeName=="P"){nextInP=p;}}}while(p&&p.firstChild);return p?new context.fn.rawTraverser(p,nextDepth,nextInP):null;};this.prev=function(){var p=this.node;var prevDepth=this.depth;var prevInP=this.inP;while(p&&!p.previousSibling){p=p.parentNode;prevDepth--;if(prevDepth==0){p=null;}
 497+if(p&&p.nodeName=="P"){prevInP=null;}}
 498+p=p?p.previousSibling:null;if(p&&p.nodeName=="P"){prevInP=p;}
 499+do{while(p&&(' '+p.className+' ').indexOf(' wikiEditor-noinclude ')!=-1){p=p.previousSibling;}
 500+if(p&&p.lastChild){p=p.lastChild;prevDepth++;if(p.nodeName=="P"){prevInP=p;}}}while(p&&p.lastChild);return p?new context.fn.rawTraverser(p,prevDepth,prevInP):null;};},'traverser':function(start){var node=start.jquery?start.get(0):start;var depth=0;var inP=node.nodeName=="P"?node:null;do{while(node&&(' '+node.className+' ').indexOf(' wikiEditor-noinclude ')!=-1){node=node.nextSibling;}
 501+if(node&&node.firstChild){node=node.firstChild;depth++;if(node.nodeName=="P"){inP=node;}}}while(node&&node.firstChild);return new context.fn.rawTraverser(node,depth,inP);},'getOffset':function(offset){if(!context.offsets){context.fn.refreshOffsets();}
490502 if(offset in context.offsets){return context.offsets[offset];}
491503 var lowerBound=-1;for(var o in context.offsets){if(o>offset){break;}
492504 lowerBound=o;}
493505 if(!(lowerBound in context.offsets)){return null;}
494 -var base=context.offsets[lowerBound];return context.offsets[offset]={'node':base.node,'offset':base.offset+offset-o,'length':base.length,'depth':base.depth,'lastTextNode':base.lastTextNode,'lastTextNodeDepth':base.lastTextNodeDepth};},'purgeOffsets':function(){context.offsets=null;},'refreshOffsets':function(){context.offsets=[];var t=context.fn.traverser(context.$content);var pos=0,lastTextNode=null,lastTextNodeDepth=null;while(t){if(t.node.nodeName!='#text'&&t.node.nodeName!='BR'){t=t.next();continue;}
495 -var nextPos=t.node.nodeName=='#text'?pos+t.node.nodeValue.length:pos+1;var nextT=t.next();var leavingP=t.inP&&nextT&&!nextT.inP;context.offsets[pos]={'node':t.node,'offset':0,'length':nextPos-pos+(leavingP?1:0),'depth':t.depth,'lastTextNode':lastTextNode,'lastTextNodeDepth':lastTextNodeDepth};if(leavingP){context.offsets[nextPos]={'node':t.node,'offset':nextPos-pos,'length':nextPos-pos+1,'depth':t.depth,'lastTextNode':lastTextNode,'lastTextNodeDepth':lastTextNodeDepth};}
 506+var base=context.offsets[lowerBound];return context.offsets[offset]={'node':base.node,'offset':base.offset+offset-lowerBound,'length':base.length,'depth':base.depth,'lastTextNode':base.lastTextNode,'lastTextNodeDepth':base.lastTextNodeDepth};},'purgeOffsets':function(){context.offsets=null;},'refreshOffsets':function(){context.offsets=[];var t=context.fn.traverser(context.$content);var pos=0,lastTextNode=null,lastTextNodeDepth=null;while(t){if(t.node.nodeName!='#text'&&t.node.nodeName!='BR'&&t.node.nodeName!='P'){t=t.next();continue;}
 507+var nextPos=t.node.nodeName=='#text'?pos+t.node.nodeValue.length:pos+1;var nextT=t.next();var leavingP=t.node.nodeName!='P'&&t.inP&&nextT&&(!nextT.inP||nextT.inP!=t.inP);context.offsets[pos]={'node':t.node,'offset':0,'length':nextPos-pos+(leavingP?1:0),'depth':t.depth,'lastTextNode':lastTextNode,'lastTextNodeDepth':lastTextNodeDepth};if(leavingP){context.offsets[nextPos]={'node':t.node,'offset':nextPos-pos,'length':nextPos-pos+1,'depth':t.depth,'lastTextNode':lastTextNode,'lastTextNodeDepth':lastTextNodeDepth};}
496508 pos=nextPos+(leavingP?1:0);if(t.node.nodeName=='#text'){lastTextNode=t.node;lastTextNodeDepth=t.depth;}
497 -t=nextT;}}};context.$textarea.wrap($('<div></div>').addClass('wikiEditor-ui')).wrap($('<div></div>').addClass('wikiEditor-ui-view wikiEditor-ui-view-wikitext')).wrap($('<div></div>').addClass('wikiEditor-ui-left')).wrap($('<div></div>').addClass('wikiEditor-ui-bottom')).wrap($('<div></div>').addClass('wikiEditor-ui-text'));context.$ui=context.$textarea.parent().parent().parent().parent().parent();context.$wikitext=context.$textarea.parent().parent().parent().parent();context.$wikitext.before($('<div></div>').addClass('wikiEditor-ui-controls').append($('<div></div>').addClass('wikiEditor-ui-tabs').hide()).append($('<div></div>').addClass('wikiEditor-ui-buttons'))).before($('<div style="clear:both;"></div>'));context.$controls=context.$ui.find('.wikiEditor-ui-buttons').hide();context.$buttons=context.$ui.find('.wikiEditor-ui-buttons');context.$tabs=context.$ui.find('.wikiEditor-ui-tabs');context.$ui.after($('<div style="clear:both;"></div>'));context.$wikitext.append($('<div></div>').addClass('wikiEditor-ui-right'));context.$wikitext.find('.wikiEditor-ui-left').prepend($('<div></div>').addClass('wikiEditor-ui-top'));context.view='wikitext';$(window).resize(function(event){context.fn.trigger('resize',event)});context.$iframe=$('<iframe></iframe>').attr({'frameBorder':0,'border':0,'src':wgScriptPath+'/extensions/UsabilityInitiative_alpha/js/plugins/jquery.wikiEditor.html?'+'instance='+context.instance+'&ts='+(new Date()).getTime(),'id':'wikiEditor-iframe-'+context.instance}).css({'backgroundColor':'white','width':'100%','height':context.$textarea.height(),'display':'none','overflow-y':'scroll','overflow-x':'hidden'}).insertAfter(context.$textarea).load(function(){if(!this.isSecondRun){context.$iframe[0].contentWindow.document.designMode='on';if($.browser.msie){this.isSecondRun=true;return;}}
498 -context.$content=$(context.$iframe[0].contentWindow.document.body);var html=context.$textarea.val();if($.browser.msie){if($.browser.versionNumber<=7){html=html.replace(/ /g,"&nbsp;");}else{html=html.replace(/(^|\n) /g,"$1&nbsp;");}
 509+t=nextT;}}};context.$textarea.wrap($('<div></div>').addClass('wikiEditor-ui')).wrap($('<div></div>').addClass('wikiEditor-ui-view wikiEditor-ui-view-wikitext')).wrap($('<div></div>').addClass('wikiEditor-ui-left')).wrap($('<div></div>').addClass('wikiEditor-ui-bottom')).wrap($('<div></div>').addClass('wikiEditor-ui-text'));context.$ui=context.$textarea.parent().parent().parent().parent().parent();context.$wikitext=context.$textarea.parent().parent().parent().parent();context.$wikitext.before($('<div></div>').addClass('wikiEditor-ui-controls').append($('<div></div>').addClass('wikiEditor-ui-tabs').hide()).append($('<div></div>').addClass('wikiEditor-ui-buttons'))).before($('<div style="clear:both;"></div>'));context.$controls=context.$ui.find('.wikiEditor-ui-buttons').hide();context.$buttons=context.$ui.find('.wikiEditor-ui-buttons');context.$tabs=context.$ui.find('.wikiEditor-ui-tabs');context.$ui.after($('<div style="clear:both;"></div>'));context.$wikitext.append($('<div></div>').addClass('wikiEditor-ui-right'));context.$wikitext.find('.wikiEditor-ui-left').prepend($('<div></div>').addClass('wikiEditor-ui-top'));context.view='wikitext';$(window).resize(function(event){context.fn.trigger('resize',event);});context.$iframe=$('<iframe></iframe>').attr({'frameBorder':0,'border':0,'src':wgScriptPath+'/extensions/UsabilityInitiative_alpha/js/plugins/jquery.wikiEditor.html?'+'instance='+context.instance+'&ts='+(new Date()).getTime(),'id':'wikiEditor-iframe-'+context.instance}).css({'backgroundColor':'white','width':'100%','height':context.$textarea.height(),'display':'none','overflow-y':'scroll','overflow-x':'hidden'}).insertAfter(context.$textarea).load(function(){if(!this.isSecondRun){context.$iframe[0].contentWindow.document.designMode='on';if($.browser.msie){this.isSecondRun=true;return;}}
 510+context.$content=$(context.$iframe[0].contentWindow.document.body);var html=context.$textarea.val().replace(/&nbsp;/g,'&amp;nbsp;').replace(/\<br\>/g,'&lt;br&gt;').replace(/\<span class="wikiEditor-tab"\>\<\/span\>/g,'&lt;span class=&quot;wikiEditor-tab&quot;&gt;&lt;/span&gt;');if($.browser.msie){if($.browser.versionNumber<=7){html=html.replace(/ /g,"&nbsp;");}else{html=html.replace(/(^|\n) /g,"$1&nbsp;");}
499511 html=html.replace(/\t/g,'<span class="wikiEditor-tab"></span>');}
500 -html=$('<div />').text(html.replace(/\r?\n/g,'<br>')).html().replace(/&amp;nbsp;/g,'&nbsp;').replace(/&lt;br&gt;/g,'<br>').replace(/&lt;span class=&quot;wikiEditor-tab&quot;&gt;&lt;\/span&gt;/g,'<span class="wikiEditor-tab"></span>');context.$content.html(html);if($('body').is('.rtl')){context.$content.addClass('rtl').attr('dir','rtl');}
501 -context.$textarea.attr('disabled',true);context.$textarea.hide();context.$iframe.show();context.fn.trigger('ready');$(context.$iframe[0].contentWindow.document).bind('keyup mouseup paste cut encapsulateSelection',function(event){context.fn.trigger('change',event);}).delayedBind(250,'keyup mouseup paste cut encapsulateSelection',function(event){context.fn.trigger('delayedChange',event);});});context.$textarea.closest('form').submit(function(){context.$textarea.attr('disabled',false);context.$textarea.val(context.$textarea.textSelection('getContents'));});context.fallbackWindowOnBeforeUnload=window.onbeforeunload;window.onbeforeunload=function(){context.$textarea.val(context.$textarea.textSelection('getContents'));return context.fallbackWindowOnBeforeUnload?context.fallbackWindowOnBeforeUnload():null;}}
502 -arguments=$.makeArray(arguments);if(arguments.length>0){var call=arguments.shift();if(call in context.api){context.api[call](context,typeof arguments[0]=='undefined'?{}:arguments[0]);}}
 512+html=$('<div />').text('<p>'+html.replace(/\r?\n/g,'</p><p>')+'</p>').html().replace(/&amp;nbsp;/g,'&nbsp;').replace(/&lt;p&gt;/g,'<p>').replace(/&lt;\/p&gt;/g,'</p>').replace(/<p><\/p>/g,'<br>').replace(/&lt;span class=&quot;wikiEditor-tab&quot;&gt;&lt;\/span&gt;/g,'<span class="wikiEditor-tab"></span>').replace(/&amp;amp;nbsp;/g,'&amp;nbsp;').replace(/&amp;lt;br&amp;gt;/g,'&lt;br&gt;').replace(/&amp;lt;span class=&amp;quot;wikiEditor-tab&amp;quot;&amp;gt;&amp;lt;\/span&amp;gt;/g,'&lt;span class=&quot;wikiEditor-tab&quot;&gt;&lt;/span&gt;');context.$content.html(html);context.oldHTML=html;if($('body').is('.rtl')){context.$content.addClass('rtl').attr('dir','rtl');}
 513+context.$textarea.attr('disabled',true);context.$textarea.hide();context.$iframe.show();context.fn.trigger('ready');$(context.$iframe[0].contentWindow.document).bind('keyup mouseup paste cut encapsulateSelection',function(event){context.fn.trigger('change',event);}).delayedBind(250,'keyup mouseup paste cut encapsulateSelection',function(event){context.fn.trigger('delayedChange',event);});});context.$textarea.closest('form').submit(function(){context.$textarea.attr('disabled',false);context.$textarea.val(context.$textarea.textSelection('getContents'));});context.fallbackWindowOnBeforeUnload=window.onbeforeunload;window.onbeforeunload=function(){context.$textarea.val(context.$textarea.textSelection('getContents'));return context.fallbackWindowOnBeforeUnload?context.fallbackWindowOnBeforeUnload():null;};}
 514+var args=$.makeArray(arguments);if(args.length>0){var call=args.shift();if(call in context.api){context.api[call](context,typeof args[0]=='undefined'?{}:args[0]);}}
503515 return $(this).data('wikiEditor-context',context);};})(jQuery);RegExp.escape=function(s){return s.replace(/([.*+?^${}()|\/\\[\]])/g,'\\$1');};(function($){$.wikiEditor.modules.dialogs={api:{addDialog:function(context,data){$.wikiEditor.modules.dialogs.fn.create(context,data)},openDialog:function(context,module){if(module in $.wikiEditor.modules.dialogs.modules){$('#'+$.wikiEditor.modules.dialogs.modules[module].id).dialog('open');}},closeDialog:function(context,data){if(module in $.wikiEditor.modules.dialogs.modules){$('#'+$.wikiEditor.modules.dialogs.modules[module].id).dialog('close');}}},fn:{create:function(context,config){for(module in config){$.wikiEditor.modules.dialogs.modules[module]=config[module];}
504516 mw.usability.load(['$j.ui','$j.ui.dialog','$j.ui.draggable','$j.ui.resizable'],function(){for(module in $.wikiEditor.modules.dialogs.modules){var module=$.wikiEditor.modules.dialogs.modules[module];if($('#'+module.id).size()==0){var configuration=module.dialog;configuration.bgiframe=true;configuration.autoOpen=false;configuration.modal=true;configuration.title=$.wikiEditor.autoMsg(module,'title');configuration.newButtons={};for(msg in configuration.buttons)
505517 configuration.newButtons[mw.usability.getMsg(msg)]=configuration.buttons[msg];configuration.buttons=configuration.newButtons;var dialogDiv=$('<div /> ').attr('id',module.id).html(module.html).data('context',context).appendTo($('body')).each(module.init).dialog(configuration);if(!('resizeme'in module)||module.resizeme){dialogDiv.bind('dialogopen',$.wikiEditor.modules.dialogs.fn.resize).find('.ui-tabs').bind('tabsshow',function(){$(this).closest('.ui-dialog-content').each($.wikiEditor.modules.dialogs.fn.resize);});}
506518 var maxTI=0;$j('[tabindex]').each(function(){var ti=parseInt($j(this).attr('tabindex'));if(ti>maxTI)
507519 maxTI=ti;});var tabIndex=maxTI+1;$j('.ui-dialog input, .ui-dialog button').not('[tabindex]').each(function(){$j(this).attr('tabindex',tabIndex++);});}}});},resize:function(){var wrapper=$(this).closest('.ui-dialog');var oldWidth=wrapper.width();var oldHidden=$(this).find('*').not(':visible');oldHidden.each(function(){$(this).data('oldstyle',$(this).attr('style'));});oldHidden.show();var oldWS=$(this).css('white-space');$(this).css('white-space','nowrap');if(wrapper.width()<=$(this).get(0).scrollWidth){var thisWidth=$(this).data('thisWidth')?$(this).data('thisWidth'):0;thisWidth=Math.max($(this).get(0).scrollWidth,thisWidth);$(this).width(thisWidth);$(this).data('thisWidth',thisWidth);var wrapperWidth=$(this).data('wrapperWidth')?$(this).data('wrapperWidth'):0;wrapperWidth=Math.max(wrapper.get(0).scrollWidth,wrapperWidth);wrapper.width(wrapperWidth);$(this).data('wrapperWidth',wrapperWidth);$(this).dialog({'width':wrapper.width()});wrapper.css('left',parseInt(wrapper.css('left'))-(wrapper.width()-oldWidth)/2);}
508 -$(this).css('white-space',oldWS);oldHidden.each(function(){$(this).attr('style',$(this).data('oldstyle'));});}},modules:{},quickDialog:function(body,settings){$('<div />').text(body).appendTo($('body')).dialog($.extend({bgiframe:true,modal:true},settings)).dialog('open');}};})(jQuery);(function($){$.wikiEditor.modules.highlight={cfg:{'styleVersion':3},evt:{delayedChange:function(context,event){if(event.data.scope=='division'){$.wikiEditor.modules.highlight.fn.scan(context,"");$.wikiEditor.modules.highlight.fn.mark(context,"","");}},ready:function(context,event){$.wikiEditor.modules.highlight.fn.scan(context,"");$.wikiEditor.modules.highlight.fn.mark(context,"","");}},fn:{create:function(context,config){},divide:function(context){},isolate:function(context){return[];},strip:function(context,division){return $('<div />').html(division.html().replace(/\<br[^\>]*\>/g,"\n")).text();},scan:function(context,division){function Token(offset,label,tokenStart,match){this.offset=offset;this.label=label;this.tokenStart=tokenStart;this.match=match;}
 520+$(this).css('white-space',oldWS);oldHidden.each(function(){$(this).attr('style',$(this).data('oldstyle'));});}},modules:{},quickDialog:function(body,settings){$('<div />').text(body).appendTo($('body')).dialog($.extend({bgiframe:true,modal:true},settings)).dialog('open');}};})(jQuery);(function($){$.wikiEditor.modules.highlight={cfg:{'styleVersion':3},evt:{delayedChange:function(context,event){if(event.data.scope=='realchange'){$.wikiEditor.modules.highlight.fn.scan(context,"");$.wikiEditor.modules.highlight.fn.mark(context,"","");}},ready:function(context,event){$.wikiEditor.modules.highlight.fn.scan(context,"");$.wikiEditor.modules.highlight.fn.mark(context,"","");}},fn:{create:function(context,config){context.modules.highlight.markersStr='';},divide:function(context){},isolate:function(context){return[];},strip:function(context,division){return $('<div />').html(division.html().replace(/\<br[^\>]*\>/g,"\n")).text();},scan:function(context,division){function Token(offset,label,tokenStart,match){this.offset=offset;this.label=label;this.tokenStart=tokenStart;this.match=match;}
509521 var tokenArray=context.modules.highlight.tokenArray=[];var text=context.fn.getContents();for(module in context.modules){if(module in $.wikiEditor.modules&&'exp'in $.wikiEditor.modules[module]){for(var i=0;i<$.wikiEditor.modules[module].exp.length;i++){var regex=$.wikiEditor.modules[module].exp[i].regex;var label=$.wikiEditor.modules[module].exp[i].label;var markAfter=false;if(typeof $.wikiEditor.modules[module].exp[i].markAfter!='undefined'){markAfter=true;}
510522 match=text.match(regex);var oldOffset=0;while(match!=null){var markOffset=0;var tokenStart=match.index+oldOffset+markOffset;if(markAfter){markOffset+=match[0].length;}
511523 tokenArray.push(new Token(match.index+oldOffset+markOffset,label,tokenStart,match));oldOffset+=match.index+match[0].length;newSubstring=text.substring(oldOffset);match=newSubstring.match(regex);}}}}
512 -tokenArray.sort(function(a,b){return a.offset-b.offset||a.tokenStart-b.tokenStart;});context.fn.trigger('scan');},mark:function(context,division,tokens){var markers=context.modules.highlight.markers=[];context.fn.trigger('mark');markers.sort(function(a,b){return a.start-b.start||a.end-b.end;});for(var i=0;i<markers.length;i++){var start=markers[i].start;var s=context.fn.getOffset(start);if(!s){continue;}
513 -var startNode=s.node;var startDepth=s.depth;if(s.offset>0){startNode=startNode.splitText(s.offset);}
514 -while(startNode.nodeName=='BR'){start++;s=context.fn.getOffset(start);startNode=s.node;startDepth=s.depth;}
 524+tokenArray.sort(function(a,b){return a.offset-b.offset||a.tokenStart-b.tokenStart;});context.fn.trigger('scan');},mark:function(context,division,tokens){var markers=context.modules.highlight.markers=[];context.fn.trigger('mark');markers.sort(function(a,b){return a.start-b.start||a.end-b.end;});var markersStr='';for(var i=0;i<markers.length;i++){markersStr+=markers[i].start+','+markers[i].end+','+markers[i].type+',';}
 525+if(context.modules.highlight.markersStr==markersStr){return;}
 526+context.modules.highlight.markersStr=markersStr;var visited=[];for(var i=0;i<markers.length;i++){var start=markers[i].start;var s=context.fn.getOffset(start);if(!s){continue;}
 527+var startNode=s.node;var startDepth=s.depth;while(startNode.nodeName=='BR'||s.offset==startNode.nodeValue.length){start++;s=context.fn.getOffset(start);startNode=s.node;startDepth=s.depth;}
 528+if(s.offset>0&&s.node.nodeName=='#text'){startNode=startNode.splitText(s.offset);context.fn.purgeOffsets();}
515529 var end=markers[i].end;var e=context.fn.getOffset(end);if(!e){continue;}
516 -var endNode=e.node;var endDepth=e.depth;if(e.offset<e.length-1){endNode.splitText(e.offset+1);}
 530+var endNode=e.node;var endDepth=e.depth;if(e.offset<e.length-1&&e.node.nodeName=='#text'){endNode.splitText(e.offset+1);context.fn.purgeOffsets();}
517531 if(endNode.nodeName=='BR'){endNode=e.lastTextNode;endDepth=e.lastTextNodeDepth;}
518532 var ca1=startNode,ca2=endNode;if(startDepth>endDepth){for(var j=0;j<startDepth-endDepth&&ca1;j++){ca1=ca1.parentNode.firstChild==ca1?ca1.parentNode:null;}}
519533 else if(startDepth<endDepth){for(var j=0;j<endDepth-startDepth&&ca2;j++){ca2=ca2.parentNode.lastChild==ca2?ca2.parentNode:null;}}
520534 while(ca1&&ca2&&ca1.parentNode&&ca2.parentNode&&ca1.parentNode!=ca2.parentNode&&ca1.parentNode.firstChild&&ca2.parentNode.lastChild){ca1=ca1.parentNode.firstChild==ca1?ca1.parentNode:null;ca2=ca2.parentNode.lastChild==ca2?ca2.parentNode:null;}
521 -if(ca1&&ca2&&ca1.parentNode&&ca2.nextSibling){var anchor=markers[i].getAnchor(ca1,ca2);if(!anchor){var newNode=ca1.ownerDocument.createElement('div');var commonAncestor=ca1.parentNode;var nextNode=ca2.nextSibling;if(markers[i].anchor=='wrap'){var n=ca1;while(n!=nextNode){var ns=n.nextSibling;newNode.appendChild(n);n=ns;}
 535+if(ca1&&ca2&&ca1.parentNode){var anchor=markers[i].getAnchor(ca1,ca2);if(!anchor){var newNode=ca1.ownerDocument.createElement('div');var commonAncestor=ca1.parentNode;if(commonAncestor.nodeName=='P'&&commonAncestor.parentNode){commonAncestor=commonAncestor.parentNode;ca1=ca1.parentNode;ca2=ca2.parentNode;}
 536+var nextNode=ca2.nextSibling;if(markers[i].anchor=='wrap'){var n=ca1;while(n!=nextNode){var ns=n.nextSibling;newNode.appendChild(n);n=ns;}
522537 if(nextNode){commonAncestor.insertBefore(newNode,nextNode);}else{commonAncestor.appendChild(newNode);}}else if(markers[i].anchor=='before'){commonAncestor.insertBefore(newNode,ca1);}else if(markers[i].anchor=='after'){if(nextNode){commonAncestor.insertBefore(newNode,nextNode);}else{commonAncestor.appendChild(newNode);}}
523 -$(newNode).data('marker',markers[i]).addClass('wikiEditor-highlight wikiEditor-highlight-tmp');markers[i].afterWrap(newNode,markers[i]);}else{$(anchor).addClass('wikiEditor-highlight-tmp').data('marker',markers[i]);markers[i].onSkip(anchor);}}}
524 -context.$content.find('div.wikiEditor-highlight:not(.wikiEditor-highlight-tmp)').each(function(){if($(this).data('marker')&&typeof $(this).data('marker').unwrap=='function')
525 -$(this).data('marker').unwrap(this);if($(this).children().size()>0){$(this).replaceWith($(this).children());}else{$(this).replaceWith($(this).html());}});context.$content.find('div.wikiEditor-highlight-tmp').removeClass('wikiEditor-highlight-tmp');}}};})(jQuery);(function($){$.wikiEditor.modules.preview={fn:{create:function(context,config){if('initialized'in context.modules.preview){return;}
 538+$(newNode).data('marker',markers[i]).addClass('wikiEditor-highlight');visited[i]=newNode;markers[i].afterWrap(newNode,markers[i]);}else{visited[i]=anchor;$(anchor).data('marker',markers[i]);markers[i].onSkip(anchor);}}}
 539+var j=0;context.$content.find('div.wikiEditor-highlight').each(function(){if(visited[j]==this){j++;return true;}
 540+if($(this).data('marker')&&typeof $(this).data('marker').unwrap=='function')
 541+$(this).data('marker').unwrap(this);if($(this).children().size()>0){$(this).replaceWith($(this).children());}else{$(this).replaceWith($(this).html());}});}}};})(jQuery);(function($){$.wikiEditor.modules.preview={fn:{create:function(context,config){if('initialized'in context.modules.preview){return;}
526542 context.modules.preview={'initialized':true,'previewText':null,'changesText':null};context.modules.preview.$preview=context.fn.addView({'name':'preview','titleMsg':'wikieditor-preview-tab','init':function(context){var wikitext=context.fn.getContents();if(context.modules.preview.previewText==wikitext){return;}
527543 context.modules.preview.$preview.find('.wikiEditor-preview-contents').empty();context.modules.preview.$preview.find('.wikiEditor-preview-loading').show();$.post(wgScriptPath+'/api.php',{'action':'parse','title':wgPageName,'text':wikitext,'prop':'text','pst':'','format':'json'},function(data){if(typeof data.parse=='undefined'||typeof data.parse.text=='undefined'||typeof data.parse.text['*']=='undefined'){return;}
528544 context.modules.preview.previewText=wikitext;context.modules.preview.$preview.find('.wikiEditor-preview-loading').hide();context.modules.preview.$preview.find('.wikiEditor-preview-contents').html(data.parse.text['*']).find('a:not([href^=#])').click(function(){return false;});},'json');}});context.$changesTab=context.fn.addView({'name':'changes','titleMsg':'wikieditor-preview-changes-tab','init':function(context){var wikitext=context.fn.getContents();if(context.modules.preview.changesText==wikitext){return;}
@@ -553,7 +569,7 @@
554570 $('#wikiEditor-'+context.instance+'-dialog-watch').hide();else if($('#wpWatchthis').is(':checked'))
555571 $('#wikiEditor-'+context.instance+'-dialog-watch').attr('checked','checked');$(this).find('form').submit(function(e){$(this).closest('.ui-dialog').find('button:first').click();e.preventDefault();});},dialog:{buttons:{'wikieditor-publish-dialog-publish':function(){var minorChecked=$('#wikiEditor-'+context.instance+'-dialog-minor').is(':checked')?'checked':'';var watchChecked=$('#wikiEditor-'+context.instance+'-dialog-watch').is(':checked')?'checked':'';$('#wpMinoredit').attr('checked',minorChecked);$('#wpWatchthis').attr('checked',watchChecked);$('#wpSummary').val($j('#wikiEditor-'+context.instance+'-dialog-summary').val());$('#editform').submit();},'wikieditor-publish-dialog-goback':function(){$(this).dialog('close');}},open:function(){$('#wikiEditor-'+context.instance+'-dialog-summary').focus();},width:500},resizeme:false}});context.fn.addButton({'captionMsg':'wikieditor-publish-button-publish','action':function(){$('#'+dialogID).dialog('open');return false;}});context.fn.addButton({'captionMsg':'wikieditor-publish-button-cancel','action':function(){}});}}};})(jQuery);(function($){$.wikiEditor.modules.templateEditor={evt:{mark:function(context,event){var markers=context.modules.highlight.markers;var tokenArray=context.modules.highlight.tokenArray;var level=0;var tokenIndex=0;while(tokenIndex<tokenArray.length){while(tokenIndex<tokenArray.length&&tokenArray[tokenIndex].label!='TEMPLATE_BEGIN'){tokenIndex++;}
556572 if(tokenIndex<tokenArray.length){var beginIndex=tokenIndex;var endIndex=-1;var openTemplates=1;var templatesMatched=false;while(tokenIndex<tokenArray.length-1&&endIndex==-1){tokenIndex++;if(tokenArray[tokenIndex].label=='TEMPLATE_BEGIN'){openTemplates++;}else if(tokenArray[tokenIndex].label=='TEMPLATE_END'){openTemplates--;if(openTemplates==0){endIndex=tokenIndex;}}}
557 -if(endIndex!=-1){markers.push({start:tokenArray[beginIndex].offset,end:tokenArray[endIndex].offset,anchor:'wrap',afterWrap:$.wikiEditor.modules.templateEditor.fn.stylize,beforeUnwrap:function(node){$(node).data('display').remove();},onSkip:function(){},getAnchor:function(ca1,ca2){return $(ca1.parentNode).is('div.wikiEditor-template-text')&&$(ca1.parentNode.previousSibling).is('ul.wikiEditor-template-modes')&&ca1.parentNode.nextSibling==null?ca1.parentNode:null;}});}else{tokenArray[beginIndex].label='TEMPLATE_FALSE_BEGIN';tokenIndex=beginIndex;}}}}},exp:[{'regex':/{{/,'label':"TEMPLATE_BEGIN"},{'regex':/}}/,'label':"TEMPLATE_END",'markAfter':true}],cfg:{},fn:{create:function(context,config){context.modules.templateEditor={};},stylize:function(wrappedTemplate){$(wrappedTemplate).each(function(){if(typeof $(this).data('model')!='undefined'){return;}
 573+if(endIndex!=-1){markers.push({start:tokenArray[beginIndex].offset,end:tokenArray[endIndex].offset,type:'template',anchor:'wrap',afterWrap:$.wikiEditor.modules.templateEditor.fn.stylize,beforeUnwrap:function(node){$(node).data('display').remove();},onSkip:function(){},getAnchor:function(ca1,ca2){return $(ca1.parentNode).is('div.wikiEditor-template-text')&&$(ca1.parentNode.previousSibling).is('ul.wikiEditor-template-modes')&&ca1.parentNode.nextSibling==null?ca1.parentNode:null;}});}else{tokenArray[beginIndex].label='TEMPLATE_FALSE_BEGIN';tokenIndex=beginIndex;}}}}},exp:[{'regex':/{{/,'label':"TEMPLATE_BEGIN"},{'regex':/}}/,'label':"TEMPLATE_END",'markAfter':true}],cfg:{},fn:{create:function(context,config){context.modules.templateEditor={};},stylize:function(wrappedTemplate){$(wrappedTemplate).each(function(){if(typeof $(this).data('model')!='undefined'){return;}
558574 var model=new $.wikiEditor.modules.templateEditor.fn.model($(this).text());if(!model.isCollapsible()){return;}
559575 var $template=$(this).wrap('<div class="wikiEditor-template"></div>').addClass('wikiEditor-template-text wikiEditor-nodisplay').html($(this).html().replace(/\{\{/,'<span class="wikiEditor-template-start">{{</span><span class="wikiEditor-template-inner-text">').replace(/\}\}$/,'</span><span class="wikiEditor-template-end">}}</span>')).css('visibility','hidden').parent().addClass('wikiEditor-template-collapsed').data('model',model);$('<span />').addClass('wikiEditor-template-name wikiEditor-noinclude').text(model.getName()).mousedown(noEdit).prependTo($template);$template.find('.wikiEditor-template-end, .wikiEditor-template-start').mousedown(toggleWikiText);var $options=$('<ul />').addClass('wikiEditor-template-modes wikiEditor-noinclude').append($('<li />').addClass('wikiEditor-template-action-wikiText').append($('<img />').attr('src',$.wikiEditor.imgPath+'templateEditor/'+'wiki-text.png')).mousedown(toggleWikiText)).insertAfter($template.find('.wikiEditor-template-name'));$options.append($('<li />').addClass('wikiEditor-template-action-form').append($('<span>F</span>')).mousedown(function(){createDialog($template);return false;}));function expandTemplate($displayDiv){$displayDiv.removeClass('wikiEditor-template-collapsed');$displayDiv.addClass('wikiEditor-template-expanded');$displayDiv.unbind('mousedown');$keyValueTable=$('<table />').appendTo($displayDiv);$header_row=$('<tr />').appendTo($keyValueTable);$('<th />').attr('colspan','2').text(model.getName()).appendTo($header_row);for(param in model.getAllParamNames()){$keyVal_row=$('<tr />').appendTo($keyValueTable);$('<td />').text(param).appendTo($keyVal_row);$('<td />').text(model.getValue(param)).appendTo($keyVal_row);}};function collapseTemplate($displayDiv){$displayDiv.addClass('wikiEditor-template-collapsed');$displayDiv.removeClass('wikiEditor-template-expanded');$displayDiv.text(model.getName());};function createDialog($templateDiv){var templateModel=$templateDiv.data('model');var $dialog=$("<div></div>");var $title=$("<div>"+templateModel.getName()+"</div>").addClass('wikiEditor-template-dialog-title');var $table=$("<table></table>").addClass('wikiEditor-template-dialog-table').appendTo($dialog);var allInitialParams=templateModel.getAllInitialParams();for(var paramIndex in allInitialParams){var param=allInitialParams[paramIndex];if(typeof param.name=='undefined'){continue;}
560576 var $paramRow=$("<tr></tr>").addClass('wikiEditor-template-dialog-row');var $paramName=$("<td></td>").addClass('wikiEditor-template-dialog-name').text(param.name);var $paramVal=$("<td></td>").addClass('wikiEditor-template-dialog-value');var $paramInput=$("<input></input>").data('name',param.name).val(templateModel.getValue(param.name));$paramVal.append($paramInput);$paramRow.append($paramName).append($paramVal);$table.append($paramRow);}
@@ -594,21 +610,21 @@
595611 if(context.modules.toc.$toc.data('positionMode')=='goofy'){context.modules.toc.$toc.find('div').autoEllipsis({'position':'right','tooltip':true,'restoreText':true});}
596612 if(!context.modules.toc.$toc.data('collapsed')){context.modules.toc.$toc.height(context.$ui.find('.wikiEditor-ui-left').height()-
597613 context.$ui.find('.tab-toc').outerHeight());}
598 -context.modules.toc.$toc.data('previousWidth',context.$wikitext.width());},mark:function(context,event){var markers=context.modules.highlight.markers;var tokenArray=context.modules.highlight.tokenArray;var outline=context.data.outline=[];var h=0;for(var i=0;i<tokenArray.length;i++){if(tokenArray[i].label!='TOC_HEADER'){continue;}
599 -h++;markers.push({index:h,start:tokenArray[i].tokenStart,end:tokenArray[i].offset,anchor:'before',afterWrap:function(node){var marker=$(node).data('marker');$(node).addClass('wikiEditor-toc-header').addClass('wikiEditor-toc-section-'+marker.index).data('section',marker.index);},onSkip:function(node){var marker=$(node).data('marker');$(node).removeClass('wikiEditor-toc-section-'+$(node).data('section')).addClass('wikiEditor-toc-section-'+marker.index).data('section',marker.index);},getAnchor:function(ca1,ca2){return $(ca1.previousSibling).is('div.wikiEditor-toc-header')?ca1.previousSibling:null;}});outline.push({'text':tokenArray[i].match[2],'level':tokenArray[i].match[1].length,'index':h});}
600 -$.wikiEditor.modules.toc.fn.build(context);$.wikiEditor.modules.toc.fn.update(context);}},exp:[{'regex':/^(={1,6})([^\r\n]+?)\1\s*$/m,'label':'TOC_HEADER','markAfter':true}],fn:{create:function(context,config){if('$toc'in context.modules.toc){return;}
 614+context.modules.toc.$toc.data('previousWidth',context.$wikitext.width());},mark:function(context,event){var hash='';var markers=context.modules.highlight.markers;var tokenArray=context.modules.highlight.tokenArray;var outline=context.data.outline=[];var h=0;for(var i=0;i<tokenArray.length;i++){if(tokenArray[i].label!='TOC_HEADER'){continue;}
 615+h++;markers.push({index:h,start:tokenArray[i].tokenStart,end:tokenArray[i].offset,type:'toc',anchor:'before',afterWrap:function(node){var marker=$(node).data('marker');$(node).addClass('wikiEditor-toc-header').addClass('wikiEditor-toc-section-'+marker.index).data('section',marker.index);},onSkip:function(node){var marker=$(node).data('marker');if($(node).data('section')!=marker.index){$(node).removeClass('wikiEditor-toc-section-'+$(node).data('section')).addClass('wikiEditor-toc-section-'+marker.index).data('section',marker.index);}},getAnchor:function(ca1,ca2){return $(ca1.parentNode.previousSibling).is('div.wikiEditor-toc-header')?ca1.parentNode.previousSibling:null;}});hash+=tokenArray[i].match[2]+'\n';outline.push({'text':tokenArray[i].match[2],'level':tokenArray[i].match[1].length,'index':h});}
 616+if(typeof context.modules.toc.lastHash=='undefined'||context.modules.toc.lastHash!==hash){$.wikiEditor.modules.toc.fn.build(context);$.wikiEditor.modules.toc.fn.update(context);context.modules.toc.lastHash=hash;}}},exp:[{'regex':/^(={1,6})([^\r\n]+?)\1\s*$/m,'label':'TOC_HEADER','markAfter':true}],fn:{create:function(context,config){if('$toc'in context.modules.toc){return;}
601617 $.wikiEditor.modules.toc.cfg.rtl=config.rtl;var height=context.$ui.find('.wikiEditor-ui-left').height();context.modules.toc.$toc=$('<div />').addClass('wikiEditor-ui-toc').data('context',context).data('positionMode','regular').data('collapsed',false);context.$ui.find('.wikiEditor-ui-right').append(context.modules.toc.$toc);context.modules.toc.$toc.height(context.$ui.find('.wikiEditor-ui-left').height());$.wikiEditor.modules.toc.fn.redraw(context,$.wikiEditor.modules.toc.cfg.defaultWidth);},redraw:function(context,fixedWidth){var fixedWidth=parseFloat(fixedWidth);if(context.modules.toc.$toc.data('positionMode')=='regular'){context.$ui.find('.wikiEditor-ui-right').css('width',fixedWidth+'px');context.$ui.find('.wikiEditor-ui-left').css('marginRight',(-1*fixedWidth)+'px').children().css('marginRight',fixedWidth+'px');}else if(context.modules.toc.$toc.data('positionMode')=='goofy'){context.$ui.find('.wikiEditor-ui-left').css('width',fixedWidth);context.$ui.find('.wikiEditor-ui-right').css($.wikiEditor.modules.toc.cfg.rtl?'right':'left',fixedWidth);context.$wikitext.css('height',context.$ui.find('.wikiEditor-ui-right').height());}},switchLayout:function(context){var width,height=context.$ui.find('.wikiEditor-ui-right').height();if(context.modules.toc.$toc.data('positionMode')=='regular'&&!context.modules.toc.$toc.data('collapsed')){context.modules.toc.$toc.data('positionMode','goofy');context.modules.toc.$toc.data('positionModeChangeAt',context.$ui.find('.wikiEditor-ui-right').width());width=$.wikiEditor.modules.toc.cfg.textMinimumWidth;context.$ui.find('.wikiEditor-ui-left').css({'marginRight':'','position':'absolute','float':'none','left':$.wikiEditor.modules.toc.cfg.rtl?'auto':0,'right':$.wikiEditor.modules.toc.cfg.rtl?0:'auto'}).children().css('marginRight','');context.$ui.find('.wikiEditor-ui-right').css({'width':'auto','position':'absolute','float':'none','right':$.wikiEditor.modules.toc.cfg.rtl?'auto':0,'left':$.wikiEditor.modules.toc.cfg.rtl?0:'auto'});context.$wikitext.css('position','relative');}else if(context.modules.toc.$toc.data('positionMode')=='goofy'){context.modules.toc.$toc.data('positionMode','regular');width=context.$wikitext.width()-context.$ui.find('.wikiEditor-ui-left').width();if(width>context.modules.toc.$toc.data('positionModeChangeAt')){width=context.modules.toc.$toc.data('positionModeChangeAt');}
602618 context.$wikitext.css({'position':'','height':''});context.$ui.find('.wikiEditor-ui-right').css({'marginRight':'','position':'','left':'','right':'','float':'','top':'','height':''});context.$ui.find('.wikiEditor-ui-left').css({'width':'','position':'','left':'','float':'','right':''});}
603619 $.wikiEditor.modules.toc.fn.redraw(context,width);},disable:function(context){if(context.modules.toc.$toc.data('collapsed')){context.$ui.find('.wikiEditor-ui-toc-expandControl').hide();}else{if(context.modules.toc.$toc.data('positionMode')=='goofy'){$.wikiEditor.modules.toc.fn.switchLayout(context);}
604620 context.$ui.find('.wikiEditor-ui-right').hide();context.$ui.find('.wikiEditor-ui-left').css('marginRight','').children().css('marginRight','');}
605 -context.modules.toc.$toc.data('positionMode','disabled');},enable:function(context){context.modules.toc.$toc.data('positionMode','regular');if(context.modules.toc.$toc.data('collapsed')){context.$ui.find('.wikiEditor-ui-toc-expandControl').show();}else{context.$ui.find('.wikiEditor-ui-right').show();$.wikiEditor.modules.toc.fn.redraw(context,$.wikiEditor.modules.toc.cfg.minimumWidth);context.modules.toc.$toc.find('div').autoEllipsis({'position':'right','tooltip':true,'restoreText':true});}},unhighlight:function(context){if(context){context.modules.toc.$toc.find('div').removeClass('current');}},update:function(context){$.wikiEditor.modules.toc.fn.unhighlight(context);var div=context.fn.beforeSelection('div.wikiEditor-toc-header');var section=div.data('section')||0;if(context.data.outline.length>0){var sectionLink=context.modules.toc.$toc.find('div.section-'+section);sectionLink.addClass('current');var relTop=sectionLink.offset().top-context.modules.toc.$toc.offset().top;var scrollTop=context.modules.toc.$toc.scrollTop();var divHeight=context.modules.toc.$toc.height();var sectionHeight=sectionLink.height();if(relTop<0)
 621+context.modules.toc.$toc.data('positionMode','disabled');},enable:function(context){context.modules.toc.$toc.data('positionMode','regular');if(context.modules.toc.$toc.data('collapsed')){context.$ui.find('.wikiEditor-ui-toc-expandControl').show();}else{context.$ui.find('.wikiEditor-ui-right').show();$.wikiEditor.modules.toc.fn.redraw(context,$.wikiEditor.modules.toc.cfg.minimumWidth);context.modules.toc.$toc.find('div').autoEllipsis({'position':'right','tooltip':true,'restoreText':true});}},unhighlight:function(context){if(context){context.modules.toc.$toc.find('div').removeClass('current');}},update:function(context){$.wikiEditor.modules.toc.fn.unhighlight(context);var div=context.fn.beforeSelection('wikiEditor-toc-header');var section=div.data('section')||0;if(context.data.outline.length>0){var sectionLink=context.modules.toc.$toc.find('div.section-'+section);sectionLink.addClass('current');var relTop=sectionLink.offset().top-context.modules.toc.$toc.offset().top;var scrollTop=context.modules.toc.$toc.scrollTop();var divHeight=context.modules.toc.$toc.height();var sectionHeight=sectionLink.height();if(relTop<0)
606622 context.modules.toc.$toc.scrollTop(scrollTop+relTop);else if(relTop+sectionHeight>divHeight)
607623 context.modules.toc.$toc.scrollTop(scrollTop+relTop+sectionHeight-divHeight);}},collapse:function(event){var $this=$(this),context=$this.data('context');if(context.modules.toc.$toc.data('positionMode')=='goofy'){$.wikiEditor.modules.toc.fn.switchLayout(context);}
608624 var pT=$this.parent().position().top-1;context.modules.toc.$toc.data('collapsed',true);context.$ui.find('.wikiEditor-ui-left').animate({'marginRight':'-1px'},'fast',function(){$(this).css('marginRight',0);}).children().animate({'marginRight':'1px'},'fast',function(){$(this).css('marginRight',0);});context.$ui.find('.wikiEditor-ui-right').css({'marginTop':'1px','position':'absolute','left':$.wikiEditor.modules.toc.cfg.rtl?0:'auto','right':$.wikiEditor.modules.toc.cfg.rtl?'auto':0,'top':pT}).fadeOut('fast',function(){$(this).hide().css({'marginTop':'0','width':'1px'});context.$ui.find('.wikiEditor-ui-toc-expandControl').fadeIn('fast');context.fn.trigger('tocCollapse');context.fn.trigger('resize');});$.cookie('wikiEditor-'+context.instance+'-toc-width',0);return false;},expand:function(event){var $this=$(this),context=$this.data('context'),openWidth=parseFloat(context.modules.toc.$toc.data('openWidth')),availableSpace=context.$wikitext.width()-parseFloat($.wikiEditor.modules.toc.cfg.textMinimumWidth);if(availableSpace<$.wikiEditor.modules.toc.cfg.textMinmumWidth)return false;context.modules.toc.$toc.data('collapsed',false);if(availableSpace<openWidth)openWidth=availableSpace;context.$ui.find('.wikiEditor-ui-toc-expandControl').hide();context.$ui.find('.wikiEditor-ui-left').animate({'marginRight':(parseFloat(openWidth)*-1)},'fast').children().animate({'marginRight':openWidth},'fast');context.$ui.find('.wikiEditor-ui-right').show().css('marginTop','1px').animate({'width':openWidth},'fast',function(){context.$content.trigger('mouseup');$(this).css({'marginTop':'0','position':'relative','right':'auto','left':'auto','top':'auto'});context.fn.trigger('tocExpand');context.fn.trigger('resize');});$.cookie('wikiEditor-'+context.instance+'-toc-width',context.modules.toc.$toc.data('openWidth'));return false;},build:function(context){function buildStructure(outline,offset,level){if(offset==undefined)offset=0;if(level==undefined)level=1;var sections=[];for(var i=offset;i<outline.length;i++){if(outline[i].nLevel==level){var sub=buildStructure(outline,i+1,level+1);if(sub.length){outline[i].sections=sub;}
609625 sections[sections.length]=outline[i];}else if(outline[i].nLevel<level){break;}}
610626 return sections;}
611 -function buildList(structure){var list=$('<ul />');for(i in structure){var wrapper=context.$content.find('.wikiEditor-toc-section-'+structure[i].index);if(wrapper.size()==0)
612 -wrapper=context.$content;var div=$('<div />').addClass('section-'+structure[i].index).data('wrapper',wrapper).click(function(event){context.fn.scrollToTop($(this).data('wrapper'),true);context.$textarea.textSelection('setSelection',{'start':0,'startContainer':$(this).data('wrapper')});$.wikiEditor.modules.toc.fn.unhighlight(context);$(this).addClass('current');if(typeof $.trackAction!='undefined')
 627+function buildList(structure){var list=$('<ul />');for(i in structure){var div=$('<div />').addClass('section-'+structure[i].index).data('index',structure[i].index).click(function(event){var wrapper=context.$content.find('.wikiEditor-toc-section-'+$(this).data('index'));if(wrapper.size()==0)
 628+wrapper=context.$content;context.fn.scrollToTop(wrapper,true);context.$textarea.textSelection('setSelection',{'start':0,'startContainer':wrapper});$.wikiEditor.modules.toc.fn.unhighlight(context);$(this).addClass('current');if(typeof $.trackAction!='undefined')
613629 $.trackAction('ntoc.heading');event.preventDefault();}).text(structure[i].text);if(structure[i].text=='')
614630 div.html('&nbsp;');var item=$('<li />').append(div);if(structure[i].sections!==undefined){item.append(buildList(structure[i].sections));}
615631 list.append(item);}
@@ -644,7 +660,7 @@
645661 rels.reverse();var id=rels.join('.');$.trackAction(id);}
646662 switch(action.type){case'replace':case'encapsulate':var parts={'pre':'','peri':'','post':''};for(part in parts){if(part+'Msg'in action.options){parts[part]=mw.usability.getMsg(action.options[part+'Msg'],(action.options[part]||null));}else{parts[part]=(action.options[part]||'')}}
647663 if('regex'in action.options&&'regexReplace'in action.options){var selection=context.$textarea.textSelection('getSelection');if(selection!=''&&selection.match(action.options.regex)){parts.peri=selection.replace(action.options.regex,action.options.regexReplace);parts.pre=parts.post='';}}
648 -context.$textarea.textSelection('encapsulateSelection',$.extend({},action.options,parts,{'replace':action.type=='replace'}));break;case'callback':if(typeof action.execute=='function'){action.execute(context);}
 664+context.$textarea.textSelection('encapsulateSelection',$.extend({},action.options,parts,{'replace':action.type=='replace'}));context.$iframe[0].contentWindow.focus();break;case'callback':if(typeof action.execute=='function'){action.execute(context);}
649665 break;case'dialog':context.$textarea.wikiEditor('openDialog',action.module);break;default:break;}},buildGroup:function(context,id,group){var $group=$('<div />').attr({'class':'group group-'+id,'rel':id});var label=$.wikiEditor.autoMsg(group,'label');if(label){$group.append('<div class="label">'+label+'</div>')}
650666 var empty=true;if('tools'in group){for(tool in group.tools){var tool=$.wikiEditor.modules.toolbar.fn.buildTool(context,tool,group.tools[tool]);if(tool){empty=false;$group.append(tool);}}}
651667 return empty?null:$group;},buildTool:function(context,id,tool){if('filters'in tool){for(filter in tool.filters){if($(tool.filters[filter]).size()==0){return null;}}}
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/js/plugins/jquery.wikiEditor.templateEditor.js
@@ -38,6 +38,7 @@
3939 markers.push( {
4040 start: tokenArray[beginIndex].offset,
4141 end: tokenArray[endIndex].offset,
 42+ type: 'template',
4243 anchor: 'wrap',
4344 afterWrap: $.wikiEditor.modules.templateEditor.fn.stylize,
4445 beforeUnwrap: function( node ) {
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/js/plugins/jquery.wikiEditor.toc.js
@@ -73,6 +73,7 @@
7474 context.modules.toc.$toc.data( 'previousWidth', context.$wikitext.width() );
7575 },
7676 mark: function( context, event ) {
 77+ var hash = '';
7778 var markers = context.modules.highlight.markers;
7879 var tokenArray = context.modules.highlight.tokenArray;
7980 var outline = context.data.outline = [];
@@ -86,6 +87,7 @@
8788 index: h,
8889 start: tokenArray[i].tokenStart,
8990 end: tokenArray[i].offset,
 91+ type: 'toc',
9092 anchor: 'before',
9193 afterWrap: function( node ) {
9294 var marker = $( node ).data( 'marker' );
@@ -95,24 +97,32 @@
9698 },
9799 onSkip: function( node ) {
98100 var marker = $( node ).data( 'marker' );
99 - $( node )
100 - .removeClass( 'wikiEditor-toc-section-' + $( node ).data( 'section' ) )
101 - .addClass( 'wikiEditor-toc-section-' + marker.index )
102 - .data( 'section', marker.index );
 101+ if ( $( node ).data( 'section' ) != marker.index ) {
 102+ $( node )
 103+ .removeClass( 'wikiEditor-toc-section-' + $( node ).data( 'section' ) )
 104+ .addClass( 'wikiEditor-toc-section-' + marker.index )
 105+ .data( 'section', marker.index );
 106+ }
103107 },
104108 getAnchor: function( ca1, ca2 ) {
105 - return $( ca1.previousSibling ).is( 'div.wikiEditor-toc-header' ) ?
106 - ca1.previousSibling : null;
 109+ return $( ca1.parentNode.previousSibling ).is( 'div.wikiEditor-toc-header' ) ?
 110+ ca1.parentNode.previousSibling : null;
107111 }
108112 } );
 113+ hash += tokenArray[i].match[2] + '\n';
109114 outline.push ( {
110115 'text': tokenArray[i].match[2],
111116 'level': tokenArray[i].match[1].length,
112117 'index': h
113118 } );
114119 }
115 - $.wikiEditor.modules.toc.fn.build( context );
116 - $.wikiEditor.modules.toc.fn.update( context );
 120+ // Only update the TOC if it's been changed - we do this by comparing a hash of the headings this time to last
 121+ if ( typeof context.modules.toc.lastHash == 'undefined' || context.modules.toc.lastHash !== hash ) {
 122+ $.wikiEditor.modules.toc.fn.build( context );
 123+ $.wikiEditor.modules.toc.fn.update( context );
 124+ // Remember the changed version
 125+ context.modules.toc.lastHash = hash;
 126+ }
117127 }
118128 },
119129 exp: [
@@ -249,7 +259,7 @@
250260 update: function( context ) {
251261 $.wikiEditor.modules.toc.fn.unhighlight( context );
252262
253 - var div = context.fn.beforeSelection( 'div.wikiEditor-toc-header' );
 263+ var div = context.fn.beforeSelection( 'wikiEditor-toc-header' );
254264 var section = div.data( 'section' ) || 0;
255265 if ( context.data.outline.length > 0 ) {
256266 var sectionLink = context.modules.toc.$toc.find( 'div.section-' + section );
@@ -383,17 +393,18 @@
384394 function buildList( structure ) {
385395 var list = $( '<ul />' );
386396 for ( i in structure ) {
387 - var wrapper = context.$content.find( '.wikiEditor-toc-section-' + structure[i].index );
388 - if ( wrapper.size() == 0 )
389 - wrapper = context.$content;
390397 var div = $( '<div />' )
391398 .addClass( 'section-' + structure[i].index )
392 - .data( 'wrapper', wrapper )
 399+ .data( 'index', structure[i].index )
393400 .click( function( event ) {
394 - context.fn.scrollToTop( $( this ).data( 'wrapper' ), true );
 401+ var wrapper = context.$content.find(
 402+ '.wikiEditor-toc-section-' + $( this ).data( 'index' ) );
 403+ if ( wrapper.size() == 0 )
 404+ wrapper = context.$content;
 405+ context.fn.scrollToTop( wrapper, true );
395406 context.$textarea.textSelection( 'setSelection', {
396407 'start': 0,
397 - 'startContainer': $(this).data( 'wrapper' )
 408+ 'startContainer': wrapper
398409 } );
399410 // Highlight the clicked link
400411 $.wikiEditor.modules.toc.fn.unhighlight( context );
@@ -488,7 +499,9 @@
489500 if( ui.size.width <= parseFloat( $.wikiEditor.modules.toc.cfg.minimumWidth ) ) {
490501 context.modules.toc.$toc.trigger( 'collapse.wikiEditor-toc' );
491502 } else {
492 - context.modules.toc.$toc.find( 'div' ).autoEllipsis( { 'position': 'right', 'tooltip': true, 'restoreText': true } );
 503+ context.modules.toc.$toc.find( 'div' ).autoEllipsis(
 504+ { 'position': 'right', 'tooltip': true, 'restoreText': true }
 505+ );
493506 context.modules.toc.$toc.data( 'openWidth', ui.size.width );
494507 $.cookie( 'wikiEditor-' + context.instance + '-toc-width', ui.size.width );
495508 }
@@ -552,7 +565,9 @@
553566 buildResizeControls();
554567 buildCollapseControls();
555568 }
556 - context.modules.toc.$toc.find( 'div' ).autoEllipsis( { 'position': 'right', 'tooltip': true, 'restoreText': true } );
 569+ context.modules.toc.$toc.find( 'div' ).autoEllipsis(
 570+ { 'position': 'right', 'tooltip': true, 'restoreText': true }
 571+ );
557572 }
558573 }
559574 }
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/js/plugins/jquery.wikiEditor.js
@@ -89,7 +89,7 @@
9090 }
9191 // Check over each browser condition to determine if we are running in a compatible client
9292 var browser = $.wikiEditor.browsers[$( 'body' ).is( '.rtl' ) ? 'rtl' : 'ltr'][$.browser.name];
93 - for ( condition in browser ) {
 93+ for ( var condition in browser ) {
9494 var op = browser[condition][0];
9595 var val = browser[condition][1];
9696 if ( typeof val == 'string' ) {
@@ -118,7 +118,7 @@
119119 'autoMsg': function( object, property ) {
120120 // Accept array of possible properties, of which the first one found will be used
121121 if ( typeof property == 'object' ) {
122 - for ( i in property ) {
 122+ for ( var i in property ) {
123123 if ( property[i] in object || property[i] + 'Msg' in object ) {
124124 property = property[i];
125125 break;
@@ -199,7 +199,13 @@
200200 // Unique numeric ID of this instance used both for looking up and differentiating instances of wikiEditor
201201 'instance': $.wikiEditor.instances.push( $(this) ) - 1,
202202 // Array mapping elements in the textarea to character offsets
203 - 'offsets': null
 203+ 'offsets': null,
 204+ // Cache for context.fn.htmlToText()
 205+ 'htmlToTextMap': {},
 206+ // The previous HTML of the iframe, stored to detect whether something really changed.
 207+ 'oldHTML': null,
 208+ // Same for delayedChange()
 209+ 'oldDelayedHTML': null
204210 };
205211
206212 /*
@@ -223,12 +229,12 @@
224230 } else if ( typeof data == 'object' ) {
225231 modules = data;
226232 }
227 - for ( module in modules ) {
 233+ for ( var module in modules ) {
228234 // Check for the existance of an available module with a matching name and a create function
229235 if ( typeof module == 'string' && module in $.wikiEditor.modules ) {
230236 // Extend the context's core API with this module's own API calls
231237 if ( 'api' in $.wikiEditor.modules[module] ) {
232 - for ( call in $.wikiEditor.modules[module].api ) {
 238+ for ( var call in $.wikiEditor.modules[module].api ) {
233239 // Modules may not overwrite existing API functions - first come, first serve
234240 if ( !( call in context.api ) ) {
235241 context.api[call] = $.wikiEditor.modules[module].api[call];
@@ -262,12 +268,23 @@
263269 */
264270 'change': function( event ) {
265271 event.data.scope = 'division';
266 - context.fn.purgeOffsets();
 272+ var newHTML = context.$content.html();
 273+ if ( context.oldHTML != newHTML ) {
 274+ context.fn.purgeOffsets();
 275+ context.oldHTML = newHTML;
 276+ event.data.scope = 'realchange';
 277+ }
267278 return true;
268279 },
269280 'delayedChange': function( event ) {
270 - // Redirect - since we want the same functionality
271 - return context.evt.change( event );
 281+ event.data.scope = 'division';
 282+ var newHTML = context.$content.html();
 283+ if ( context.oldDelayedHTML != newHTML ) {
 284+ context.fn.purgeOffsets();
 285+ context.oldDelayedHTML = newHTML;
 286+ event.data.scope = 'realchange';
 287+ }
 288+ return true;
272289 }
273290 };
274291
@@ -293,7 +310,7 @@
294311 }
295312 }
296313 // Pass the event around to all modules activated on this context
297 - for ( module in context.modules ) {
 314+ for ( var module in context.modules ) {
298315 if (
299316 module in $.wikiEditor.modules &&
300317 'evt' in $.wikiEditor.modules[module] &&
@@ -360,22 +377,71 @@
361378 .appendTo( context.$ui );
362379 },
363380 'htmlToText': function( html ) {
 381+ // This function is slow for large inputs, so aggressively cache input/output pairs
 382+ if ( html in context.htmlToTextMap ) {
 383+ return context.htmlToTextMap[html];
 384+ }
 385+ var origHTML = html;
 386+
364387 // We use this elaborate trickery for cross-browser compatibility
365388 // IE does overzealous whitespace collapsing for $( '<pre />' ).html( html );
366 - var $pre = $( '<pre>' +
367 - html
 389+ // We also do <br> and easy cases for <p> conversion here, complicated cases are handled later
 390+ html = html
368391 .replace( /\r?\n/g, "" ) // IE7 inserts newlines before block elements
369 - .replace( /\<br[^\>]*\>/gi, "\n" )
370392 .replace( /&nbsp;/g, " " ) // We inserted these to prevent IE from collapsing spaces
371 - .replace( /\<p[^\>]*\>/gi, "\n" ) // IE uses </p><p> for user-inserted line breaks
372 - .replace( /\<\/p[^\>]*\>/gi, "" )
373 - .replace( /\<div[^\>]*\>/gi, "\n" ) // Webkit uses </div><div> for user-inserted line breaks
374 - .replace( /\<\/div[^\>]*\>/gi, "" )
375 - + '</pre>' );
376 - // Get rid of the noincludes when getting text
 393+ .replace( /\<br[^\>]*\>/gi, "\n" ) // <br> conversion
 394+ .replace( /\<\/p\>\<p\>/gi, "\n" ) // Easy case for <p> conversion
 395+ .replace( /\<\/p\>(\n*)\<p\>/gi, "$1\n" );
 396+ // Save leading and trailing whitespace now and restore it later. IE eats it all, and even Firefox
 397+ // won't leave everything alone
 398+ var leading = html.match( /^\s*/ )[0];
 399+ var trailing = html.match( /\s*$/ )[0];
 400+ html = html.substr( leading.length, html.length - leading.length - trailing.length );
 401+ var $pre = $( '<pre>' + html + '</pre>' );
377402 $pre.find( '.wikiEditor-noinclude' ).each( function() { $( this ).remove(); } );
378 - $pre.find( '.wikiEditor-tab' ).each( function() { $( this ).text( "\t" ) } );
379 - return $pre.text();
 403+ // Convert tabs, <p>s and <br>s back
 404+ $pre.find( '.wikiEditor-tab' ).each( function() { $( this ).text( "\t" ); } );
 405+ $pre.find( 'br' ).each( function() { $( this ).replaceWith( "\n" ); } );
 406+ // Converting <p>s is wrong if there's nothing before them, so check that.
 407+ // .find( '* + p' ) isn't good enough because textnodes aren't considered
 408+ $pre.find( 'p' ).each( function() {
 409+ if ( this.previousSibling || this.parentNode != $pre.get( 0 ) ) {
 410+ var text = $( this ).text();
 411+ // If this <p> is preceded by some text, add a \n at the beginning, and if
 412+ // it's followed by a textnode, add a \n at the end
 413+ // We need the traverser because there can be other weird stuff in between
 414+
 415+ // Check for preceding text
 416+ // FIXME: Add an option to disable depth checking, -10 is a hack
 417+ var t = new context.fn.rawTraverser( this.firstChild, -10, this ).prev();
 418+ while ( t && t.node.nodeName != '#text' && t.node.nodeName != 'BR' && t.node.nodeName != 'P' ) {
 419+ t = t.prev();
 420+ }
 421+ if ( t ) {
 422+ text = "\n" + text;
 423+ }
 424+
 425+ // Check for following text
 426+ t = new context.fn.rawTraverser( this.lastChild, -10, this ).next();
 427+ while ( t && t.node.nodeName != '#text' && t.node.nodeName != 'BR' && t.node.nodeName != 'P' ) {
 428+ t = t.next();
 429+ }
 430+ if ( t && !t.inP && t.node.nodeName == '#text' && t.node.nodeValue.charAt( 0 ) != '\n'
 431+ && t.node.nodeValue.charAt( 0 ) != '\r' ) {
 432+ text += "\n";
 433+ }
 434+ $( this ).text( text );
 435+ }
 436+ } );
 437+ var retval;
 438+ if ( $.browser.msie ) {
 439+ // IE aggressively collapses whitespace in .text() after having done DOM manipulation,
 440+ // but for some crazy reason this does work. Also convert \r back to \n
 441+ retval = $( '<pre>' + $pre.html() + '</pre>' ).text().replace( /\r/g, '\n' );
 442+ } else {
 443+ retval = $pre.text();
 444+ }
 445+ return context.htmlToTextMap[origHTML] = leading + retval + trailing;
380446 },
381447
382448 /*
@@ -400,6 +466,17 @@
401467 if ( context.$iframe[0].contentWindow.getSelection ) {
402468 // Firefox and Opera
403469 retval = context.$iframe[0].contentWindow.getSelection();
 470+ if ( $.browser.opera ) {
 471+ // Opera strips newlines in getSelection(), so we need something more sophisticated
 472+ if ( retval.rangeCount > 0 ) {
 473+ retval = context.fn.htmlToText( $( '<pre />' )
 474+ .append( retval.getRangeAt( 0 ).cloneContents() )
 475+ .html()
 476+ );
 477+ } else {
 478+ retval = '';
 479+ }
 480+ }
404481 } else if ( context.$iframe[0].contentWindow.document.selection ) { // should come last; Opera!
405482 // IE
406483 retval = context.$iframe[0].contentWindow.document.selection.createRange();
@@ -443,25 +520,47 @@
444521 // Firefox and Opera
445522 var range = context.$iframe[0].contentWindow.getSelection().getRangeAt( 0 );
446523 if ( options.ownline ) {
 524+ // We need to figure out if the cursor is at the start or end of a line
 525+ var atStart = false, atEnd = false;
447526 var body = context.$content.get( 0 );
448 - // TODO: This'll probably break with syntax highlighting
449 - // When the selection starts at the beginning of a line, it'll have either
450 - // startOffset == 0 or startContainer == body
451 - if ( range.startOffset != 0 && range.startContainer != body ) {
 527+ if ( range.startOffset == 0 ) {
 528+ // Start of a line
 529+ // FIXME: Not necessarily the case with syntax highlighting or
 530+ // template collapsing
 531+ atStart = true;
 532+ } else if ( range.startContainer == body ) {
 533+ // Look up the node just before the start of the selection
 534+ // If it's a <BR>, we're at the start of a line that starts with a
 535+ // block element; if not, we're at the end of a line
 536+ var n = body.firstChild;
 537+ for ( var i = 0; i < range.startOffset - 1 && n; i++ ) {
 538+ n = n.nextSibling;
 539+ }
 540+ if ( n && n.nodeName == 'BR' ) {
 541+ atStart = true;
 542+ } else {
 543+ atEnd = true;
 544+ }
 545+ } else if ( range.startContainer.nodeName == '#text' &&
 546+ range.startOffset == range.startContainer.nodeValue.length ) {
 547+ // Apparently this happens when splitting text nodes
 548+ atEnd = true;
 549+ }
 550+
 551+ if ( !atStart ) {
452552 pre = "\n" + options.pre;
453553 }
454 - // TODO: Will this still work with syntax highlighting?
455 - // When the selection ends at the end of a line, it'll have endContainer == body
456 - // and endOffset != 0
457 - if ( range.endContainer != body || range.endOffset == 0 ) {
 554+ if ( !atEnd ) {
458555 post += "\n";
459556 }
460557 }
461558 var insertText = "";
462559 if ( options.splitlines ) {
463 - for( var i = 0; i < selTextArr.length; i++ ) {
464 - insertText = insertText + pre + selTextArr[i] + post;
465 - if( i != selTextArr.length - 1 ) insertText += "\n";
 560+ for( var j = 0; j < selTextArr.length; j++ ) {
 561+ insertText = insertText + pre + selTextArr[j] + post;
 562+ if( j != selTextArr.length - 1 ) {
 563+ insertText += "\n";
 564+ }
466565 }
467566 } else {
468567 insertText = pre + selText + post;
@@ -507,9 +606,9 @@
508607 // TODO: Clean this up. Duplicate code due to the pre-existing browser specific structure of this function
509608 var insertText = "";
510609 if ( options.splitlines ) {
511 - for( var i = 0; i < selTextArr.length; i++ ) {
512 - insertText = insertText + pre + selTextArr[i] + post;
513 - if( i != selTextArr.length - 1 ) {
 610+ for( var j = 0; j < selTextArr.length; j++ ) {
 611+ insertText = insertText + pre + selTextArr[j] + post;
 612+ if( j != selTextArr.length - 1 ) {
514613 insertText += "\n";
515614 }
516615 }
@@ -634,14 +733,14 @@
635734 */
636735
637736 /**
638 - * Get the first element before the selection matching a certain selector.
639 - * @param selector Selector to match. Defaults to '*'
 737+ * Get the first element before the selection that's in a certain class
 738+ * @param classname Class to match. Defaults to '', meaning any class
640739 * @param strict If true, the element the selection starts in cannot match (default: false)
641740 * @return jQuery object
642741 */
643 - 'beforeSelection': function( selector, strict ) {
644 - if ( typeof selector == 'undefined' ) {
645 - selector = '*';
 742+ 'beforeSelection': function( classname, strict ) {
 743+ if ( typeof classname == 'undefined' ) {
 744+ classname = '';
646745 }
647746 var e, offset;
648747 if ( context.$iframe[0].contentWindow.getSelection ) {
@@ -652,7 +751,7 @@
653752 // Start at the selection's start and traverse the DOM backwards
654753 // This is done by traversing an element's children first, then the element itself, then its parent
655754 e = selection.getRangeAt( 0 ).startContainer;
656 - offset = selection.startOffset;
 755+ offset = selection.getRangeAt( 0 ).startOffset;
657756 } else {
658757 return $( [] );
659758 }
@@ -667,7 +766,7 @@
668767 // not in the iframe
669768 try {
670769 range2.setEndPoint( 'EndToStart', range );
671 - } catch ( e ) {
 770+ } catch ( ex ) {
672771 return $( [] );
673772 }
674773 var seekPos = context.fn.htmlToText( range2.htmlText ).length;
@@ -691,9 +790,14 @@
692791 }
693792 e = newE || e;
694793 }
 794+
 795+ // We'd normally use if( $( e ).hasClass( class ) in the while loop, but running the jQuery
 796+ // constructor thousands of times is very inefficient
 797+ var classStr = ' ' + classname + ' ';
695798 while ( e ) {
696 - if ( $( e ).is( selector ) && !strict )
 799+ if ( !strict && ( !classname || ( ' ' + e.className + ' ' ).indexOf( classStr ) != -1 ) ) {
697800 return $( e );
 801+ }
698802 var next = e.previousSibling;
699803 while ( next && next.lastChild ) {
700804 next = next.lastChild;
@@ -704,8 +808,88 @@
705809 return $( [] );
706810 },
707811 /**
 812+ * Object used by traverser(). Don't use this unless you know what you're doing
 813+ */
 814+ 'rawTraverser': function( node, depth, inP ) {
 815+ this.node = node;
 816+ this.depth = depth;
 817+ this.inP = inP;
 818+ this.next = function() {
 819+ var p = this.node;
 820+ var nextDepth = this.depth;
 821+ var nextInP = this.inP;
 822+ while ( p && !p.nextSibling ) {
 823+ p = p.parentNode;
 824+ nextDepth--;
 825+ if ( nextDepth == 0 ) {
 826+ // We're back at the start node
 827+ p = null;
 828+ }
 829+ if ( p && p.nodeName == "P" ) {
 830+ nextInP = null;
 831+ }
 832+ }
 833+ p = p ? p.nextSibling : null;
 834+ if ( p && p.nodeName == "P" ) {
 835+ nextInP = p;
 836+ }
 837+ do {
 838+ // Filter nodes with the wikiEditor-noinclude class
 839+ // Don't use $( p ).hasClass( 'wikiEditor-noinclude' ) because
 840+ // $() is slow in a tight loop
 841+ while ( p && ( ' ' + p.className + ' ' ).indexOf( ' wikiEditor-noinclude ' ) != -1 ) {
 842+ p = p.nextSibling;
 843+ }
 844+ if ( p && p.firstChild ) {
 845+ p = p.firstChild;
 846+ nextDepth++;
 847+ if ( p.nodeName == "P" ) {
 848+ nextInP = p;
 849+ }
 850+ }
 851+ } while ( p && p.firstChild );
 852+ return p ? new context.fn.rawTraverser( p, nextDepth, nextInP ) : null;
 853+ };
 854+ this.prev = function() {
 855+ var p = this.node;
 856+ var prevDepth = this.depth;
 857+ var prevInP = this.inP;
 858+ while ( p && !p.previousSibling ) {
 859+ p = p.parentNode;
 860+ prevDepth--;
 861+ if ( prevDepth == 0 ) {
 862+ // We're back at the start node
 863+ p = null;
 864+ }
 865+ if ( p && p.nodeName == "P" ) {
 866+ prevInP = null;
 867+ }
 868+ }
 869+ p = p ? p.previousSibling : null;
 870+ if ( p && p.nodeName == "P" ) {
 871+ prevInP = p;
 872+ }
 873+ do {
 874+ // Filter nodes with the wikiEditor-noinclude class
 875+ // Don't use $( p ).hasClass( 'wikiEditor-noinclude' ) because
 876+ // $() is slow in a tight loop
 877+ while ( p && ( ' ' + p.className + ' ' ).indexOf( ' wikiEditor-noinclude ' ) != -1 ) {
 878+ p = p.previousSibling;
 879+ }
 880+ if ( p && p.lastChild ) {
 881+ p = p.lastChild;
 882+ prevDepth++;
 883+ if ( p.nodeName == "P" ) {
 884+ prevInP = p;
 885+ }
 886+ }
 887+ } while ( p && p.lastChild );
 888+ return p ? new context.fn.rawTraverser( p, prevDepth, prevInP ) : null;
 889+ };
 890+ },
 891+ /**
708892 * Get an object used to traverse the leaf nodes in the iframe DOM. This traversal skips leaf nodes
709 - * inside an element with the wikiEditor-noinclude class.
 893+ * inside an element with the wikiEditor-noinclude class. This basically wraps rawTraverser
710894 *
711895 * Usage:
712896 * var t = context.fn.traverser( context.$content );
@@ -715,48 +899,10 @@
716900 * // Trying to advance past the end will set t.node to null
717901 */
718902 'traverser': function( start ) {
719 - function Traverser( node, depth, inP ) {
720 - this.node = node;
721 - this.depth = depth;
722 - this.inP = inP;
723 - this.next = function() {
724 - var p = this.node;
725 - var nextDepth = this.depth;
726 - var nextInP = this.inP;
727 - while ( p && !p.nextSibling ) {
728 - if ( p.nodeName == "P" ) {
729 - nextInP = false;
730 - }
731 - p = p.parentNode;
732 - nextDepth--;
733 - if ( nextDepth == 0 ) {
734 - // We're back at the start node
735 - p = null;
736 - }
737 - }
738 - p = p ? p.nextSibling : null;
739 - do {
740 - // Filter nodes with the wikiEditor-noinclude class
741 - // Don't use $( p ).hasClass( 'wikiEditor-noinclude' ) because
742 - // $() is slow in a tight loop
743 - while ( p && ( ' ' + p.className + ' ' ).indexOf( ' wikiEditor-noinclude ' ) != -1 ) {
744 - p = p.nextSibling;
745 - }
746 - if ( p && p.firstChild ) {
747 - p = p.firstChild;
748 - nextDepth++;
749 - if ( p.nodeName == "P" ) {
750 - nextInP = true;
751 - }
752 - }
753 - } while ( p && p.firstChild );
754 - return p ? new Traverser( p, nextDepth, nextInP ) : null;
755 - };
756 - }
757903 // Find the leftmost leaf node in the tree
758904 var node = start.jquery ? start.get( 0 ) : start;
759905 var depth = 0;
760 - var inP = node.nodeName == "P";
 906+ var inP = node.nodeName == "P" ? node : null;
761907 do {
762908 // Filter nodes with the wikiEditor-noinclude class
763909 // Don't use $( p ).hasClass( 'wikiEditor-noinclude' ) because
@@ -768,11 +914,11 @@
769915 node = node.firstChild;
770916 depth++;
771917 if ( node.nodeName == "P" ) {
772 - inP = true;
 918+ inP = node;
773919 }
774920 }
775921 } while ( node && node.firstChild );
776 - return new Traverser( node, depth, inP );
 922+ return new context.fn.rawTraverser( node, depth, inP );
777923 },
778924 'getOffset': function( offset ) {
779925 if ( !context.offsets ) {
@@ -796,7 +942,7 @@
797943 var base = context.offsets[lowerBound];
798944 return context.offsets[offset] = {
799945 'node': base.node,
800 - 'offset': base.offset + offset - o,
 946+ 'offset': base.offset + offset - lowerBound,
801947 'length': base.length,
802948 'depth': base.depth,
803949 'lastTextNode': base.lastTextNode,
@@ -811,13 +957,13 @@
812958 var t = context.fn.traverser( context.$content );
813959 var pos = 0, lastTextNode = null, lastTextNodeDepth = null;
814960 while ( t ) {
815 - if ( t.node.nodeName != '#text' && t.node.nodeName != 'BR' ) {
 961+ if ( t.node.nodeName != '#text' && t.node.nodeName != 'BR' && t.node.nodeName != 'P' ) {
816962 t = t.next();
817963 continue;
818964 }
819965 var nextPos = t.node.nodeName == '#text' ? pos + t.node.nodeValue.length : pos + 1;
820966 var nextT = t.next();
821 - var leavingP = t.inP && nextT && !nextT.inP;
 967+ var leavingP = t.node.nodeName != 'P' && t.inP && nextT && ( !nextT.inP || nextT.inP != t.inP );
822968 context.offsets[pos] = {
823969 'node': t.node,
824970 'offset': 0,
@@ -887,7 +1033,7 @@
8881034 // Setup the intial view
8891035 context.view = 'wikitext';
8901036 // Trigger the "resize" event anytime the window is resized
891 - $( window ).resize( function( event ) { context.fn.trigger( 'resize', event ) } );
 1037+ $( window ).resize( function( event ) { context.fn.trigger( 'resize', event ); } );
8921038 // Create an iframe in place of the text area
8931039 context.$iframe = $( '<iframe></iframe>' )
8941040 .attr( {
@@ -923,7 +1069,13 @@
9241070 // If we just do "context.$content.text( context.$textarea.val() )", Internet Explorer will strip out the
9251071 // whitespace charcters, specifically "\n" - so we must manually encode the text and append it
9261072 // TODO: Refactor this into a textToHtml() function
927 - var html = context.$textarea.val();
 1073+ // Because we're gonna insert instances of <br>, &nbsp; and <span class="wikiEditor-tab"></span>,
 1074+ // we have to escape existing instances first. This'll cause them to be double-escaped, which we
 1075+ // fix later on
 1076+ var html = context.$textarea.val()
 1077+ .replace( /&nbsp;/g, '&amp;nbsp;' )
 1078+ .replace( /\<br\>/g, '&lt;br&gt;' )
 1079+ .replace( /\<span class="wikiEditor-tab"\>\<\/span\>/g, '&lt;span class=&quot;wikiEditor-tab&quot;&gt;&lt;/span&gt;' );
9281080 // We must do some extra processing on IE to avoid dirty diffs, specifically IE will collapse leading spaces
9291081 if ( $.browser.msie ) {
9301082 // Browser sniffing is not ideal, but executing this code on a non-broken browser doesn't cause harm
@@ -939,11 +1091,20 @@
9401092 }
9411093 // Use a dummy div to escape all entities
9421094 // This'll also escape <br>, <span> and &nbsp; , so we unescape those after
943 - html = $( '<div />' ).text( html.replace( /\r?\n/g, '<br>' ) ).html()
 1095+ // We also need to unescape the doubly-escaped things mentioned above
 1096+ html = $( '<div />' ).text( '<p>' + html.replace( /\r?\n/g, '</p><p>' ) + '</p>' ).html()
9441097 .replace( /&amp;nbsp;/g, '&nbsp;' )
945 - .replace( /&lt;br&gt;/g, '<br>' )
946 - .replace( /&lt;span class=&quot;wikiEditor-tab&quot;&gt;&lt;\/span&gt;/g, '<span class="wikiEditor-tab"></span>' );
 1098+ // Allow p tags to survive encoding
 1099+ .replace( /&lt;p&gt;/g, '<p>' )
 1100+ .replace( /&lt;\/p&gt;/g, '</p>' )
 1101+ // Empty p tags should just be br tags
 1102+ .replace( /<p><\/p>/g, '<br>' )
 1103+ .replace( /&lt;span class=&quot;wikiEditor-tab&quot;&gt;&lt;\/span&gt;/g, '<span class="wikiEditor-tab"></span>' )
 1104+ .replace( /&amp;amp;nbsp;/g, '&amp;nbsp;' )
 1105+ .replace( /&amp;lt;br&amp;gt;/g, '&lt;br&gt;' )
 1106+ .replace( /&amp;lt;span class=&amp;quot;wikiEditor-tab&amp;quot;&amp;gt;&amp;lt;\/span&amp;gt;/g, '&lt;span class=&quot;wikiEditor-tab&quot;&gt;&lt;/span&gt;' );
9471107 context.$content.html( html );
 1108+ context.oldHTML = html;
9481109
9491110 // Reflect direction of parent frame into child
9501111 if ( $( 'body' ).is( '.rtl' ) ) {
@@ -976,19 +1137,19 @@
9771138 window.onbeforeunload = function() {
9781139 context.$textarea.val( context.$textarea.textSelection( 'getContents' ) );
9791140 return context.fallbackWindowOnBeforeUnload ? context.fallbackWindowOnBeforeUnload() : null;
980 - }
 1141+ };
9811142 }
9821143
9831144 /* API Execution */
9841145
9851146 // Since javascript gives arguments as an object, we need to convert them so they can be used more easily
986 -arguments = $.makeArray( arguments );
 1147+var args = $.makeArray( arguments );
9871148 // There would need to be some arguments if the API is being called
988 -if ( arguments.length > 0 ) {
 1149+if ( args.length > 0 ) {
9891150 // Handle API calls
990 - var call = arguments.shift();
 1151+ var call = args.shift();
9911152 if ( call in context.api ) {
992 - context.api[call]( context, typeof arguments[0] == 'undefined' ? {} : arguments[0] );
 1153+ context.api[call]( context, typeof args[0] == 'undefined' ? {} : args[0] );
9931154 }
9941155 }
9951156
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/js/plugins/jquery.wikiEditor.toolbar.js
@@ -109,7 +109,7 @@
110110 $( $.wikiEditor.modules.toolbar.fn.buildCharacter( data[type][character], actions ) )
111111 .click( function() {
112112 $.wikiEditor.modules.toolbar.fn.doAction( $(this).parent().data( 'context' ),
113 - $(this).parent().data( 'actions' )[$(this).attr( 'rel' )] );
 113+ $(this).parent().data( 'actions' )[$(this).attr( 'rel' )] );
114114 return false;
115115 } )
116116 );
@@ -205,7 +205,7 @@
206206 doAction : function( context, action, source ) {
207207 // Verify that this has been called from a source that's within the toolbar
208208 // 'trackAction' defined in click tracking
209 - if ($.trackAction != undefined && source.closest( '.wikiEditor-ui-toolbar' ).size() ) {
 209+ if ( $.trackAction != undefined && source.closest( '.wikiEditor-ui-toolbar' ).size() ) {
210210 // Build a unique id for this action by tracking the parent rel attributes up to the toolbar level
211211 var rels = [];
212212 var step = source;
@@ -223,7 +223,7 @@
224224 }
225225 rels.reverse();
226226 var id = rels.join( '.' );
227 - $.trackAction(id);
 227+ $.trackAction( id );
228228 }
229229 switch ( action.type ) {
230230 case 'replace':
@@ -249,6 +249,7 @@
250250 'encapsulateSelection',
251251 $.extend( {}, action.options, parts, { 'replace': action.type == 'replace' } )
252252 );
 253+ context.$iframe[0].contentWindow.focus();
253254 break;
254255 case 'callback':
255256 if ( typeof action.execute == 'function' ) {
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/js/plugins/jquery.wikiEditor.highlight.js
@@ -34,7 +34,7 @@
3535 * ; Definition
3636 * : Definition
3737 */
38 - if ( event.data.scope == 'division' ) {
 38+ if ( event.data.scope == 'realchange' ) {
3939 $.wikiEditor.modules.highlight.fn.scan( context, "" );
4040 $.wikiEditor.modules.highlight.fn.mark( context, "", "" );
4141 }
@@ -55,7 +55,7 @@
5656 * @param config Configuration object to create module from
5757 */
5858 create: function( context, config ) {
59 - // hook $.wikiEditor.modules.highlight.evt.change to context.evt.change
 59+ context.modules.highlight.markersStr = '';
6060 },
6161 /**
6262 * Divides text into divisions
@@ -144,6 +144,7 @@
145145 * @param tokens
146146 */
147147 // FIXME: What do division and tokens do?
 148+ // TODO: Document the scan() and mark() APIs somewhere
148149 mark: function( context, division, tokens ) {
149150 // Reset markers
150151 var markers = context.modules.highlight.markers = [];
@@ -151,7 +152,21 @@
152153 context.fn.trigger( 'mark' );
153154 markers.sort( function( a, b ) { return a.start - b.start || a.end - b.end; } );
154155
 156+ // Serialize the markers array to a string and compare it with the one stored in the previous run
 157+ // If they're equal, there's no markers to change
 158+ var markersStr = '';
 159+ for ( var i = 0; i < markers.length; i++ ) {
 160+ markersStr += markers[i].start + ',' + markers[i].end + ',' + markers[i].type + ',';
 161+ }
 162+ if ( context.modules.highlight.markersStr == markersStr ) {
 163+ // No change, bail out
 164+ return;
 165+ }
 166+ context.modules.highlight.markersStr = markersStr;
 167+
155168 // Traverse the iframe DOM, inserting markers where they're needed.
 169+ // Store visited markers here so we know which markers should be removed
 170+ var visited = [];
156171 for ( var i = 0; i < markers.length; i++ ) {
157172 // We want to isolate each marker, so we may need to split textNodes
158173 // if a marker starts or ends halfway one.
@@ -163,23 +178,27 @@
164179 }
165180 var startNode = s.node;
166181 var startDepth = s.depth;
167 - // The next marker starts somewhere in this textNode or at this BR
168 - if ( s.offset > 0 ) {
169 - // t.node must be a textnode at this point because
170 - // only textnodes can have offset > 0
171 -
172 - // Split off the prefix
173 - // This leaves the prefix in the current node and puts
174 - // the rest in a new node which is our start node
175 - startNode = startNode.splitText( s.offset );
176 - }
 182+
177183 // Don't wrap leading BRs, produces undesirable results
178 - while ( startNode.nodeName == 'BR' ) {
 184+ // FIXME: It's also possible that the offset is a bit high because getOffset() has incremented
 185+ // .length to fake the newline caused by startNode being in a P. In this case, prevent
 186+ // the textnode splitting below from making startNode an empty textnode, IE barfs on that
 187+ while ( startNode.nodeName == 'BR' || s.offset == startNode.nodeValue.length ) {
179188 start++;
180189 s = context.fn.getOffset( start );
181190 startNode = s.node;
182191 startDepth = s.depth;
183192 }
 193+
 194+ // The next marker starts somewhere in this textNode or at this BR
 195+ if ( s.offset > 0 && s.node.nodeName == '#text' ) {
 196+ // Split off the prefix
 197+ // This leaves the prefix in the current node and puts
 198+ // the rest in a new node which is our start node
 199+ startNode = startNode.splitText( s.offset );
 200+ // This also invalidates cached offset objects
 201+ context.fn.purgeOffsets(); // TODO: Optimize better, get end offset object earlier
 202+ }
184203
185204 var end = markers[i].end;
186205 var e = context.fn.getOffset( end );
@@ -189,14 +208,13 @@
190209 }
191210 var endNode = e.node;
192211 var endDepth = e.depth;
193 - if ( e.offset < e.length - 1 ) {
194 - // t.node must be a textnode at this point because
195 - // .length is 1 for BRs and offset can't be < 0
196 -
 212+ if ( e.offset < e.length - 1 && e.node.nodeName == '#text' ) {
197213 // Split off the suffix - This puts the suffix in a new node and leaves the rest in the current
198214 // node.
199215 // endNode.nodeValue.length - ( newPos - markers[i].end )
200216 endNode.splitText( e.offset + 1 );
 217+ // This also invalidates cached offset objects
 218+ context.fn.purgeOffsets(); // TODO: Optimize better, get end offset object earlier
201219 }
202220
203221 // Don't wrap trailing BRs, doing that causes weird issues
@@ -236,13 +254,19 @@
237255 ca1 = ca1.parentNode.firstChild == ca1 ? ca1.parentNode : null;
238256 ca2 = ca2.parentNode.lastChild == ca2 ? ca2.parentNode : null;
239257 }
240 - if ( ca1 && ca2 && ca1.parentNode && ca2.nextSibling ) {
 258+ if ( ca1 && ca2 && ca1.parentNode ) {
241259 var anchor = markers[i].getAnchor( ca1, ca2 );
242260 if ( !anchor ) {
243261 // We have to store things like .parentNode and .nextSibling because appendChild() changes these
244262 // properties
245263 var newNode = ca1.ownerDocument.createElement( 'div' );
246264 var commonAncestor = ca1.parentNode;
 265+ // Special case: can't put block elements in a <p>
 266+ if ( commonAncestor.nodeName == 'P' && commonAncestor.parentNode ) {
 267+ commonAncestor = commonAncestor.parentNode;
 268+ ca1 = ca1.parentNode;
 269+ ca2 = ca2.parentNode;
 270+ }
247271 var nextNode = ca2.nextSibling;
248272 if ( markers[i].anchor == 'wrap' ) {
249273 // Append all nodes between ca1 and ca2 (inclusive) to newNode
@@ -269,22 +293,32 @@
270294 }
271295
272296 $( newNode ).data( 'marker', markers[i] )
273 - .addClass( 'wikiEditor-highlight wikiEditor-highlight-tmp' );
 297+ .addClass( 'wikiEditor-highlight' );
 298+ visited[i] = newNode;
274299
275300 // Allow the module adding this marker to manipulate it
276301 markers[i].afterWrap( newNode, markers[i] );
277302 } else {
278 - // Temporarily add a class for bookkeeping purposes
279 - $( anchor )
280 - .addClass( 'wikiEditor-highlight-tmp' )
281 - .data( 'marker', markers[i] );
 303+ visited[i] = anchor;
 304+ // Update the marker object
 305+ $( anchor ).data( 'marker', markers[i] );
282306 markers[i].onSkip( anchor );
283307 }
284308 }
285309 }
286310
287311 // Remove markers that were previously inserted but weren't passed to this function
288 - context.$content.find( 'div.wikiEditor-highlight:not(.wikiEditor-highlight-tmp)' ).each( function() {
 312+ // This function works because visited[] contains the visited elements in order and find() and each()
 313+ // preserve order
 314+ var j = 0;
 315+ context.$content.find( 'div.wikiEditor-highlight' ).each( function() {
 316+ if ( visited[j] == this ) {
 317+ // This marker is legit, leave it in
 318+ j++;
 319+ return true;
 320+ }
 321+
 322+ // Remove this marker
289323 if ( $(this).data( 'marker' ) && typeof $(this).data( 'marker' ).unwrap == 'function' )
290324 $(this).data( 'marker' ).unwrap( this );
291325 if ( $(this).children().size() > 0 ) {
@@ -293,8 +327,6 @@
294328 $(this).replaceWith( $(this).html() );
295329 }
296330 });
297 - // Remove temporary class
298 - context.$content.find( 'div.wikiEditor-highlight-tmp' ).removeClass( 'wikiEditor-highlight-tmp' );
299331 }
300332 }
301333
Index: branches/wmf-deployment/extensions/UsabilityInitiative_alpha/UsabilityInitiative.hooks.php
@@ -21,19 +21,19 @@
2222 array( 'src' => 'css/suggestions.css', 'version' => 6 ),
2323 array( 'src' => 'css/vector.collapsibleNav.css', 'version' => 7 ),
2424 array( 'src' => 'css/vector.footerCleanup.css', 'version' => 1 ),
25 - array( 'src' => 'css/wikiEditor.css', 'version' => 8 ),
26 - array( 'src' => 'css/wikiEditor.dialogs.css', 'version' => 15 ),
 25+ array( 'src' => 'css/wikiEditor.css', 'version' => 9 ),
 26+ array( 'src' => 'css/wikiEditor.dialogs.css', 'version' => 16 ),
2727 array( 'src' => 'css/wikiEditor.preview.css', 'version' => 1 ),
2828 array( 'src' => 'css/wikiEditor.toc.css', 'version' => 28 ),
2929 array( 'src' => 'css/wikiEditor.toolbar.css', 'version' => 10 ),
3030 array( 'src' => 'css/vector/jquery-ui-1.7.2.css', 'version' => '1.7.2y' ),
3131 ),
3232 'combined' => array(
33 - array( 'src' => 'css/combined.css', 'version' => 58 ),
 33+ array( 'src' => 'css/combined.css', 'version' => 60 ),
3434 array( 'src' => 'css/vector/jquery-ui-1.7.2.css', 'version' => '1.7.2y' ),
3535 ),
3636 'minified' => array(
37 - array( 'src' => 'css/combined.min.css', 'version' => 58 ),
 37+ array( 'src' => 'css/combined.min.css', 'version' => 60 ),
3838 array( 'src' => 'css/vector/jquery-ui-1.7.2.css', 'version' => '1.7.2y' ),
3939 ),
4040 )
@@ -72,20 +72,20 @@
7373 array( 'src' => 'js/plugins/jquery.namespaceSelect.js', 'version' => 1 ),
7474 array( 'src' => 'js/plugins/jquery.suggestions.js', 'version' => 7 ),
7575 array( 'src' => 'js/plugins/jquery.textSelection.js', 'version' => 26 ),
76 - array( 'src' => 'js/plugins/jquery.wikiEditor.js', 'version' => 77 ),
77 - array( 'src' => 'js/plugins/jquery.wikiEditor.highlight.js', 'version' => 25 ),
78 - array( 'src' => 'js/plugins/jquery.wikiEditor.toolbar.js', 'version' => 45 ),
 76+ array( 'src' => 'js/plugins/jquery.wikiEditor.js', 'version' => 94 ),
 77+ array( 'src' => 'js/plugins/jquery.wikiEditor.highlight.js', 'version' => 29 ),
 78+ array( 'src' => 'js/plugins/jquery.wikiEditor.toolbar.js', 'version' => 46 ),
7979 array( 'src' => 'js/plugins/jquery.wikiEditor.dialogs.js', 'version' => 11 ),
80 - array( 'src' => 'js/plugins/jquery.wikiEditor.toc.js', 'version' => 74 ),
 80+ array( 'src' => 'js/plugins/jquery.wikiEditor.toc.js', 'version' => 78 ),
8181 array( 'src' => 'js/plugins/jquery.wikiEditor.preview.js', 'version' => 10 ),
82 - array( 'src' => 'js/plugins/jquery.wikiEditor.templateEditor.js', 'version' => 16 ),
 82+ array( 'src' => 'js/plugins/jquery.wikiEditor.templateEditor.js', 'version' => 17 ),
8383 array( 'src' => 'js/plugins/jquery.wikiEditor.publish.js', 'version' => 2 ),
8484 ),
8585 'combined' => array(
86 - array( 'src' => 'js/plugins.combined.js', 'version' => 189 ),
 86+ array( 'src' => 'js/plugins.combined.js', 'version' => 211 ),
8787 ),
8888 'minified' => array(
89 - array( 'src' => 'js/plugins.combined.min.js', 'version' => 189 ),
 89+ array( 'src' => 'js/plugins.combined.min.js', 'version' => 211 ),
9090 ),
9191 ),
9292 );

Status & tagging log