Index: trunk/extensions/UsabilityInitiative/combine.sh |
— | — | @@ -3,8 +3,10 @@ |
4 | 4 | rm js/plugins.combined.* |
5 | 5 | rm css/combined.* |
6 | 6 | echo "Merging raw scripts and styles" |
7 | | -cat js/js2/*.js > js/js2.combined.js |
8 | | -cat js/plugins/*.js > js/plugins.combined.js |
| 7 | +# Explicitly including scripts is important, because loading order is important |
| 8 | +cat js/js2/jquery-1.3.2.js js/js2/jquery-ui-1.7.2.js js/js2/js2.js > js/js2.combined.js |
| 9 | +cat js/plugins/jquery.async.js js/plugins/jquery.browser.js js/plugins/jquery.cookie.js js/plugins/jquery.suggestions.js js/plugins/jquery.textSelection.js js/plugins/jquery.wikiEditor.js js/plugins/jquery.wikiEditor.dialogs.js js/plugins/jquery.wikiEditor.toolbar.js js/plugins/jquery.wikiEditor.toc.js > js/plugins.combined.js |
| 10 | +# Styles can be loaded in any order |
9 | 11 | cat css/*.css > css/combined.css |
10 | 12 | # For more info on JSMin, see: http://www.crockford.com/javascript/jsmin.html |
11 | 13 | echo "Minifying merged scripts and styles" |
Index: trunk/extensions/UsabilityInitiative/js/plugins.combined.js |
— | — | @@ -1010,82 +1010,6 @@ |
1011 | 1011 | } |
1012 | 1012 | |
1013 | 1013 | } ); } )( jQuery );/** |
1014 | | - * Extend the RegExp object with an escaping function |
1015 | | - * From http://simonwillison.net/2006/Jan/20/escape/ |
1016 | | - */ |
1017 | | -RegExp.escape = function( s ) { return s.replace(/([.*+?^${}()|\/\\[\]])/g, '\\$1'); }; |
1018 | | - |
1019 | | -/** |
1020 | | - * Dialog Module for wikiEditor |
1021 | | - */ |
1022 | | -( function( $ ) { $.wikiEditor.modules.dialogs = { |
1023 | | - |
1024 | | -/** |
1025 | | - * API accessible functions |
1026 | | - */ |
1027 | | -api: { |
1028 | | - addDialog: function( context, data ) { |
1029 | | - $.wikiEditor.modules.dialogs.fn.create( context, { 'modules': data } ) |
1030 | | - }, |
1031 | | - openDialog: function( context, data ) { |
1032 | | - if ( data.dialog in $.wikiEditor.modules.dialogs.modules ) { |
1033 | | - $( '#' + $.wikiEditor.modules.dialogs.modules[data.dialog].id ).dialog( 'open' ); |
1034 | | - } |
1035 | | - }, |
1036 | | - closeDialog: function( context, data ) { |
1037 | | - if ( data.dialog in $.wikiEditor.modules.dialogs.modules ) { |
1038 | | - $( '#' + $.wikiEditor.modules.dialogs.modules[data.dialog].id ).dialog( 'close' ); |
1039 | | - } |
1040 | | - } |
1041 | | -}, |
1042 | | -/** |
1043 | | - * Internally used functions |
1044 | | - */ |
1045 | | -fn: { |
1046 | | - /** |
1047 | | - * Creates a dialog module within a wikiEditor |
1048 | | - * |
1049 | | - * @param {Object} context Context object of editor to create module in |
1050 | | - * @param {Object} config Configuration object to create module from |
1051 | | - */ |
1052 | | - create: function( context, config ) { |
1053 | | - // Add modules |
1054 | | - for ( module in config ) { |
1055 | | - $.wikiEditor.modules.dialogs.modules[module] = config[module]; |
1056 | | - } |
1057 | | - // Build out modules immediately |
1058 | | - for ( module in $.wikiEditor.modules.dialogs.modules ) { |
1059 | | - var module = $.wikiEditor.modules.dialogs.modules[module]; |
1060 | | - // Only create the dialog if it doesn't exist yet |
1061 | | - if ( $( '#' + module.id ).size() == 0 ) { |
1062 | | - var configuration = module.dialog; |
1063 | | - // Add some stuff to configuration |
1064 | | - configuration.bgiframe = true; |
1065 | | - configuration.autoOpen = false; |
1066 | | - configuration.modal = true; |
1067 | | - configuration.title = $.wikiEditor.autoMsg( module, 'title' ); |
1068 | | - // Transform messages in keys |
1069 | | - // Stupid JS won't let us do stuff like |
1070 | | - // foo = { gM ('bar'): baz } |
1071 | | - for ( msg in configuration.buttons ) { |
1072 | | - configuration.buttons[gM( msg )] = configuration.buttons[msg]; |
1073 | | - delete configuration.buttons[msg]; |
1074 | | - } |
1075 | | - // Create the dialog <div> |
1076 | | - $( '<div /> ' ) |
1077 | | - .attr( 'id', module.id ) |
1078 | | - .html( module.html ) |
1079 | | - .data( 'context', context ) |
1080 | | - .appendTo( $( 'body' ) ) |
1081 | | - .each( module.init ) |
1082 | | - .dialog( configuration ); |
1083 | | - } |
1084 | | - } |
1085 | | - } |
1086 | | -}, |
1087 | | -'modules': {} |
1088 | | - |
1089 | | -}; } ) ( jQuery );/** |
1090 | 1014 | * This plugin provides a way to build a user interface around a textarea. You |
1091 | 1015 | * can build the UI from a confguration.. |
1092 | 1016 | * $j( 'div#edittoolbar' ).wikiEditor( |
— | — | @@ -1246,226 +1170,80 @@ |
1247 | 1171 | return $(this).data( 'context', context ); |
1248 | 1172 | |
1249 | 1173 | };})(jQuery);/** |
1250 | | - * TOC Module for wikiEditor |
| 1174 | + * Extend the RegExp object with an escaping function |
| 1175 | + * From http://simonwillison.net/2006/Jan/20/escape/ |
1251 | 1176 | */ |
1252 | | -( function( $ ) { $.wikiEditor.modules.toc = { |
| 1177 | +RegExp.escape = function( s ) { return s.replace(/([.*+?^${}()|\/\\[\]])/g, '\\$1'); }; |
1253 | 1178 | |
1254 | 1179 | /** |
| 1180 | + * Dialog Module for wikiEditor |
| 1181 | + */ |
| 1182 | +( function( $ ) { $.wikiEditor.modules.dialogs = { |
| 1183 | + |
| 1184 | +/** |
1255 | 1185 | * API accessible functions |
1256 | 1186 | */ |
1257 | 1187 | api: { |
1258 | | - // |
| 1188 | + addDialog: function( context, data ) { |
| 1189 | + $.wikiEditor.modules.dialogs.fn.create( context, { 'modules': data } ) |
| 1190 | + }, |
| 1191 | + openDialog: function( context, data ) { |
| 1192 | + if ( data.dialog in $.wikiEditor.modules.dialogs.modules ) { |
| 1193 | + $( '#' + $.wikiEditor.modules.dialogs.modules[data.dialog].id ).dialog( 'open' ); |
| 1194 | + } |
| 1195 | + }, |
| 1196 | + closeDialog: function( context, data ) { |
| 1197 | + if ( data.dialog in $.wikiEditor.modules.dialogs.modules ) { |
| 1198 | + $( '#' + $.wikiEditor.modules.dialogs.modules[data.dialog].id ).dialog( 'close' ); |
| 1199 | + } |
| 1200 | + } |
1259 | 1201 | }, |
1260 | 1202 | /** |
1261 | 1203 | * Internally used functions |
1262 | 1204 | */ |
1263 | 1205 | fn: { |
1264 | 1206 | /** |
1265 | | - * Creates a table of contents module within a wikiEditor |
| 1207 | + * Creates a dialog module within a wikiEditor |
1266 | 1208 | * |
1267 | 1209 | * @param {Object} context Context object of editor to create module in |
1268 | 1210 | * @param {Object} config Configuration object to create module from |
1269 | 1211 | */ |
1270 | 1212 | create: function( context, config ) { |
1271 | | - if ( '$toc' in context.modules ) { |
1272 | | - return; |
| 1213 | + // Add modules |
| 1214 | + for ( module in config ) { |
| 1215 | + $.wikiEditor.modules.dialogs.modules[module] = config[module]; |
1273 | 1216 | } |
1274 | | - context.modules.$toc = $( '<div></div>' ) |
1275 | | - .addClass( 'wikiEditor-ui-toc' ) |
1276 | | - .attr( 'id', 'wikiEditor-ui-toc' ); |
1277 | | - $.wikiEditor.modules.toc.fn.build( context, config ); |
1278 | | - context.$ui.find( '.wikiEditor-ui-bottom' ) |
1279 | | - .append( context.modules.$toc ); |
1280 | | - context.modules.$toc.height( |
1281 | | - context.$ui.find( '.wikiEditor-ui-bottom' ).height() |
1282 | | - ); |
1283 | | - // Make some css modifications to make room for the toc on the right... |
1284 | | - // Perhaps this could be configurable? |
1285 | | - context.modules.$toc |
1286 | | - .css( 'width', '12em' ) |
1287 | | - .css( 'marginTop', -( context.$ui.find( '.wikiEditor-ui-bottom' ).height() ) ); |
1288 | | - context.$ui.find( '.wikiEditor-ui-text' ) |
1289 | | - .css( ( $( 'body.rtl' ).size() ? 'marginLeft' : 'marginRight' ), '12em' ); |
1290 | | - // Add the TOC to the document |
1291 | | - $.wikiEditor.modules.toc.fn.build( context ); |
1292 | | - $.wikiEditor.modules.toc.fn.update( context ); |
1293 | | - context.$textarea |
1294 | | - .bind( 'keyup encapsulateSelection', |
1295 | | - function( event ) { |
1296 | | - var context = $(this).data( 'context' ); |
1297 | | - $(this).eachAsync( { |
1298 | | - bulk: 0, |
1299 | | - loop: function() { |
1300 | | - $.wikiEditor.modules.toc.fn.build( context ); |
1301 | | - $.wikiEditor.modules.toc.fn.update( context ); |
1302 | | - } |
1303 | | - } ); |
| 1217 | + // Build out modules immediately |
| 1218 | + for ( module in $.wikiEditor.modules.dialogs.modules ) { |
| 1219 | + var module = $.wikiEditor.modules.dialogs.modules[module]; |
| 1220 | + // Only create the dialog if it doesn't exist yet |
| 1221 | + if ( $( '#' + module.id ).size() == 0 ) { |
| 1222 | + var configuration = module.dialog; |
| 1223 | + // Add some stuff to configuration |
| 1224 | + configuration.bgiframe = true; |
| 1225 | + configuration.autoOpen = false; |
| 1226 | + configuration.modal = true; |
| 1227 | + configuration.title = $.wikiEditor.autoMsg( module, 'title' ); |
| 1228 | + // Transform messages in keys |
| 1229 | + // Stupid JS won't let us do stuff like |
| 1230 | + // foo = { gM ('bar'): baz } |
| 1231 | + for ( msg in configuration.buttons ) { |
| 1232 | + configuration.buttons[gM( msg )] = configuration.buttons[msg]; |
| 1233 | + delete configuration.buttons[msg]; |
1304 | 1234 | } |
1305 | | - ) |
1306 | | - .bind( 'mouseup scrollToPosition', |
1307 | | - function( event ) { |
1308 | | - var context = $(this).data( 'context' ); |
1309 | | - $(this).eachAsync( { |
1310 | | - bulk: 0, |
1311 | | - loop: function() { |
1312 | | - $.wikiEditor.modules.toc.fn.update( context ); |
1313 | | - } |
1314 | | - } ); |
1315 | | - } |
1316 | | - ); |
1317 | | - }, |
1318 | | - /** |
1319 | | - * Highlight the section the cursor is currently within |
1320 | | - * |
1321 | | - * @param {Object} context |
1322 | | - */ |
1323 | | - update: function( context ) { |
1324 | | - context.modules.$toc.find( 'a' ).removeClass( 'currentSelection' ); |
1325 | | - var position = context.$textarea.getCaretPosition(); |
1326 | | - var section = 0; |
1327 | | - if ( context.data.outline.length > 0 ) { |
1328 | | - // If the caret is before the first heading, you must be in section |
1329 | | - // 0, and there is no need to look any farther - otherwise check |
1330 | | - // that the caret is before each section, and when it's not, we now |
1331 | | - // know what section it is in |
1332 | | - if ( !( position < context.data.outline[0].position - 1 ) ) { |
1333 | | - while ( |
1334 | | - section < context.data.outline.length && context.data.outline[section].position - 1 < position |
1335 | | - ) { |
1336 | | - section++; |
1337 | | - } |
1338 | | - section = Math.max( 0, section ); |
| 1235 | + // Create the dialog <div> |
| 1236 | + $( '<div /> ' ) |
| 1237 | + .attr( 'id', module.id ) |
| 1238 | + .html( module.html ) |
| 1239 | + .data( 'context', context ) |
| 1240 | + .appendTo( $( 'body' ) ) |
| 1241 | + .each( module.init ) |
| 1242 | + .dialog( configuration ); |
1339 | 1243 | } |
1340 | | - context.modules.$toc.find( 'a.section-' + section ).addClass( 'currentSelection' ); |
1341 | 1244 | } |
1342 | | - }, |
1343 | | - /** |
1344 | | - * Builds table of contents |
1345 | | - * |
1346 | | - * @param {Object} context |
1347 | | - */ |
1348 | | - build: function( context ) { |
1349 | | - /** |
1350 | | - * Builds a structured outline from flat outline |
1351 | | - * |
1352 | | - * @param {Object} outline Array of objects with level fields |
1353 | | - */ |
1354 | | - function buildStructure( outline, offset, level ) { |
1355 | | - if ( offset == undefined ) offset = 0; |
1356 | | - if ( level == undefined ) level = 1; |
1357 | | - var sections = []; |
1358 | | - for ( var i = offset; i < outline.length; i++ ) { |
1359 | | - if ( outline[i].nLevel == level ) { |
1360 | | - var sub = buildStructure( outline, i + 1, level + 1 ); |
1361 | | - if ( sub.length ) { |
1362 | | - outline[i].sections = sub; |
1363 | | - } |
1364 | | - sections[sections.length] = outline[i]; |
1365 | | - } else if ( outline[i].nLevel < level ) { |
1366 | | - break; |
1367 | | - } |
1368 | | - } |
1369 | | - return sections; |
1370 | | - } |
1371 | | - /** |
1372 | | - * Bulds unordered list HTML object from structured outline |
1373 | | - * |
1374 | | - * @param {Object} structure Structured outline |
1375 | | - */ |
1376 | | - function buildList( structure ) { |
1377 | | - var list = $( '<ul></ul>' ); |
1378 | | - for ( i in structure ) { |
1379 | | - var item = $( '<li></li>' ) |
1380 | | - .append( |
1381 | | - $( '<a></a>' ) |
1382 | | - .attr( 'href', '#' ) |
1383 | | - .addClass( 'section-' + structure[i].index ) |
1384 | | - .data( 'textbox', context.$textarea ) |
1385 | | - .data( 'position', structure[i].position ) |
1386 | | - .click( function( event ) { |
1387 | | - $(this).data( 'textbox' ).scrollToCaretPosition( $(this).data( 'position' ) ); |
1388 | | - event.preventDefault(); |
1389 | | - } ) |
1390 | | - .text( structure[i].text ) |
1391 | | - ); |
1392 | | - if ( structure[i].sections !== undefined ) { |
1393 | | - item.append( buildList( structure[i].sections ) ); |
1394 | | - } |
1395 | | - list.append( item ); |
1396 | | - } |
1397 | | - return list; |
1398 | | - } |
1399 | | - // Build outline from wikitext |
1400 | | - var outline = []; |
1401 | | - var wikitext = '\n' + context.$textarea.val() + '\n'; |
1402 | | - var headings = wikitext.match( /\n={1,5}.*={1,5}(?=\n)/g ); |
1403 | | - var offset = 0; |
1404 | | - headings = $.makeArray( headings ); |
1405 | | - for ( var h = 0; h < headings.length; h++ ) { |
1406 | | - text = headings[h]; |
1407 | | - // Get position of first occurence |
1408 | | - var position = wikitext.indexOf( text, offset ); |
1409 | | - // Update offset to avoid stumbling on duplicate headings |
1410 | | - if ( position > offset ) { |
1411 | | - offset = position; |
1412 | | - } else if ( position == -1 ) { |
1413 | | - // Not sure this is possible, or what should happen |
1414 | | - continue; |
1415 | | - } |
1416 | | - // Trim off whitespace |
1417 | | - text = $.trim( text ); |
1418 | | - // Detect the starting and ending heading levels |
1419 | | - var startLevel = 0; |
1420 | | - for ( var c = 0; c < text.length; c++ ) { |
1421 | | - if ( text.charAt( c ) == '=' ) { |
1422 | | - startLevel++; |
1423 | | - } else { |
1424 | | - break; |
1425 | | - } |
1426 | | - } |
1427 | | - var endLevel = 0; |
1428 | | - for ( var c = text.length - 1; c >= 0; c-- ) { |
1429 | | - if ( text.charAt( c ) == '=' ) { |
1430 | | - endLevel++; |
1431 | | - } else { |
1432 | | - break; |
1433 | | - } |
1434 | | - } |
1435 | | - // Use the lowest number of =s as the actual level |
1436 | | - var level = Math.min( startLevel, endLevel ); |
1437 | | - text = $.trim( text.substr( level, text.length - ( level * 2 ) ) ); |
1438 | | - // Add the heading data to the outline |
1439 | | - outline[h] = { 'text': text, 'position': position, 'level': level, 'index': h + 1 }; |
1440 | | - } |
1441 | | - // Normalize heading levels for list creation |
1442 | | - // This is based on Linker::generateTOC() so, it should behave like the |
1443 | | - // TOC on rendered articles does - which is considdered to be correct |
1444 | | - // at this point in time. |
1445 | | - var lastLevel = 0; |
1446 | | - var nLevel = 0; |
1447 | | - for ( var i = 0; i < outline.length; i++ ) { |
1448 | | - if ( outline[i].level > lastLevel ) { |
1449 | | - nLevel++; |
1450 | | - } |
1451 | | - else if ( outline[i].level < nLevel ) { |
1452 | | - nLevel -= Math.max( 1, lastLevel - outline[i].level ); |
1453 | | - } |
1454 | | - if ( nLevel <= 0 ) { |
1455 | | - nLevel = 1; |
1456 | | - } |
1457 | | - outline[i].nLevel = nLevel; |
1458 | | - lastLevel = outline[i].level; |
1459 | | - } |
1460 | | - // Recursively build the structure and add special item for |
1461 | | - // section 0, if needed |
1462 | | - var structure = buildStructure( outline ); |
1463 | | - if ( $( 'input[name=wpSection]' ).val() == '' ) |
1464 | | - structure.unshift( { 'text': wgPageName.replace(/_/g, ' '), 'level': 1, 'index': 0, 'position': 0 } ); |
1465 | | - context.modules.$toc.html( buildList( structure ) ); |
1466 | | - // Cache the outline for later use |
1467 | | - context.data.outline = outline; |
1468 | 1245 | } |
1469 | | -} |
| 1246 | +}, |
| 1247 | +'modules': {} |
1470 | 1248 | |
1471 | 1249 | }; } ) ( jQuery );/** |
1472 | 1250 | * Toolbar module for wikiEditor |
— | — | @@ -1925,6 +1703,12 @@ |
1926 | 1704 | $section.show(); |
1927 | 1705 | $(this).addClass( 'current' ); |
1928 | 1706 | } |
| 1707 | + |
| 1708 | + //click tracking |
| 1709 | + if($.trackAction != undefined){ |
| 1710 | + $.trackAction($section.attr('rel') + '.' + ( show ? 'show': 'hide' ) ); |
| 1711 | + } |
| 1712 | + |
1929 | 1713 | $.cookie( |
1930 | 1714 | 'wikiEditor-' + $(this).data( 'context' ).instance + '-toolbar-section', |
1931 | 1715 | show ? $section.attr( 'rel' ) : null |
— | — | @@ -2022,3 +1806,226 @@ |
2023 | 1807 | } |
2024 | 1808 | |
2025 | 1809 | }; } )( jQuery ); |
| 1810 | +/** |
| 1811 | + * TOC Module for wikiEditor |
| 1812 | + */ |
| 1813 | +( function( $ ) { $.wikiEditor.modules.toc = { |
| 1814 | + |
| 1815 | +/** |
| 1816 | + * API accessible functions |
| 1817 | + */ |
| 1818 | +api: { |
| 1819 | + // |
| 1820 | +}, |
| 1821 | +/** |
| 1822 | + * Internally used functions |
| 1823 | + */ |
| 1824 | +fn: { |
| 1825 | + /** |
| 1826 | + * Creates a table of contents module within a wikiEditor |
| 1827 | + * |
| 1828 | + * @param {Object} context Context object of editor to create module in |
| 1829 | + * @param {Object} config Configuration object to create module from |
| 1830 | + */ |
| 1831 | + create: function( context, config ) { |
| 1832 | + if ( '$toc' in context.modules ) { |
| 1833 | + return; |
| 1834 | + } |
| 1835 | + context.modules.$toc = $( '<div></div>' ) |
| 1836 | + .addClass( 'wikiEditor-ui-toc' ) |
| 1837 | + .attr( 'id', 'wikiEditor-ui-toc' ); |
| 1838 | + $.wikiEditor.modules.toc.fn.build( context, config ); |
| 1839 | + context.$ui.find( '.wikiEditor-ui-bottom' ) |
| 1840 | + .append( context.modules.$toc ); |
| 1841 | + context.modules.$toc.height( |
| 1842 | + context.$ui.find( '.wikiEditor-ui-bottom' ).height() |
| 1843 | + ); |
| 1844 | + // Make some css modifications to make room for the toc on the right... |
| 1845 | + // Perhaps this could be configurable? |
| 1846 | + context.modules.$toc |
| 1847 | + .css( 'width', '12em' ) |
| 1848 | + .css( 'marginTop', -( context.$ui.find( '.wikiEditor-ui-bottom' ).height() ) ); |
| 1849 | + context.$ui.find( '.wikiEditor-ui-text' ) |
| 1850 | + .css( ( $( 'body.rtl' ).size() ? 'marginLeft' : 'marginRight' ), '12em' ); |
| 1851 | + // Add the TOC to the document |
| 1852 | + $.wikiEditor.modules.toc.fn.build( context ); |
| 1853 | + $.wikiEditor.modules.toc.fn.update( context ); |
| 1854 | + context.$textarea |
| 1855 | + .bind( 'keyup encapsulateSelection', |
| 1856 | + function( event ) { |
| 1857 | + var context = $(this).data( 'context' ); |
| 1858 | + $(this).eachAsync( { |
| 1859 | + bulk: 0, |
| 1860 | + loop: function() { |
| 1861 | + $.wikiEditor.modules.toc.fn.build( context ); |
| 1862 | + $.wikiEditor.modules.toc.fn.update( context ); |
| 1863 | + } |
| 1864 | + } ); |
| 1865 | + } |
| 1866 | + ) |
| 1867 | + .bind( 'mouseup scrollToPosition', |
| 1868 | + function( event ) { |
| 1869 | + var context = $(this).data( 'context' ); |
| 1870 | + $(this).eachAsync( { |
| 1871 | + bulk: 0, |
| 1872 | + loop: function() { |
| 1873 | + $.wikiEditor.modules.toc.fn.update( context ); |
| 1874 | + } |
| 1875 | + } ); |
| 1876 | + } |
| 1877 | + ); |
| 1878 | + }, |
| 1879 | + /** |
| 1880 | + * Highlight the section the cursor is currently within |
| 1881 | + * |
| 1882 | + * @param {Object} context |
| 1883 | + */ |
| 1884 | + update: function( context ) { |
| 1885 | + context.modules.$toc.find( 'a' ).removeClass( 'currentSelection' ); |
| 1886 | + var position = context.$textarea.getCaretPosition(); |
| 1887 | + var section = 0; |
| 1888 | + if ( context.data.outline.length > 0 ) { |
| 1889 | + // If the caret is before the first heading, you must be in section |
| 1890 | + // 0, and there is no need to look any farther - otherwise check |
| 1891 | + // that the caret is before each section, and when it's not, we now |
| 1892 | + // know what section it is in |
| 1893 | + if ( !( position < context.data.outline[0].position - 1 ) ) { |
| 1894 | + while ( |
| 1895 | + section < context.data.outline.length && context.data.outline[section].position - 1 < position |
| 1896 | + ) { |
| 1897 | + section++; |
| 1898 | + } |
| 1899 | + section = Math.max( 0, section ); |
| 1900 | + } |
| 1901 | + context.modules.$toc.find( 'a.section-' + section ).addClass( 'currentSelection' ); |
| 1902 | + } |
| 1903 | + }, |
| 1904 | + /** |
| 1905 | + * Builds table of contents |
| 1906 | + * |
| 1907 | + * @param {Object} context |
| 1908 | + */ |
| 1909 | + build: function( context ) { |
| 1910 | + /** |
| 1911 | + * Builds a structured outline from flat outline |
| 1912 | + * |
| 1913 | + * @param {Object} outline Array of objects with level fields |
| 1914 | + */ |
| 1915 | + function buildStructure( outline, offset, level ) { |
| 1916 | + if ( offset == undefined ) offset = 0; |
| 1917 | + if ( level == undefined ) level = 1; |
| 1918 | + var sections = []; |
| 1919 | + for ( var i = offset; i < outline.length; i++ ) { |
| 1920 | + if ( outline[i].nLevel == level ) { |
| 1921 | + var sub = buildStructure( outline, i + 1, level + 1 ); |
| 1922 | + if ( sub.length ) { |
| 1923 | + outline[i].sections = sub; |
| 1924 | + } |
| 1925 | + sections[sections.length] = outline[i]; |
| 1926 | + } else if ( outline[i].nLevel < level ) { |
| 1927 | + break; |
| 1928 | + } |
| 1929 | + } |
| 1930 | + return sections; |
| 1931 | + } |
| 1932 | + /** |
| 1933 | + * Bulds unordered list HTML object from structured outline |
| 1934 | + * |
| 1935 | + * @param {Object} structure Structured outline |
| 1936 | + */ |
| 1937 | + function buildList( structure ) { |
| 1938 | + var list = $( '<ul></ul>' ); |
| 1939 | + for ( i in structure ) { |
| 1940 | + var item = $( '<li></li>' ) |
| 1941 | + .append( |
| 1942 | + $( '<a></a>' ) |
| 1943 | + .attr( 'href', '#' ) |
| 1944 | + .addClass( 'section-' + structure[i].index ) |
| 1945 | + .data( 'textbox', context.$textarea ) |
| 1946 | + .data( 'position', structure[i].position ) |
| 1947 | + .click( function( event ) { |
| 1948 | + $(this).data( 'textbox' ).scrollToCaretPosition( $(this).data( 'position' ) ); |
| 1949 | + event.preventDefault(); |
| 1950 | + } ) |
| 1951 | + .text( structure[i].text ) |
| 1952 | + ); |
| 1953 | + if ( structure[i].sections !== undefined ) { |
| 1954 | + item.append( buildList( structure[i].sections ) ); |
| 1955 | + } |
| 1956 | + list.append( item ); |
| 1957 | + } |
| 1958 | + return list; |
| 1959 | + } |
| 1960 | + // Build outline from wikitext |
| 1961 | + var outline = []; |
| 1962 | + var wikitext = '\n' + context.$textarea.val() + '\n'; |
| 1963 | + var headings = wikitext.match( /\n={1,5}.*={1,5}(?=\n)/g ); |
| 1964 | + var offset = 0; |
| 1965 | + headings = $.makeArray( headings ); |
| 1966 | + for ( var h = 0; h < headings.length; h++ ) { |
| 1967 | + text = headings[h]; |
| 1968 | + // Get position of first occurence |
| 1969 | + var position = wikitext.indexOf( text, offset ); |
| 1970 | + // Update offset to avoid stumbling on duplicate headings |
| 1971 | + if ( position > offset ) { |
| 1972 | + offset = position; |
| 1973 | + } else if ( position == -1 ) { |
| 1974 | + // Not sure this is possible, or what should happen |
| 1975 | + continue; |
| 1976 | + } |
| 1977 | + // Trim off whitespace |
| 1978 | + text = $.trim( text ); |
| 1979 | + // Detect the starting and ending heading levels |
| 1980 | + var startLevel = 0; |
| 1981 | + for ( var c = 0; c < text.length; c++ ) { |
| 1982 | + if ( text.charAt( c ) == '=' ) { |
| 1983 | + startLevel++; |
| 1984 | + } else { |
| 1985 | + break; |
| 1986 | + } |
| 1987 | + } |
| 1988 | + var endLevel = 0; |
| 1989 | + for ( var c = text.length - 1; c >= 0; c-- ) { |
| 1990 | + if ( text.charAt( c ) == '=' ) { |
| 1991 | + endLevel++; |
| 1992 | + } else { |
| 1993 | + break; |
| 1994 | + } |
| 1995 | + } |
| 1996 | + // Use the lowest number of =s as the actual level |
| 1997 | + var level = Math.min( startLevel, endLevel ); |
| 1998 | + text = $.trim( text.substr( level, text.length - ( level * 2 ) ) ); |
| 1999 | + // Add the heading data to the outline |
| 2000 | + outline[h] = { 'text': text, 'position': position, 'level': level, 'index': h + 1 }; |
| 2001 | + } |
| 2002 | + // Normalize heading levels for list creation |
| 2003 | + // This is based on Linker::generateTOC() so, it should behave like the |
| 2004 | + // TOC on rendered articles does - which is considdered to be correct |
| 2005 | + // at this point in time. |
| 2006 | + var lastLevel = 0; |
| 2007 | + var nLevel = 0; |
| 2008 | + for ( var i = 0; i < outline.length; i++ ) { |
| 2009 | + if ( outline[i].level > lastLevel ) { |
| 2010 | + nLevel++; |
| 2011 | + } |
| 2012 | + else if ( outline[i].level < nLevel ) { |
| 2013 | + nLevel -= Math.max( 1, lastLevel - outline[i].level ); |
| 2014 | + } |
| 2015 | + if ( nLevel <= 0 ) { |
| 2016 | + nLevel = 1; |
| 2017 | + } |
| 2018 | + outline[i].nLevel = nLevel; |
| 2019 | + lastLevel = outline[i].level; |
| 2020 | + } |
| 2021 | + // Recursively build the structure and add special item for |
| 2022 | + // section 0, if needed |
| 2023 | + var structure = buildStructure( outline ); |
| 2024 | + if ( $( 'input[name=wpSection]' ).val() == '' ) |
| 2025 | + structure.unshift( { 'text': wgPageName.replace(/_/g, ' '), 'level': 1, 'index': 0, 'position': 0 } ); |
| 2026 | + context.modules.$toc.html( buildList( structure ) ); |
| 2027 | + // Cache the outline for later use |
| 2028 | + context.data.outline = outline; |
| 2029 | + } |
| 2030 | +} |
| 2031 | + |
| 2032 | +}; } ) ( jQuery ); |
\ No newline at end of file |
Index: trunk/extensions/UsabilityInitiative/js/plugins.combined.min.js |
— | — | @@ -107,34 +107,16 @@ |
108 | 108 | return($.os.name=='mac'?13:($.os.name=='linux'?15:16))*row;} |
109 | 109 | return this.each(function(){$(this).focus();if(this.selectionStart||this.selectionStart=='0'){this.selectionStart=pos;this.selectionEnd=pos;$(this).scrollTop(getCaretScrollPosition(this));}else if(document.selection&&document.selection.createRange){var range=document.selection.createRange();var oldPos=$(this).getCaretPosition();var goBack=false;if(oldPos==pos){pos++;goBack=true;} |
110 | 110 | range.moveToElementText(this);range.collapse();range.move('character',pos);range.select();this.scrollTop+=range.offsetTop;if(goBack){range.move('character',-1);range.select();}} |
111 | | -$(this).trigger('scrollToPosition');});}});})(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,{'modules':data})},openDialog:function(context,data){if(data.dialog in $.wikiEditor.modules.dialogs.modules){$('#'+$.wikiEditor.modules.dialogs.modules[data.dialog].id).dialog('open');}},closeDialog:function(context,data){if(data.dialog in $.wikiEditor.modules.dialogs.modules){$('#'+$.wikiEditor.modules.dialogs.modules[data.dialog].id).dialog('close');}}},fn:{create:function(context,config){for(module in config){$.wikiEditor.modules.dialogs.modules[module]=config[module];} |
112 | | -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');for(msg in configuration.buttons){configuration.buttons[gM(msg)]=configuration.buttons[msg];delete configuration.buttons[msg];} |
113 | | -$('<div /> ').attr('id',module.id).html(module.html).data('context',context).appendTo($('body')).each(module.init).dialog(configuration);}}}},'modules':{}};})(jQuery);(function($){$.wikiEditor={'modules':{},'instances':[],'supportedBrowsers':{'ltr':{'msie':7,'firefox':2,'opera':9,'safari':3,'chrome':1,'camino':1},'rtl':{'msie':8,'firefox':2,'opera':9,'safari':3,'chrome':1,'camino':1}},imgPath:wgScriptPath+'/extensions/UsabilityInitiative/images/wikiEditor/'};$.wikiEditor.isSupportKnown=function(){return(function(supportedBrowsers){return $.browser.name in supportedBrowsers;})($.wikiEditor.supportedBrowsers[$('body.rtl').size()?'rtl':'ltr']);};$.wikiEditor.isSupported=function(){return(function(supportedBrowsers){return $.browser.name in supportedBrowsers&&$.browser.versionNumber>=supportedBrowsers[$.browser.name];})($.wikiEditor.supportedBrowsers[$('body.rtl').size()?'rtl':'ltr']);};$.wikiEditor.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;}}} |
| 111 | +$(this).trigger('scrollToPosition');});}});})(jQuery);(function($){$.wikiEditor={'modules':{},'instances':[],'supportedBrowsers':{'ltr':{'msie':7,'firefox':2,'opera':9,'safari':3,'chrome':1,'camino':1},'rtl':{'msie':8,'firefox':2,'opera':9,'safari':3,'chrome':1,'camino':1}},imgPath:wgScriptPath+'/extensions/UsabilityInitiative/images/wikiEditor/'};$.wikiEditor.isSupportKnown=function(){return(function(supportedBrowsers){return $.browser.name in supportedBrowsers;})($.wikiEditor.supportedBrowsers[$('body.rtl').size()?'rtl':'ltr']);};$.wikiEditor.isSupported=function(){return(function(supportedBrowsers){return $.browser.name in supportedBrowsers&&$.browser.versionNumber>=supportedBrowsers[$.browser.name];})($.wikiEditor.supportedBrowsers[$('body.rtl').size()?'rtl':'ltr']);};$.wikiEditor.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;}}} |
114 | 112 | if(property in object){return object[property];}else if(property+'Msg'in object){return gM(object[property+'Msg']);}else{return'';}};$.fn.wikiEditor=function(){var context=$(this).data('context');if(typeof context!=='undefined'){arguments=$.makeArray(arguments);if(arguments.length>0){var call=arguments.shift();if(call in context.api){context.api[call](context,arguments[0]==undefined?{}:arguments[0]);} |
115 | 113 | return $(this).data('context',context);} |
116 | 114 | return $(this);} |
117 | 115 | var instance=$.wikiEditor.instances.length;context={'$textarea':$(this),'modules':{},'data':{},'instance':instance};$.wikiEditor.instances[instance]=$(this);$(this).wrap($('<div></div>').addClass('wikiEditor-ui').attr('id','wikiEditor-ui')).wrap($('<div></div>').addClass('wikiEditor-ui-bottom').attr('id','wikiEditor-ui-bottom')).wrap($('<div></div>').addClass('wikiEditor-ui-text').attr('id','wikiEditor-ui-text'));context.$ui=$(this).parent().parent().parent();context.$ui.after($('<div style="clear:both;"></div>'));context.$ui.prepend($('<div></div>').addClass('wikiEditor-ui-top').attr('id','wikiEditor-ui-top'));context.api={addModule:function(context,data){function callModuleApi(module,call,data){if(module in $.wikiEditor.modules&&'fn'in $.wikiEditor.modules[module]&&call in $.wikiEditor.modules[module].fn){$.wikiEditor.modules[module].fn[call](context,data);}} |
118 | 116 | if(typeof data=='string'){callModuleApi(data,'create',{});}else if(typeof data=='object'){for(module in data){if(typeof module=='string'){callModuleApi(module,'create',data[module]);}}}}};for(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];}}}} |
119 | 117 | if(arguments.length>0&&typeof arguments[0]=='object'){context.api.addModule(context,arguments[0]);} |
120 | | -context.$textarea.scrollToCaretPosition(0);return $(this).data('context',context);};})(jQuery);(function($){$.wikiEditor.modules.toc={api:{},fn:{create:function(context,config){if('$toc'in context.modules){return;} |
121 | | -context.modules.$toc=$('<div></div>').addClass('wikiEditor-ui-toc').attr('id','wikiEditor-ui-toc');$.wikiEditor.modules.toc.fn.build(context,config);context.$ui.find('.wikiEditor-ui-bottom').append(context.modules.$toc);context.modules.$toc.height(context.$ui.find('.wikiEditor-ui-bottom').height());context.modules.$toc.css('width','12em').css('marginTop',-(context.$ui.find('.wikiEditor-ui-bottom').height()));context.$ui.find('.wikiEditor-ui-text').css(($('body.rtl').size()?'marginLeft':'marginRight'),'12em');$.wikiEditor.modules.toc.fn.build(context);$.wikiEditor.modules.toc.fn.update(context);context.$textarea.bind('keyup encapsulateSelection',function(event){var context=$(this).data('context');$(this).eachAsync({bulk:0,loop:function(){$.wikiEditor.modules.toc.fn.build(context);$.wikiEditor.modules.toc.fn.update(context);}});}).bind('mouseup scrollToPosition',function(event){var context=$(this).data('context');$(this).eachAsync({bulk:0,loop:function(){$.wikiEditor.modules.toc.fn.update(context);}});});},update:function(context){context.modules.$toc.find('a').removeClass('currentSelection');var position=context.$textarea.getCaretPosition();var section=0;if(context.data.outline.length>0){if(!(position<context.data.outline[0].position-1)){while(section<context.data.outline.length&&context.data.outline[section].position-1<position){section++;} |
122 | | -section=Math.max(0,section);} |
123 | | -context.modules.$toc.find('a.section-'+section).addClass('currentSelection');}},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;} |
124 | | -sections[sections.length]=outline[i];}else if(outline[i].nLevel<level){break;}} |
125 | | -return sections;} |
126 | | -function buildList(structure){var list=$('<ul></ul>');for(i in structure){var item=$('<li></li>').append($('<a></a>').attr('href','#').addClass('section-'+structure[i].index).data('textbox',context.$textarea).data('position',structure[i].position).click(function(event){$(this).data('textbox').scrollToCaretPosition($(this).data('position'));event.preventDefault();}).text(structure[i].text));if(structure[i].sections!==undefined){item.append(buildList(structure[i].sections));} |
127 | | -list.append(item);} |
128 | | -return list;} |
129 | | -var outline=[];var wikitext='\n'+context.$textarea.val()+'\n';var headings=wikitext.match(/\n={1,5}.*={1,5}(?=\n)/g);var offset=0;headings=$.makeArray(headings);for(var h=0;h<headings.length;h++){text=headings[h];var position=wikitext.indexOf(text,offset);if(position>offset){offset=position;}else if(position==-1){continue;} |
130 | | -text=$.trim(text);var startLevel=0;for(var c=0;c<text.length;c++){if(text.charAt(c)=='='){startLevel++;}else{break;}} |
131 | | -var endLevel=0;for(var c=text.length-1;c>=0;c--){if(text.charAt(c)=='='){endLevel++;}else{break;}} |
132 | | -var level=Math.min(startLevel,endLevel);text=$.trim(text.substr(level,text.length-(level*2)));outline[h]={'text':text,'position':position,'level':level,'index':h+1};} |
133 | | -var lastLevel=0;var nLevel=0;for(var i=0;i<outline.length;i++){if(outline[i].level>lastLevel){nLevel++;} |
134 | | -else if(outline[i].level<nLevel){nLevel-=Math.max(1,lastLevel-outline[i].level);} |
135 | | -if(nLevel<=0){nLevel=1;} |
136 | | -outline[i].nLevel=nLevel;lastLevel=outline[i].level;} |
137 | | -var structure=buildStructure(outline);if($('input[name=wpSection]').val()=='') |
138 | | -structure.unshift({'text':wgPageName.replace(/_/g,' '),'level':1,'index':0,'position':0});context.modules.$toc.html(buildList(structure));context.data.outline=outline;}}};})(jQuery);(function($){$.wikiEditor.modules.toolbar={api:{addToToolbar:function(context,data){for(type in data){switch(type){case'sections':var $sections=context.modules.$toolbar.find('div.sections');var $tabs=context.modules.$toolbar.find('div.tabs');for(section in data[type]){if(section=='main'){context.modules.$toolbar.prepend($.wikiEditor.modules.toolbar.fn.buildSection(context,section,data[type][section]));continue;} |
| 118 | +context.$textarea.scrollToCaretPosition(0);return $(this).data('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,{'modules':data})},openDialog:function(context,data){if(data.dialog in $.wikiEditor.modules.dialogs.modules){$('#'+$.wikiEditor.modules.dialogs.modules[data.dialog].id).dialog('open');}},closeDialog:function(context,data){if(data.dialog in $.wikiEditor.modules.dialogs.modules){$('#'+$.wikiEditor.modules.dialogs.modules[data.dialog].id).dialog('close');}}},fn:{create:function(context,config){for(module in config){$.wikiEditor.modules.dialogs.modules[module]=config[module];} |
| 119 | +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');for(msg in configuration.buttons){configuration.buttons[gM(msg)]=configuration.buttons[msg];delete configuration.buttons[msg];} |
| 120 | +$('<div /> ').attr('id',module.id).html(module.html).data('context',context).appendTo($('body')).each(module.init).dialog(configuration);}}}},'modules':{}};})(jQuery);(function($){$.wikiEditor.modules.toolbar={api:{addToToolbar:function(context,data){for(type in data){switch(type){case'sections':var $sections=context.modules.$toolbar.find('div.sections');var $tabs=context.modules.$toolbar.find('div.tabs');for(section in data[type]){if(section=='main'){context.modules.$toolbar.prepend($.wikiEditor.modules.toolbar.fn.buildSection(context,section,data[type][section]));continue;} |
139 | 121 | $sections.append($.wikiEditor.modules.toolbar.fn.buildSection(context,section,data[type][section]));$tabs.append($.wikiEditor.modules.toolbar.fn.buildTab(context,section,data[type][section]));} |
140 | 122 | break;case'groups':if(!('section'in data)){continue;} |
141 | 123 | var $section=context.modules.$toolbar.find('div[rel='+data.section+'].section');for(group in data[type]){$section.append($.wikiEditor.modules.toolbar.fn.buildGroup(context,group,data[type][group]));} |
— | — | @@ -173,10 +155,29 @@ |
174 | 156 | $.wikiEditor.autoMsg(row[cell],['html','text'])+'</span></td>';} |
175 | 157 | html+='</tr>';return html;},buildCharacter:function(character,actions){if(typeof character=='string'){character={'label':character,'action':{'type':'encapsulate','options':{'pre':character}}};}else if(0 in character&&1 in character){character={'label':character[0],'action':{'type':'encapsulate','options':{'pre':character[1]}}};} |
176 | 158 | if('action'in character&&'label'in character){actions[character.label]=character.action;return'<a rel="'+character.label+'" href="#">'+character.label+'</a>';}},buildTab:function(context,id,section){var selected=$.cookie('wikiEditor-'+context.instance+'-toolbar-section');return $('<span />').attr({'class':'tab tab-'+id,'rel':id}).append($('<a />').addClass(selected==id?'current':null).attr('href','#').text($.wikiEditor.autoMsg(section,'label')).data('context',context).click(function(){var $section=$(this).data('context').$ui.find('.section-'+$(this).parent().attr('rel'));$(this).blur();var show=$section.css('display')=='none';$section.parent().children().hide();$(this).parent().parent().find('a').removeClass('current');if(show){$section.show();$(this).addClass('current');} |
| 159 | +if($.trackAction!=undefined){$.trackAction($section.attr('rel')+'.'+(show?'show':'hide'));} |
177 | 160 | $.cookie('wikiEditor-'+$(this).data('context').instance+'-toolbar-section',show?$section.attr('rel'):null);return false;}));},buildSection:function(context,id,section){var selected=$.cookie('wikiEditor-'+context.instance+'-toolbar-section');var $section;switch(section.type){case'toolbar':var $section=$('<div />').attr({'class':'toolbar section section-'+id,'rel':id});if('groups'in section){for(group in section.groups){$section.append($.wikiEditor.modules.toolbar.fn.buildGroup(context,group,section.groups[group]));}} |
178 | 161 | break;case'booklet':var $pages=$('<div />').addClass('pages');var $index=$('<div />').addClass('index');if('pages'in section){for(page in section.pages){$pages.append($.wikiEditor.modules.toolbar.fn.buildPage(context,page,section.pages[page]));$index.append($.wikiEditor.modules.toolbar.fn.buildBookmark(context,page,section.pages[page]));}} |
179 | 162 | $section=$('<div />').attr({'class':'booklet section section-'+id,'rel':id}).append($index).append($pages);$.wikiEditor.modules.toolbar.fn.updateBookletSelection(context,page,$pages,$index);break;} |
180 | 163 | if($section!==null&&id!=='main'){$section.css('display',selected==id?'block':'none');} |
181 | 164 | return $section;},updateBookletSelection:function(context,id,$pages,$index){var cookie='wikiEditor-'+context.instance+'-booklet-'+id+'-page';var selected=$.cookie(cookie);var $selectedIndex=$index.find('*[rel='+selected+']');if($selectedIndex.size()==0){selected=$index.children().eq(0).attr('rel');$.cookie(cookie,selected);} |
182 | 165 | $pages.children().hide();$pages.find('*[rel='+selected+']').show();$index.children().removeClass('current');$selectedIndex.addClass('current');},build:function(context,config){var $tabs=$('<div />').addClass('tabs').appendTo(context.modules.$toolbar);var $sections=$('<div />').addClass('sections').appendTo(context.modules.$toolbar);context.modules.$toolbar.append($('<div />').css('clear','both'));var sectionQueue=[];for(section in config){if(section=='main'){context.modules.$toolbar.prepend($.wikiEditor.modules.toolbar.fn.buildSection(context,section,config[section]));}else{sectionQueue.push({'$sections':$sections,'context':context,'id':section,'config':config[section]});$tabs.append($.wikiEditor.modules.toolbar.fn.buildTab(context,section,config[section]));}} |
183 | | -$.eachAsync(sectionQueue,{'bulk':0,'end':function(){$('body').css('position','static');$('body').css('position','relative');},'loop':function(i,s){s.$sections.append($.wikiEditor.modules.toolbar.fn.buildSection(s.context,s.id,s.config));}});}}};})(jQuery); |
\ No newline at end of file |
| 166 | +$.eachAsync(sectionQueue,{'bulk':0,'end':function(){$('body').css('position','static');$('body').css('position','relative');},'loop':function(i,s){s.$sections.append($.wikiEditor.modules.toolbar.fn.buildSection(s.context,s.id,s.config));}});}}};})(jQuery);(function($){$.wikiEditor.modules.toc={api:{},fn:{create:function(context,config){if('$toc'in context.modules){return;} |
| 167 | +context.modules.$toc=$('<div></div>').addClass('wikiEditor-ui-toc').attr('id','wikiEditor-ui-toc');$.wikiEditor.modules.toc.fn.build(context,config);context.$ui.find('.wikiEditor-ui-bottom').append(context.modules.$toc);context.modules.$toc.height(context.$ui.find('.wikiEditor-ui-bottom').height());context.modules.$toc.css('width','12em').css('marginTop',-(context.$ui.find('.wikiEditor-ui-bottom').height()));context.$ui.find('.wikiEditor-ui-text').css(($('body.rtl').size()?'marginLeft':'marginRight'),'12em');$.wikiEditor.modules.toc.fn.build(context);$.wikiEditor.modules.toc.fn.update(context);context.$textarea.bind('keyup encapsulateSelection',function(event){var context=$(this).data('context');$(this).eachAsync({bulk:0,loop:function(){$.wikiEditor.modules.toc.fn.build(context);$.wikiEditor.modules.toc.fn.update(context);}});}).bind('mouseup scrollToPosition',function(event){var context=$(this).data('context');$(this).eachAsync({bulk:0,loop:function(){$.wikiEditor.modules.toc.fn.update(context);}});});},update:function(context){context.modules.$toc.find('a').removeClass('currentSelection');var position=context.$textarea.getCaretPosition();var section=0;if(context.data.outline.length>0){if(!(position<context.data.outline[0].position-1)){while(section<context.data.outline.length&&context.data.outline[section].position-1<position){section++;} |
| 168 | +section=Math.max(0,section);} |
| 169 | +context.modules.$toc.find('a.section-'+section).addClass('currentSelection');}},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;} |
| 170 | +sections[sections.length]=outline[i];}else if(outline[i].nLevel<level){break;}} |
| 171 | +return sections;} |
| 172 | +function buildList(structure){var list=$('<ul></ul>');for(i in structure){var item=$('<li></li>').append($('<a></a>').attr('href','#').addClass('section-'+structure[i].index).data('textbox',context.$textarea).data('position',structure[i].position).click(function(event){$(this).data('textbox').scrollToCaretPosition($(this).data('position'));event.preventDefault();}).text(structure[i].text));if(structure[i].sections!==undefined){item.append(buildList(structure[i].sections));} |
| 173 | +list.append(item);} |
| 174 | +return list;} |
| 175 | +var outline=[];var wikitext='\n'+context.$textarea.val()+'\n';var headings=wikitext.match(/\n={1,5}.*={1,5}(?=\n)/g);var offset=0;headings=$.makeArray(headings);for(var h=0;h<headings.length;h++){text=headings[h];var position=wikitext.indexOf(text,offset);if(position>offset){offset=position;}else if(position==-1){continue;} |
| 176 | +text=$.trim(text);var startLevel=0;for(var c=0;c<text.length;c++){if(text.charAt(c)=='='){startLevel++;}else{break;}} |
| 177 | +var endLevel=0;for(var c=text.length-1;c>=0;c--){if(text.charAt(c)=='='){endLevel++;}else{break;}} |
| 178 | +var level=Math.min(startLevel,endLevel);text=$.trim(text.substr(level,text.length-(level*2)));outline[h]={'text':text,'position':position,'level':level,'index':h+1};} |
| 179 | +var lastLevel=0;var nLevel=0;for(var i=0;i<outline.length;i++){if(outline[i].level>lastLevel){nLevel++;} |
| 180 | +else if(outline[i].level<nLevel){nLevel-=Math.max(1,lastLevel-outline[i].level);} |
| 181 | +if(nLevel<=0){nLevel=1;} |
| 182 | +outline[i].nLevel=nLevel;lastLevel=outline[i].level;} |
| 183 | +var structure=buildStructure(outline);if($('input[name=wpSection]').val()=='') |
| 184 | +structure.unshift({'text':wgPageName.replace(/_/g,' '),'level':1,'index':0,'position':0});context.modules.$toc.html(buildList(structure));context.data.outline=outline;}}};})(jQuery); |
\ No newline at end of file |