Index: trunk/extensions/WikiEditor/tests/wikiEditor.toolbar.js |
— | — | @@ -0,0 +1,246 @@ |
| 2 | +/** |
| 3 | + * Test set for the edit toolbar |
| 4 | + */ |
| 5 | +var textareaId = '#wpTextbox1'; |
| 6 | +var wikiEditorTests = { |
| 7 | + // Add emoticons section |
| 8 | + 'add_sections_toolbar': { |
| 9 | + 'call': 'addToToolbar', |
| 10 | + 'data': { |
| 11 | + 'sections': { |
| 12 | + 'emoticons': { |
| 13 | + 'type': 'toolbar', |
| 14 | + 'label': 'Emoticons' |
| 15 | + } |
| 16 | + } |
| 17 | + }, |
| 18 | + 'test': '*[rel=emoticons].section', |
| 19 | + 'pre': 0, |
| 20 | + 'post': 1 |
| 21 | + }, |
| 22 | + // Add faces group to emoticons section |
| 23 | + 'add_groups': { |
| 24 | + 'call': 'addToToolbar', |
| 25 | + 'data': { |
| 26 | + 'section': 'emoticons', |
| 27 | + 'groups': { |
| 28 | + 'faces': { |
| 29 | + 'label': 'Faces' |
| 30 | + } |
| 31 | + } |
| 32 | + }, |
| 33 | + 'test': '*[rel=emoticons].section *[rel=faces].group', |
| 34 | + 'pre': 0, |
| 35 | + 'post': 1 |
| 36 | + }, |
| 37 | + // Add smile tool to faces group of emoticons section |
| 38 | + 'add_tools': { |
| 39 | + 'call': 'addToToolbar', |
| 40 | + 'data': { |
| 41 | + 'section': 'emoticons', |
| 42 | + 'group': 'faces', |
| 43 | + 'tools': { |
| 44 | + 'smile': { |
| 45 | + label: 'Smile!', |
| 46 | + type: 'button', |
| 47 | + icon: 'http://upload.wikimedia.org/wikipedia/commons/thumb/a/a4/Gnome-face-smile.svg/22px-Gnome-face-smile.svg.png', |
| 48 | + action: { |
| 49 | + type: 'encapsulate', |
| 50 | + options: { |
| 51 | + pre: ":)" |
| 52 | + } |
| 53 | + } |
| 54 | + } |
| 55 | + } |
| 56 | + }, |
| 57 | + 'test': '*[rel=emoticons].section *[rel=faces].group *[rel=smile].tool', |
| 58 | + 'pre': 0, |
| 59 | + 'post': 1 |
| 60 | + }, |
| 61 | + // Add info section |
| 62 | + 'add_sections_booklet': { |
| 63 | + 'call': 'addToToolbar', |
| 64 | + 'data': { |
| 65 | + 'sections': { |
| 66 | + 'info': { |
| 67 | + 'type': 'booklet', |
| 68 | + 'label': 'Info' |
| 69 | + } |
| 70 | + } |
| 71 | + }, |
| 72 | + 'test': '*[rel=info].section', |
| 73 | + 'pre': 0, |
| 74 | + 'post': 1 |
| 75 | + }, |
| 76 | + // Add info section |
| 77 | + 'add_pages_table': { |
| 78 | + 'call': 'addToToolbar', |
| 79 | + 'data': { |
| 80 | + 'section': 'info', |
| 81 | + 'pages': { |
| 82 | + 'colors': { |
| 83 | + 'layout': 'table', |
| 84 | + 'label': 'Colors', |
| 85 | + 'headings': [ |
| 86 | + { text: 'Name' }, |
| 87 | + { text: 'Temperature' }, |
| 88 | + { text: 'Swatch' } |
| 89 | + ] |
| 90 | + } |
| 91 | + } |
| 92 | + }, |
| 93 | + 'test': '*[rel=info].section *[rel=colors].page', |
| 94 | + 'pre': 0, |
| 95 | + 'post': 1 |
| 96 | + }, |
| 97 | + // Add colors rows |
| 98 | + 'add_rows': { |
| 99 | + 'call': 'addToToolbar', |
| 100 | + 'data': { |
| 101 | + 'section': 'info', |
| 102 | + 'page': 'colors', |
| 103 | + 'rows': [ |
| 104 | + { |
| 105 | + 'name': { text: 'Red' }, |
| 106 | + 'temp': { text: 'Warm' }, |
| 107 | + 'swatch': { html: '<div style="width:10px;height:10px;background-color:red;">' } |
| 108 | + }, |
| 109 | + { |
| 110 | + 'name': { text: 'Blue' }, |
| 111 | + 'temp': { text: 'Cold' }, |
| 112 | + 'swatch': { html: '<div style="width:10px;height:10px;background-color:blue;">' } |
| 113 | + }, |
| 114 | + { |
| 115 | + 'name': { text: 'Silver' }, |
| 116 | + 'temp': { text: 'Neutral' }, |
| 117 | + 'swatch': { html: '<div style="width:10px;height:10px;background-color:silver;">' } |
| 118 | + } |
| 119 | + ] |
| 120 | + }, |
| 121 | + 'test': '*[rel=info].section *[rel=colors].page tr td', |
| 122 | + 'pre': 0, |
| 123 | + 'post': 9 |
| 124 | + }, |
| 125 | + // Add |
| 126 | + 'add_pages_characters': { |
| 127 | + 'call': 'addToToolbar', |
| 128 | + 'data': { |
| 129 | + 'section': 'info', |
| 130 | + 'pages': { |
| 131 | + 'emoticons': { |
| 132 | + 'layout': 'characters', |
| 133 | + 'label': 'Emoticons' |
| 134 | + }, |
| 135 | + 'removeme': { |
| 136 | + 'layout': 'characters', |
| 137 | + 'label': 'Remove Me!' |
| 138 | + } |
| 139 | + } |
| 140 | + }, |
| 141 | + 'test': '*[rel=info].section *[rel=emoticons].page', |
| 142 | + 'pre': 0, |
| 143 | + 'post': 1 |
| 144 | + }, |
| 145 | + // Add |
| 146 | + 'add_characters': { |
| 147 | + 'call': 'addToToolbar', |
| 148 | + 'data': { |
| 149 | + 'section': 'info', |
| 150 | + 'page': 'emoticons', |
| 151 | + 'characters': [ ':)', ':))', ':(', '<3', ';)' ] |
| 152 | + }, |
| 153 | + 'test': '*[rel=info].section *[rel=emoticons].page *[rel=":)"]', |
| 154 | + 'pre': 0, |
| 155 | + 'post': 1 |
| 156 | + }, |
| 157 | + // Remove page |
| 158 | + 'remove_page': { |
| 159 | + 'call': 'removeFromToolbar', |
| 160 | + 'data': { |
| 161 | + 'section': 'info', |
| 162 | + 'page': 'removeme' |
| 163 | + }, |
| 164 | + 'test': '*[rel=info].section *[rel=removeme].page', |
| 165 | + 'pre': 1, |
| 166 | + 'post': 0 |
| 167 | + }, |
| 168 | + // Remove :)) from emoticon characters |
| 169 | + 'remove_character': { |
| 170 | + 'call': 'removeFromToolbar', |
| 171 | + 'data': { |
| 172 | + 'section': 'info', |
| 173 | + 'page': 'emoticons', |
| 174 | + 'character': ':))' |
| 175 | + }, |
| 176 | + 'test': '*[rel=info].section *[rel=emoticons].page a[rel=":))"]', |
| 177 | + 'pre': 1, |
| 178 | + 'post': 0 |
| 179 | + }, |
| 180 | + // Remove row from colors table of info section |
| 181 | + 'remove_row': { |
| 182 | + 'call': 'removeFromToolbar', |
| 183 | + 'data': { |
| 184 | + 'section': 'info', |
| 185 | + 'page': 'colors', |
| 186 | + 'row': 0 |
| 187 | + }, |
| 188 | + 'test': '*[rel=info].section *[rel=colors].page tr td', |
| 189 | + 'pre': 9, |
| 190 | + 'post': 6 |
| 191 | + } |
| 192 | +}; |
| 193 | +$j(document).ready( function() { |
| 194 | + var button = $j( '<button>Run wikiEditor Tests!</button>' ) |
| 195 | + .css( { |
| 196 | + 'position': 'fixed', |
| 197 | + 'bottom': 0, |
| 198 | + 'right': 0, |
| 199 | + 'width': '100%', |
| 200 | + 'backgroundColor': '#333333', |
| 201 | + 'opacity': 0.75, |
| 202 | + 'color': '#DDDDDD', |
| 203 | + 'padding': '0.5em', |
| 204 | + 'border': 'none', |
| 205 | + 'display': 'none' |
| 206 | + } ) |
| 207 | + .click( function() { |
| 208 | + if ( $j(this).attr( 'enabled' ) == 'false' ) { |
| 209 | + $j(this).slideUp( 'fast' ); |
| 210 | + return false; |
| 211 | + } |
| 212 | + var messages = [ 'Running tests for wikiEditor API' ]; |
| 213 | + var $target = $j( textareaId ); |
| 214 | + var $ui = $target.data( 'wikiEditor-context' ).$ui; |
| 215 | + var passes = 0; |
| 216 | + var tests = 0; |
| 217 | + for ( test in wikiEditorTests ) { |
| 218 | + var pre = $ui.find( wikiEditorTests[test].test ).size() == |
| 219 | + wikiEditorTests[test].pre; |
| 220 | + messages.push ( test + '-pre: ' + ( pre ? 'PASS' : 'FAIL' ) ); |
| 221 | + $target.wikiEditor( |
| 222 | + wikiEditorTests[test].call, |
| 223 | + wikiEditorTests[test].data |
| 224 | + ); |
| 225 | + var post = $ui.find( wikiEditorTests[test].test ).size() == |
| 226 | + wikiEditorTests[test].post; |
| 227 | + messages.push ( test + '-post: ' + ( post ? 'PASS' : 'FAIL' ) ); |
| 228 | + if ( pre && post ) { |
| 229 | + passes++; |
| 230 | + } |
| 231 | + tests++; |
| 232 | + } |
| 233 | + if ( window.console !== undefined ) { |
| 234 | + for ( message in messages ) { |
| 235 | + console.log( messages[message] ); |
| 236 | + } |
| 237 | + } |
| 238 | + $j(this) |
| 239 | + .attr( 'title', messages.join( " | " ) ) |
| 240 | + .text( passes + ' / ' + tests + ' were successful' ) |
| 241 | + .css( 'backgroundColor', passes < tests ? 'red' : 'green' ) |
| 242 | + .attr( 'enabled', 'false' ) |
| 243 | + .blur(); |
| 244 | + } ) |
| 245 | + .appendTo( $j( 'body' ) ); |
| 246 | + setTimeout( function() { button.slideDown( 'fast' ) }, 2000 ); |
| 247 | +} ); |
Property changes on: trunk/extensions/WikiEditor/tests/wikiEditor.toolbar.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 248 | + native |
Index: trunk/extensions/WikiEditor/modules/wikiEditor.preview.css |
— | — | @@ -0,0 +1,23 @@ |
| 2 | +/* CSS for wikiEditor preview plugin */ |
| 3 | + |
| 4 | +.wikiEditor-preview-loading { |
| 5 | + padding: 1em; |
| 6 | + background-color: white; |
| 7 | +} |
| 8 | +.wikiEditor-preview-loading span { |
| 9 | + color: #666666; |
| 10 | +} |
| 11 | +.wikiEditor-preview-spinner { |
| 12 | + padding-right: 1em; |
| 13 | +} |
| 14 | +.wikiEditor-preview-contents { |
| 15 | + padding: 1em; |
| 16 | + background-color: white; |
| 17 | +} |
| 18 | +#wikiEditor-0-preview-dialog .wikiEditor-ui-loading { |
| 19 | + overflow: hidden; |
| 20 | + border: none; |
| 21 | +} |
| 22 | +.ui-dialog .ui-dialog-buttonpane { |
| 23 | + margin: 0 !important; |
| 24 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/WikiEditor/modules/wikiEditor.preview.css |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 25 | + native |
Index: trunk/extensions/WikiEditor/modules/Publish.js |
— | — | @@ -0,0 +1,12 @@ |
| 2 | +/* JavaScript for WikiEditor Publish module */ |
| 3 | + |
| 4 | +$j(document).ready( function() { |
| 5 | + // Check preferences for publish |
| 6 | + if ( !wgWikiEditorEnabledModules.publish ) { |
| 7 | + return true; |
| 8 | + } |
| 9 | + // Add the publish module |
| 10 | + if ( $j.fn.wikiEditor ) { |
| 11 | + $j( 'textarea#wpTextbox1' ).wikiEditor( 'addModule', 'publish' ); |
| 12 | + } |
| 13 | +}); |
Property changes on: trunk/extensions/WikiEditor/modules/Publish.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 14 | + native |
Index: trunk/extensions/WikiEditor/modules/wikiEditor.dialogs.css |
— | — | @@ -0,0 +1,309 @@ |
| 2 | +/* wikiEditor dialogs module */ |
| 3 | + |
| 4 | +.wikiEditor-toolbar-dialog table { |
| 5 | + margin-top: 0.75em; |
| 6 | +} |
| 7 | +.wikiEditor-toolbar-dialog table td { |
| 8 | + padding: 0.5em; |
| 9 | + height: 3em; |
| 10 | + overflow: visible; |
| 11 | +} |
| 12 | +/* Put suggestions (default z-index 99) on top of dialogs (z-index 1002) */ |
| 13 | +div.suggestions { |
| 14 | + z-index: 1099; |
| 15 | +} |
| 16 | +.wikiEditor-toolbar-dialog .ui-dialog-titlebar-close:hover { |
| 17 | + text-decoration: none; |
| 18 | +} |
| 19 | +.wikiEditor-toolbar-dialog .ui-dialog-content .status-invalid input { |
| 20 | + border: 2px solid red; |
| 21 | + padding: 2px 1px; |
| 22 | +} |
| 23 | +.wikiEditor-toolbar-dialog .ui-dialog-titlebar { |
| 24 | + padding: 0.9em 1.4em 0.6em !important; |
| 25 | +} |
| 26 | +.wikiEditor-toolbar-dialog table td { |
| 27 | + padding: 0 !important; |
| 28 | +} |
| 29 | +.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button { |
| 30 | + -moz-border-radius: 4px; |
| 31 | + -webkit-border-radius: 4px; |
| 32 | + padding: 0.2em 0.6em 0.15em !important; |
| 33 | + margin: 0.5em 0 0.5em 0.4em !important; |
| 34 | + border: 1px solid #a6a6a6 !important; |
| 35 | + background: #f2f2f2 url( ../images/wikiEditor/dialogs/button_off.png?1) repeat-x scroll 50% 100% !important; |
| 36 | +} |
| 37 | +.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button:hover { |
| 38 | + border-color: #6e7273; |
| 39 | + background: #e1e1e1 url( ../images/wikiEditor/dialogs/button_over.png?1) repeat-x scroll 50% 100% !important; |
| 40 | +} |
| 41 | +.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button:active, |
| 42 | +.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button:focus { |
| 43 | + border-color: #707271; |
| 44 | + background: #bfbfbf url( ../images/wikiEditor/dialogs/button_down.png?1) repeat-x scroll 50% 100% !important; |
| 45 | +} |
| 46 | +.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button.disabled { |
| 47 | + color: #7f7f7f; |
| 48 | + border-color: #cccccc; |
| 49 | + background: #f2f2f2 url( ../images/wikiEditor/dialogs/button_disabled.png?1) repeat-x scroll 50% 100% !important; |
| 50 | +} |
| 51 | +/* Disables the annoying dashed border Firefox puts on active buttons */ |
| 52 | +.wikiEditor-toolbar-dialog .ui-dialog-buttonpane button::-moz-focus-inner { |
| 53 | + border: 0; |
| 54 | +} |
| 55 | +.wikiEditor-toolbar-dialog .ui-widget-header { |
| 56 | + background: #f0f0f0 url( ../images/wikiEditor/dialogs/titlebar_fade.png?1) repeat-x scroll 50% 100% !important; |
| 57 | +} |
| 58 | +/* FIXME: Should just update the icon sprite if we're keeping this X */ |
| 59 | +.wikiEditor-toolbar-dialog .ui-icon-closethick { |
| 60 | + background: url( ../images/wikiEditor/dialogs/close_x.png?1) no-repeat 50% 50% !important; |
| 61 | +} |
| 62 | +.wikiEditor-toolbar-dialog .ui-dialog-buttonpane { |
| 63 | + margin-top: 0 !important; |
| 64 | + padding:0.3em 1.4em 0.5em 1.4em !important; |
| 65 | +} |
| 66 | + |
| 67 | +.wikiEditor-toolbar-dialog .ui-dialog-content fieldset{ |
| 68 | + border: none !important; |
| 69 | + margin: 0 !important; |
| 70 | + padding: 0 !important; |
| 71 | +} |
| 72 | +.wikiEditor-toolbar-dialog .ui-widget-header { |
| 73 | + border-bottom:1px solid #6bc8f3 !important; |
| 74 | +} |
| 75 | +.wikiEditor-toolbar-dialog .ui-dialog-content input[type=text] { |
| 76 | + -moz-box-sizing: border-box; |
| 77 | + -ms-box-sizing: border-box; |
| 78 | + -webkit-box-sizing: border-box; |
| 79 | + -khtml-box-sizing: border-box; |
| 80 | +} |
| 81 | +.wikiEditor-toolbar-dialog .ui-dialog-content input[type="radio"], |
| 82 | +.wikiEditor-toolbar-dialog .ui-dialog-content input[type="checkbox"] { |
| 83 | + margin-left: 0; |
| 84 | +} |
| 85 | +.wikiEditor-toolbar-dialog .ui-dialog-titlebar-close { |
| 86 | + padding: 0; |
| 87 | +} |
| 88 | +body.ltr .wikiEditor-toolbar-dialog .ui-dialog-titlebar-close { |
| 89 | + right: 0.9em; |
| 90 | +} |
| 91 | +.wikieditor-toolbar-field-wrapper { |
| 92 | + padding: 0 0 25px 0; |
| 93 | +} |
| 94 | +.wikieditor-toolbar-floated-field-wrapper { |
| 95 | + float: left; |
| 96 | + margin-right: 2em; |
| 97 | +} |
| 98 | +.wikieditor-toolbar-dialog-hint { |
| 99 | + color: #999999; |
| 100 | +} |
| 101 | +.wikiEditor-toolbar-dialog, |
| 102 | +.wikiEditor-toolbar-dialog .ui-widget-content { |
| 103 | + border: none !important; |
| 104 | +} |
| 105 | +/* Table Dialog */ |
| 106 | + |
| 107 | +#wikieditor-toolbar-table-dialog fieldset { |
| 108 | + width: 218px; |
| 109 | + padding: 0; |
| 110 | + float: left; |
| 111 | +} |
| 112 | +body.rtl #wikieditor-toolbar-table-dialog fieldset { |
| 113 | + float: right; |
| 114 | +} |
| 115 | +#wikieditor-toolbar-table-dialog .wikieditor-toolbar-table-preview-wrapper { |
| 116 | + width: 330px; |
| 117 | + padding: 0; |
| 118 | + float: right; |
| 119 | +} |
| 120 | +body.rtl #wikieditor-toolbar-table-dialog .wikieditor-toolbar-table-preview-wrapper { |
| 121 | + float: left; |
| 122 | +} |
| 123 | +body.rtl .wikiEditor-toolbar-dialog .wikieditor-toolbar-table-preview-wrapper table { |
| 124 | + margin-left: 1em; |
| 125 | + margin-right: 0; |
| 126 | +} |
| 127 | +.wikieditor-toolbar-table-preview-content * { |
| 128 | + cursor: default; |
| 129 | +} |
| 130 | +.wikiEditor-toolbar-dialog .wikieditor-toolbar-table-preview-wrapper table { |
| 131 | + width: 100% !important; |
| 132 | +} |
| 133 | +.wikiEditor-toolbar-dialog .wikieditor-toolbar-table-preview-content table td { |
| 134 | + padding: 10px 4px !important; |
| 135 | + height: auto !important; |
| 136 | +} |
| 137 | +.wikiEditor-toolbar-dialog .wikieditor-toolbar-table-preview-content table th { |
| 138 | + padding: 7px 3px !important; |
| 139 | +} |
| 140 | +.wikieditor-toolbar-table-dimension-fields .wikieditor-toolbar-field-wrapper { |
| 141 | + float: left; |
| 142 | + margin-right: 20px; |
| 143 | + vertical-align: bottom; |
| 144 | +} |
| 145 | +body.rtl .wikieditor-toolbar-table-dimension-fields .wikieditor-toolbar-field-wrapper { |
| 146 | + float: right; |
| 147 | + margin-right: 0px; |
| 148 | + margin-left: 20px; |
| 149 | +} |
| 150 | +.wikiEditor-toolbar-dialog .ui-dialog-content { |
| 151 | + padding: 30px 20px 0 !important; |
| 152 | +} |
| 153 | +.wikieditor-toolbar-dialog-wrapper { |
| 154 | + width: 100%; |
| 155 | +} |
| 156 | +/* REPLACE Dialog */ |
| 157 | + |
| 158 | +/* Insert Link Dialog */ |
| 159 | +#wikieditor-toolbar-link-int-target-status { |
| 160 | + float: right; |
| 161 | +} |
| 162 | +#wikieditor-toolbar-link-int-target, |
| 163 | +#wikieditor-toolbar-link-int-text { |
| 164 | + width: 100%; |
| 165 | +} |
| 166 | +#wikieditor-toolbar-tool-link-int-target-label { |
| 167 | + float: left; |
| 168 | + line-height: 1.7em; |
| 169 | +} |
| 170 | +#wikieditor-toolbar-link-int-target-status-loading { |
| 171 | + line-height: 1.7em; |
| 172 | +} |
| 173 | +#wikieditor-toolbar-link-int-target-status-exists, |
| 174 | +#wikieditor-toolbar-link-int-target-status-notexists, |
| 175 | +#wikieditor-toolbar-link-int-target-status-invalid, |
| 176 | +#wikieditor-toolbar-link-int-target-status-external { |
| 177 | + padding-left: 30px; |
| 178 | + background-position: 0 50%; |
| 179 | + background-repeat: no-repeat; |
| 180 | +} |
| 181 | +#wikieditor-toolbar-link-int-target-status-exists { |
| 182 | + background-image: url( ../images/wikiEditor/dialogs/insert-link-exists.png?1); |
| 183 | +} |
| 184 | +#wikieditor-toolbar-link-int-target-status-notexists { |
| 185 | + background-image: url( ../images/wikiEditor/dialogs/insert-link-notexists.png?1); |
| 186 | +} |
| 187 | +#wikieditor-toolbar-link-int-target-status-invalid { |
| 188 | + background-image: url( ../images/wikiEditor/dialogs/insert-link-invalid.png?1); |
| 189 | +} |
| 190 | +#wikieditor-toolbar-link-int-target-status-external { |
| 191 | + background-image: url( ../images/wikiEditor/dialogs/insert-link-external.png?1); |
| 192 | +} |
| 193 | + |
| 194 | +/* Reference Dialog */ |
| 195 | +#wikieditor-toolbar-reference-dialog label { |
| 196 | + float: left; |
| 197 | + line-height: 1.7em; |
| 198 | +} |
| 199 | +#wikieditor-toolbar-reference-text { |
| 200 | + width: 100%; |
| 201 | +} |
| 202 | +/* RTL Changes */ |
| 203 | +body.rtl .wikiEditor-toolbar-dialog .ui-dialog-buttonpane button { |
| 204 | + float: left; |
| 205 | + margin: 0.5em 0.4em 0.5em 0 !important; |
| 206 | +} |
| 207 | +body.rtl .wikiEditor-toolbar-dialog .ui-dialog-titlebar-close { |
| 208 | + left: 0.9em; |
| 209 | + right: auto; |
| 210 | +} |
| 211 | +body.rtl .wikiEditor-toolbar-dialog .ui-dialog-title { |
| 212 | + float:right; |
| 213 | +} |
| 214 | +body.rtl #wikieditor-toolbar-link-int-target-status { |
| 215 | + float: left; |
| 216 | +} |
| 217 | +body.rtl #wikieditor-toolbar-tool-link-int-target-label { |
| 218 | + float: right; |
| 219 | +} |
| 220 | +body.rtl .wikieditor-toolbar-floated-field-wrapper { |
| 221 | + float: right; |
| 222 | + margin-right: 0; |
| 223 | + margin-left: 2em; |
| 224 | +} |
| 225 | +body.rtl #wikieditor-toolbar-link-int-target-status-exists, |
| 226 | +body.rtl #wikieditor-toolbar-link-int-target-status-notexists, |
| 227 | +body.rtl #wikieditor-toolbar-link-int-target-status-invalid, |
| 228 | +body.rtl #wikieditor-toolbar-link-int-target-status-external { |
| 229 | + padding-left: 0; |
| 230 | + padding-right: 30px; |
| 231 | + background-position: 100% 50%; |
| 232 | +} |
| 233 | +body.rtl #wikieditor-toolbar-link-int-target-status-external { |
| 234 | + background-image: url( ../images/wikiEditor/dialogs/insert-link-external-rtl.png?1); |
| 235 | +} |
| 236 | +body.rtl #wikieditor-toolbar-reference-dialog label { |
| 237 | + float: right; |
| 238 | +} |
| 239 | +/* Template Editor Dialogs */ |
| 240 | +.wikiEditor-template-dialog-fields label { |
| 241 | + text-transform: capitalize; |
| 242 | + float: left; |
| 243 | + width: 25%; |
| 244 | + line-height: 2.25em; |
| 245 | +} |
| 246 | +.wikiEditor-template-dialog-fields textarea { |
| 247 | + float: right; |
| 248 | + width: 70%; |
| 249 | + line-height: 1.5em; |
| 250 | + height: 1.5em; |
| 251 | +} |
| 252 | +.wikiEditor-template-dialog-fields .wikiEditor-template-dialog-field-wrapper { |
| 253 | + padding: 0.75em 0.33em; |
| 254 | + border-bottom: dashed 1px silver; |
| 255 | + clear: both; |
| 256 | +} |
| 257 | +.wikiEditor-template-dialog-fields .wikiEditor-template-dialog-field-wrapper:first-child { |
| 258 | + padding-top: 0; |
| 259 | +} |
| 260 | +.wikiEditor-template-dialog-fields .wikiEditor-template-dialog-field-wrapper:last-child { |
| 261 | + border-bottom: none; |
| 262 | +} |
| 263 | + |
| 264 | +/* Self Clearing Floats */ |
| 265 | +.wikieditor-toolbar-table-dimension-fields:after, |
| 266 | +.wikieditor-toolbar-dialog-wrapper:after { |
| 267 | + visibility: hidden; |
| 268 | + display: block; |
| 269 | + font-size: 0; |
| 270 | + content: " "; |
| 271 | + clear: both; |
| 272 | + height: 0; |
| 273 | +} |
| 274 | +.wikieditor-toolbar-table-dimension-fields, |
| 275 | +.wikieditor-toolbar-dialog-wrapper { |
| 276 | + display: inline-table; |
| 277 | +} |
| 278 | +/* Hides from IE-mac \*/ |
| 279 | +* html .wikieditor-toolbar-table-dimension-fields, |
| 280 | +* html .wikieditor-toolbar-dialog-wrapper { |
| 281 | + height: 1%; |
| 282 | +} |
| 283 | +.wikieditor-toolbar-table-dimension-fields, |
| 284 | +.wikieditor-toolbar-dialog-wrapper { |
| 285 | + display: block; |
| 286 | +} |
| 287 | +/* End hide from IE-mac */ |
| 288 | + |
| 289 | +.wikiEditor-toolbar-dialog .ui-dialog-buttonpane { |
| 290 | + border-top: 1px solid #cccccc !important; |
| 291 | +} |
| 292 | +.wikiEditor-toolbar-dialog .ui-dialog-content { |
| 293 | + padding-bottom: 1em !important; |
| 294 | +} |
| 295 | + |
| 296 | +/* Edit dialog */ |
| 297 | +.wikiEditor-dialog-editoptions { |
| 298 | + margin-top: 15px; |
| 299 | +} |
| 300 | + |
| 301 | +/* Publish dialog */ |
| 302 | +.wikiEditor-publish-dialog-copywarn { |
| 303 | + margin-top: 0.5em; |
| 304 | +} |
| 305 | +.wikiEditor-publish-dialog-summary { |
| 306 | + margin-top: 1.5em; |
| 307 | +} |
| 308 | +.wikiEditor-publish-dialog-options { |
| 309 | + margin-top: 1.5em; |
| 310 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/WikiEditor/modules/wikiEditor.dialogs.css |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 311 | + native |
Index: trunk/extensions/WikiEditor/modules/Highlight.js |
— | — | @@ -0,0 +1,12 @@ |
| 2 | +/* JavaScript for WikiEditor Highlight module */ |
| 3 | + |
| 4 | +$j(document).ready( function() { |
| 5 | + // Check preferences for highlight |
| 6 | + if ( !wgWikiEditorEnabledModules.toc ) { //HACK |
| 7 | + return true; |
| 8 | + } |
| 9 | + // Add the highlight module |
| 10 | + if ( $j.fn.wikiEditor ) { |
| 11 | + $j( 'textarea#wpTextbox1' ).wikiEditor( 'addModule', 'highlight' ); |
| 12 | + } |
| 13 | +}); |
Property changes on: trunk/extensions/WikiEditor/modules/Highlight.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 14 | + native |
Index: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.preview.js |
— | — | @@ -0,0 +1,170 @@ |
| 2 | +/* Preview module for wikiEditor */ |
| 3 | +( function( $ ) { $.wikiEditor.modules.preview = { |
| 4 | + |
| 5 | +/** |
| 6 | + * Compatability map |
| 7 | + */ |
| 8 | +'browsers': { |
| 9 | + // Left-to-right languages |
| 10 | + 'ltr': { |
| 11 | + 'msie': [['>=', 7]], |
| 12 | + 'firefox': [['>=', 3]], |
| 13 | + 'opera': [['>=', 9.6]], |
| 14 | + 'safari': [['>=', 4]] |
| 15 | + }, |
| 16 | + // Right-to-left languages |
| 17 | + 'rtl': { |
| 18 | + 'msie': [['>=', 8]], |
| 19 | + 'firefox': [['>=', 3]], |
| 20 | + 'opera': [['>=', 9.6]], |
| 21 | + 'safari': [['>=', 4]] |
| 22 | + } |
| 23 | +}, |
| 24 | +/** |
| 25 | + * Internally used functions |
| 26 | + */ |
| 27 | +fn: { |
| 28 | + /** |
| 29 | + * Creates a preview module within a wikiEditor |
| 30 | + * @param context Context object of editor to create module in |
| 31 | + * @param config Configuration object to create module from |
| 32 | + */ |
| 33 | + create: function( context, config ) { |
| 34 | + if ( 'initialized' in context.modules.preview ) { |
| 35 | + return; |
| 36 | + } |
| 37 | + context.modules.preview = { |
| 38 | + 'initialized': true, |
| 39 | + 'previewText': null, |
| 40 | + 'changesText': null |
| 41 | + }; |
| 42 | + context.modules.preview.$preview = context.fn.addView( { |
| 43 | + 'name': 'preview', |
| 44 | + 'titleMsg': 'wikieditor-preview-tab', |
| 45 | + 'init': function( context ) { |
| 46 | + // Gets the latest copy of the wikitext |
| 47 | + var wikitext = context.fn.getContents(); |
| 48 | + // Aborts when nothing has changed since the last preview |
| 49 | + if ( context.modules.preview.previewText == wikitext ) { |
| 50 | + return; |
| 51 | + } |
| 52 | + context.modules.preview.$preview.find( '.wikiEditor-preview-contents' ).empty(); |
| 53 | + context.modules.preview.$preview.find( '.wikiEditor-preview-loading' ).show(); |
| 54 | + $.post( |
| 55 | + wgScriptPath + '/api.php', |
| 56 | + { |
| 57 | + 'action': 'parse', |
| 58 | + 'title': wgPageName, |
| 59 | + 'text': wikitext, |
| 60 | + 'prop': 'text', |
| 61 | + 'pst': '', |
| 62 | + 'format': 'json' |
| 63 | + }, |
| 64 | + function( data ) { |
| 65 | + if ( |
| 66 | + typeof data.parse == 'undefined' || |
| 67 | + typeof data.parse.text == 'undefined' || |
| 68 | + typeof data.parse.text['*'] == 'undefined' |
| 69 | + ) { |
| 70 | + return; |
| 71 | + } |
| 72 | + context.modules.preview.previewText = wikitext; |
| 73 | + context.modules.preview.$preview.find( '.wikiEditor-preview-loading' ).hide(); |
| 74 | + context.modules.preview.$preview.find( '.wikiEditor-preview-contents' ) |
| 75 | + .html( data.parse.text['*'] ) |
| 76 | + .find( 'a:not([href^=#])' ).click( function() { return false; } ); |
| 77 | + }, |
| 78 | + 'json' |
| 79 | + ); |
| 80 | + } |
| 81 | + } ); |
| 82 | + |
| 83 | + context.$changesTab = context.fn.addView( { |
| 84 | + 'name': 'changes', |
| 85 | + 'titleMsg': 'wikieditor-preview-changes-tab', |
| 86 | + 'init': function( context ) { |
| 87 | + // Gets the latest copy of the wikitext |
| 88 | + var wikitext = context.fn.getContents(); |
| 89 | + // Aborts when nothing has changed since the last time |
| 90 | + if ( context.modules.preview.changesText == wikitext ) { |
| 91 | + return; |
| 92 | + } |
| 93 | + context.$changesTab.find( 'table.diff tbody' ).empty(); |
| 94 | + context.$changesTab.find( '.wikiEditor-preview-loading' ).show(); |
| 95 | + |
| 96 | + // Call the API. First PST the input, then diff it |
| 97 | + var postdata = { |
| 98 | + 'action': 'parse', |
| 99 | + 'onlypst': '', |
| 100 | + 'text': wikitext, |
| 101 | + 'format': 'json' |
| 102 | + }; |
| 103 | + |
| 104 | + $.post( wgScriptPath + '/api.php', postdata, function( data ) { |
| 105 | + try { |
| 106 | + var postdata2 = { |
| 107 | + 'action': 'query', |
| 108 | + 'indexpageids': '', |
| 109 | + 'prop': 'revisions', |
| 110 | + 'titles': wgPageName, |
| 111 | + 'rvdifftotext': data.parse.text['*'], |
| 112 | + 'rvprop': '', |
| 113 | + 'format': 'json' |
| 114 | + }; |
| 115 | + var section = $( '[name=wpSection]' ).val(); |
| 116 | + if ( section != '' ) |
| 117 | + postdata['rvsection'] = section; |
| 118 | + |
| 119 | + $.post( wgScriptPath + '/api.php', postdata2, function( data ) { |
| 120 | + // Add diff CSS |
| 121 | + if ( $( 'link[href=' + stylepath + '/common/diff.css]' ).size() == 0 ) { |
| 122 | + $( 'head' ).append( $( '<link />' ).attr( { |
| 123 | + 'rel': 'stylesheet', |
| 124 | + 'type': 'text/css', |
| 125 | + 'href': stylepath + '/common/diff.css' |
| 126 | + } ) ); |
| 127 | + } |
| 128 | + try { |
| 129 | + var diff = data.query.pages[data.query.pageids[0]] |
| 130 | + .revisions[0].diff['*']; |
| 131 | + context.$changesTab.find( 'table.diff tbody' ) |
| 132 | + .html( diff ); |
| 133 | + context.$changesTab |
| 134 | + .find( '.wikiEditor-preview-loading' ).hide(); |
| 135 | + context.modules.preview.changesText = wikitext; |
| 136 | + } catch ( e ) { } // "blah is undefined" error, ignore |
| 137 | + }, 'json' |
| 138 | + ); |
| 139 | + } catch( e ) { } // "blah is undefined" error, ignore |
| 140 | + }, 'json' ); |
| 141 | + } |
| 142 | + } ); |
| 143 | + |
| 144 | + var loadingMsg = mw.usability.getMsg( 'wikieditor-preview-loading' ); |
| 145 | + context.modules.preview.$preview |
| 146 | + .add( context.$changesTab ) |
| 147 | + .append( $( '<div />' ) |
| 148 | + .addClass( 'wikiEditor-preview-loading' ) |
| 149 | + .append( $( '<img />' ) |
| 150 | + .addClass( 'wikiEditor-preview-spinner' ) |
| 151 | + .attr( { |
| 152 | + 'src': $.wikiEditor.imgPath + 'dialogs/loading.gif', |
| 153 | + 'valign': 'absmiddle', |
| 154 | + 'alt': loadingMsg, |
| 155 | + 'title': loadingMsg |
| 156 | + } ) |
| 157 | + ) |
| 158 | + .append( |
| 159 | + $( '<span></span>' ).text( loadingMsg ) |
| 160 | + ) |
| 161 | + ) |
| 162 | + .append( $( '<div />' ) |
| 163 | + .addClass( 'wikiEditor-preview-contents' ) |
| 164 | + ); |
| 165 | + context.$changesTab.find( '.wikiEditor-preview-contents' ) |
| 166 | + .html( '<table class="diff"><col class="diff-marker" /><col class="diff-content" />' + |
| 167 | + '<col class="diff-marker" /><col class="diff-content" /><tbody /></table>' ); |
| 168 | + } |
| 169 | +} |
| 170 | + |
| 171 | +}; } )( jQuery ); |
Property changes on: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.preview.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 172 | + native |
Index: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.templateEditor.js |
— | — | @@ -0,0 +1,864 @@ |
| 2 | +/* TemplateEditor module for wikiEditor */ |
| 3 | +( function( $ ) { $.wikiEditor.modules.templateEditor = { |
| 4 | +/** |
| 5 | + * Name mappings, dirty hack which will be removed once "TemplateInfo" extension is more fully supported |
| 6 | + */ |
| 7 | +'nameMappings': { //keep these all lowercase to navigate web of redirects |
| 8 | + "infobox skyscraper": "building_name", |
| 9 | + "infobox settlement": "official_name" |
| 10 | +}, |
| 11 | + |
| 12 | + |
| 13 | +/** |
| 14 | + * Compatability map |
| 15 | + */ |
| 16 | +'browsers': { |
| 17 | + // Left-to-right languages |
| 18 | + 'ltr': { |
| 19 | + 'msie': [['>=', 8]], |
| 20 | + 'firefox': [['>=', 3]], |
| 21 | + 'opera': [['>=', 10]], |
| 22 | + 'safari': [['>=', 4]] |
| 23 | + }, |
| 24 | + // Right-to-left languages |
| 25 | + 'rtl': { |
| 26 | + 'msie': false, |
| 27 | + 'firefox': [['>=', 3]], |
| 28 | + 'opera': [['>=', 10]], |
| 29 | + 'safari': [['>=', 4]] |
| 30 | + } |
| 31 | +}, |
| 32 | +/** |
| 33 | + * Core Requirements |
| 34 | + */ |
| 35 | +'req': [ 'iframe' ], |
| 36 | +/** |
| 37 | + * Event handlers |
| 38 | + */ |
| 39 | +evt: { |
| 40 | + |
| 41 | + mark: function( context, event ) { |
| 42 | + // The markers returned by this function are skipped on realchange, so don't regenerate them in that case |
| 43 | + if ( context.modules.highlight.currentScope == 'realchange' ) { |
| 44 | + return; |
| 45 | + } |
| 46 | + |
| 47 | + // Get references to the markers and tokens from the current context |
| 48 | + var markers = context.modules.highlight.markers; |
| 49 | + var tokenArray = context.modules.highlight.tokenArray; |
| 50 | + // Collect matching level 0 template call boundaries from the tokenArray |
| 51 | + var level = 0; |
| 52 | + var tokenIndex = 0; |
| 53 | + while ( tokenIndex < tokenArray.length ){ |
| 54 | + while ( tokenIndex < tokenArray.length && tokenArray[tokenIndex].label != 'TEMPLATE_BEGIN' ) { |
| 55 | + tokenIndex++; |
| 56 | + } |
| 57 | + //open template |
| 58 | + if ( tokenIndex < tokenArray.length ) { |
| 59 | + var beginIndex = tokenIndex; |
| 60 | + var endIndex = -1; //no match found |
| 61 | + var openTemplates = 1; |
| 62 | + var templatesMatched = false; |
| 63 | + while ( tokenIndex < tokenArray.length - 1 && endIndex == -1 ) { |
| 64 | + tokenIndex++; |
| 65 | + if ( tokenArray[tokenIndex].label == 'TEMPLATE_BEGIN' ) { |
| 66 | + openTemplates++; |
| 67 | + } else if ( tokenArray[tokenIndex].label == 'TEMPLATE_END' ) { |
| 68 | + openTemplates--; |
| 69 | + if ( openTemplates == 0 ) { |
| 70 | + endIndex = tokenIndex; |
| 71 | + } //we can stop looping |
| 72 | + } |
| 73 | + }//while finding template ending |
| 74 | + if ( endIndex != -1 ) { |
| 75 | + markers.push( { |
| 76 | + start: tokenArray[beginIndex].offset, |
| 77 | + end: tokenArray[endIndex].offset, |
| 78 | + type: 'template', |
| 79 | + anchor: 'wrap', |
| 80 | + afterWrap: function( node ) { |
| 81 | + // Generate model |
| 82 | + var model = $.wikiEditor.modules.templateEditor.fn.updateModel( $( node ) ); |
| 83 | + if ( model.isCollapsible() ) { |
| 84 | + $.wikiEditor.modules.templateEditor.fn.wrapTemplate( $( node ) ); |
| 85 | + $.wikiEditor.modules.templateEditor.fn.bindTemplateEvents( $( node ) ); |
| 86 | + } else { |
| 87 | + $( node ).addClass( 'wikiEditor-template-text' ); |
| 88 | + } |
| 89 | + }, |
| 90 | + beforeUnwrap: function( node ) { |
| 91 | + if ( $( node ).parent().hasClass( 'wikiEditor-template' ) ) { |
| 92 | + $.wikiEditor.modules.templateEditor.fn.unwrapTemplate( $( node ) ); |
| 93 | + } |
| 94 | + }, |
| 95 | + onSkip: function( node ) { |
| 96 | + if ( $( node ).html() == $( node ).data( 'oldHTML' ) ) { |
| 97 | + // No change |
| 98 | + return; |
| 99 | + } |
| 100 | + |
| 101 | + // Text changed, regenerate model |
| 102 | + var model = $.wikiEditor.modules.templateEditor.fn.updateModel( $( node ) ); |
| 103 | + |
| 104 | + // Update template name if needed |
| 105 | + if ( $( node ).parent().hasClass( 'wikiEditor-template' ) ) { |
| 106 | + var $label = $( node ).parent().find( '.wikiEditor-template-label' ); |
| 107 | + var displayName = $.wikiEditor.modules.templateEditor.fn.getTemplateDisplayName( model ); |
| 108 | + if ( $label.text() != displayName ) { |
| 109 | + $label.text( displayName ); |
| 110 | + } |
| 111 | + } |
| 112 | + |
| 113 | + // Wrap or unwrap the template if needed |
| 114 | + if ( $( node ).parent().hasClass( 'wikiEditor-template' ) && |
| 115 | + !model.isCollapsible() ) { |
| 116 | + $.wikiEditor.modules.templateEditor.fn.unwrapTemplate( $( node ) ); |
| 117 | + } else if ( !$( node ).parent().hasClass( 'wikiEditor-template' ) && |
| 118 | + model.isCollapsible() ) { |
| 119 | + $.wikiEditor.modules.templateEditor.fn.wrapTemplate( $( node ) ); |
| 120 | + $.wikiEditor.modules.templateEditor.fn.bindTemplateEvents( $( node ) ); |
| 121 | + } |
| 122 | + }, |
| 123 | + getAnchor: function( ca1, ca2 ) { |
| 124 | + return $( ca1.parentNode ).is( 'span.wikiEditor-template-text' ) ? |
| 125 | + ca1.parentNode : null; |
| 126 | + }, |
| 127 | + context: context, |
| 128 | + skipDivision: 'realchange' |
| 129 | + } ); |
| 130 | + } else { //else this was an unmatched opening |
| 131 | + tokenArray[beginIndex].label = 'TEMPLATE_FALSE_BEGIN'; |
| 132 | + tokenIndex = beginIndex; |
| 133 | + } |
| 134 | + }//if opentemplates |
| 135 | + } |
| 136 | + }, //mark |
| 137 | + |
| 138 | + keydown: function( context, event ) { |
| 139 | + // Reset our ignoreKeypress variable if it's set to true |
| 140 | + if ( context.$iframe.data( 'ignoreKeypress' ) ) { |
| 141 | + context.$iframe.data( 'ignoreKeypress', false ); |
| 142 | + } |
| 143 | + var $evtElem = event.jQueryNode; |
| 144 | + if ( $evtElem.hasClass( 'wikiEditor-template-label' ) ) { |
| 145 | + // Allow anything if the command or control key are depressed |
| 146 | + if ( event.ctrlKey || event.metaKey ) return true; |
| 147 | + switch ( event.which ) { |
| 148 | + case 13: // Enter |
| 149 | + $evtElem.click(); |
| 150 | + event.preventDefault(); |
| 151 | + return false; |
| 152 | + case 32: // Space |
| 153 | + $evtElem.parent().siblings( '.wikiEditor-template-expand' ).click(); |
| 154 | + event.preventDefault(); |
| 155 | + return false; |
| 156 | + case 37:// Left |
| 157 | + case 38:// Up |
| 158 | + case 39:// Right |
| 159 | + case 40: //Down |
| 160 | + return true; |
| 161 | + default: |
| 162 | + // Set the ignroreKeypress variable so we don't allow typing if the key is held |
| 163 | + context.$iframe.data( 'ignoreKeypress', true ); |
| 164 | + // Can't type in a template name |
| 165 | + event.preventDefault(); |
| 166 | + return false; |
| 167 | + } |
| 168 | + } else if ( $evtElem.hasClass( 'wikiEditor-template-text' ) ) { |
| 169 | + switch ( event.which ) { |
| 170 | + case 13: // Enter |
| 171 | + // Ensure that the user can't break this by holding in the enter key |
| 172 | + context.$iframe.data( 'ignoreKeypress', true ); |
| 173 | + // FIXME: May be a more elegant way to do this, but this works too |
| 174 | + context.fn.encapsulateSelection( { 'pre': '\n', 'peri': '', 'post': '' } ); |
| 175 | + event.preventDefault(); |
| 176 | + return false; |
| 177 | + default: return true; |
| 178 | + } |
| 179 | + } |
| 180 | + }, |
| 181 | + keyup: function( context, event ) { |
| 182 | + // Rest our ignoreKeypress variable if it's set to true |
| 183 | + if ( context.$iframe.data( 'ignoreKeypress' ) ) { |
| 184 | + context.$iframe.data( 'ignoreKeypress', false ); |
| 185 | + } |
| 186 | + return true; |
| 187 | + }, |
| 188 | + keypress: function( context, event ) { |
| 189 | + // If this event is from a keydown event which we want to block, ignore it |
| 190 | + return ( context.$iframe.data( 'ignoreKeypress' ) ? false : true ); |
| 191 | + } |
| 192 | +}, |
| 193 | +/** |
| 194 | + * Regular expressions that produce tokens |
| 195 | + */ |
| 196 | +exp: [ |
| 197 | + { 'regex': /{{/, 'label': "TEMPLATE_BEGIN" }, |
| 198 | + { 'regex': /}}/, 'label': "TEMPLATE_END", 'markAfter': true } |
| 199 | +], |
| 200 | +/** |
| 201 | + * Configuration |
| 202 | + */ |
| 203 | +cfg: { |
| 204 | +}, |
| 205 | +/** |
| 206 | + * Internally used functions |
| 207 | + */ |
| 208 | +fn: { |
| 209 | + /** |
| 210 | + * Creates template form module within wikieditor |
| 211 | + * @param context Context object of editor to create module in |
| 212 | + * @param config Configuration object to create module from |
| 213 | + */ |
| 214 | + create: function( context, config ) { |
| 215 | + // Initialize module within the context |
| 216 | + context.modules.templateEditor = {}; |
| 217 | + }, |
| 218 | + /** |
| 219 | + * Turns a simple template wrapper (really just a <span>) into a complex one |
| 220 | + * @param $wrapper Wrapping <span> |
| 221 | + */ |
| 222 | + wrapTemplate: function( $wrapper ) { |
| 223 | + var model = $wrapper.data( 'model' ); |
| 224 | + var context = $wrapper.data( 'marker' ).context; |
| 225 | + var $template = $wrapper |
| 226 | + .wrap( '<span class="wikiEditor-template"></span>' ) |
| 227 | + .addClass( 'wikiEditor-template-text wikiEditor-template-text-shrunken' ) |
| 228 | + .parent() |
| 229 | + .addClass( 'wikiEditor-template-collapsed' ) |
| 230 | + .prepend( |
| 231 | + '<span class="wikiEditor-template-expand wikiEditor-noinclude"></span>' + |
| 232 | + '<span class="wikiEditor-template-name wikiEditor-noinclude">' + |
| 233 | + '<span class="wikiEditor-template-label wikiEditor-noinclude">' + |
| 234 | + $.wikiEditor.modules.templateEditor.fn.getTemplateDisplayName( model ) + '</span>' + |
| 235 | + '<span class="wikiEditor-template-dialog wikiEditor-noinclude"></span>' + |
| 236 | + '</span>' |
| 237 | + ); |
| 238 | + }, |
| 239 | + /** |
| 240 | + * Turn a complex template wrapper back into a simple one |
| 241 | + * @param $wrapper Wrapping <span> |
| 242 | + */ |
| 243 | + unwrapTemplate: function( $wrapper ) { |
| 244 | + $wrapper.parent().replaceWith( $wrapper ); |
| 245 | + }, |
| 246 | + /** |
| 247 | + * Bind events to a template |
| 248 | + * @param $wrapper Original wrapper for the template to bind events to |
| 249 | + */ |
| 250 | + bindTemplateEvents: function( $wrapper ) { |
| 251 | + var $template = $wrapper.parent( '.wikiEditor-template' ); |
| 252 | + |
| 253 | + if ( typeof ( opera ) == "undefined" ) { |
| 254 | + $template.parent().attr('contentEditable', 'false'); |
| 255 | + } |
| 256 | + |
| 257 | + $template.click( function(event) {event.preventDefault(); return false;} ) |
| 258 | + |
| 259 | + $template.find( '.wikiEditor-template-name' ) |
| 260 | + .click( function( event ) { |
| 261 | + $.wikiEditor.modules.templateEditor.fn.createDialog( $wrapper ); |
| 262 | + event.stopPropagation(); |
| 263 | + return false; |
| 264 | + } ) |
| 265 | + .mousedown( function( event ) { event.stopPropagation(); return false; } ); |
| 266 | + $template.find( '.wikiEditor-template-expand' ) |
| 267 | + .click( function( event ) { |
| 268 | + $.wikiEditor.modules.templateEditor.fn.toggleWikiTextEditor( $wrapper ); |
| 269 | + event.stopPropagation(); |
| 270 | + return false; |
| 271 | + } ) |
| 272 | + .mousedown( function( event ) { event.stopPropagation(); return false; } ); |
| 273 | + }, |
| 274 | + /** |
| 275 | + * Toggle the visisbilty of the wikitext for a given template |
| 276 | + * @param $wrapper The origianl wrapper we want expand/collapse |
| 277 | + */ |
| 278 | + toggleWikiTextEditor: function( $wrapper ) { |
| 279 | + var context = $wrapper.data( 'marker' ).context; |
| 280 | + var $template = $wrapper.parent( '.wikiEditor-template' ); |
| 281 | + context.fn.purgeOffsets(); |
| 282 | + $template |
| 283 | + .toggleClass( 'wikiEditor-template-expanded' ) |
| 284 | + .toggleClass( 'wikiEditor-template-collapsed' ) ; |
| 285 | + |
| 286 | + var $templateText = $template.find( '.wikiEditor-template-text' ); |
| 287 | + $templateText.toggleClass( 'wikiEditor-template-text-shrunken' ); |
| 288 | + $templateText.toggleClass( 'wikiEditor-template-text-visible' ); |
| 289 | + if( $templateText.hasClass('wikiEditor-template-text-shrunken') ){ |
| 290 | + //we just closed the template |
| 291 | + |
| 292 | + // Update the model if we need to |
| 293 | + if ( $templateText.html() != $templateText.data( 'oldHTML' ) ) { |
| 294 | + var templateModel = $.wikiEditor.modules.templateEditor.fn.updateModel( $templateText ); |
| 295 | + |
| 296 | + //this is the only place the template name can be changed; keep the template name in sync |
| 297 | + var $tLabel = $template.find( '.wikiEditor-template-label' ); |
| 298 | + $tLabel.text( $.wikiEditor.modules.templateEditor.fn.getTemplateDisplayName( templateModel ) ); |
| 299 | + } |
| 300 | + |
| 301 | + } |
| 302 | + }, |
| 303 | + /** |
| 304 | + * Create a dialog for editing a given template and open it |
| 305 | + * @param $wrapper The origianl wrapper for which to create the dialog |
| 306 | + */ |
| 307 | + createDialog: function( $wrapper ) { |
| 308 | + var context = $wrapper.data( 'marker' ).context; |
| 309 | + var $template = $wrapper.parent( '.wikiEditor-template' ); |
| 310 | + var dialog = { |
| 311 | + 'titleMsg': 'wikieditor-template-editor-dialog-title', |
| 312 | + 'id': 'wikiEditor-template-dialog', |
| 313 | + 'html': '\ |
| 314 | + <fieldset>\ |
| 315 | + <div class="wikiEditor-template-dialog-title" />\ |
| 316 | + <div class="wikiEditor-template-dialog-fields" />\ |
| 317 | + </fieldset>', |
| 318 | + init: function() { |
| 319 | + $(this).find( '[rel]' ).each( function() { |
| 320 | + $(this).text( mw.usability.getMsg( $(this).attr( 'rel' ) ) ); |
| 321 | + } ); |
| 322 | + }, |
| 323 | + dialog: { |
| 324 | + width: 600, |
| 325 | + height: 400, |
| 326 | + dialogClass: 'wikiEditor-toolbar-dialog', |
| 327 | + buttons: { |
| 328 | + 'wikieditor-template-editor-dialog-submit': function() { |
| 329 | + // More user feedback |
| 330 | + var $templateDiv = $( this ).data( 'templateDiv' ); |
| 331 | + context.fn.highlightLine( $templateDiv ); |
| 332 | + |
| 333 | + var $templateText = $templateDiv.children( '.wikiEditor-template-text' ); |
| 334 | + var templateModel = $templateText.data( 'model' ); |
| 335 | + $( this ).find( '.wikiEditor-template-dialog-field-wrapper textarea' ).each( function() { |
| 336 | + // Update the value |
| 337 | + templateModel.setValue( $( this ).data( 'name' ), $( this ).val() ); |
| 338 | + }); |
| 339 | + //keep text consistent |
| 340 | + $.wikiEditor.modules.templateEditor.fn.updateModel( $templateText, templateModel ); |
| 341 | + |
| 342 | + $( this ).dialog( 'close' ); |
| 343 | + }, |
| 344 | + 'wikieditor-template-editor-dialog-cancel': function() { |
| 345 | + $(this).dialog( 'close' ); |
| 346 | + } |
| 347 | + }, |
| 348 | + open: function() { |
| 349 | + var $templateDiv = $( this ).data( 'templateDiv' ); |
| 350 | + var $templateText = $templateDiv.children( '.wikiEditor-template-text' ); |
| 351 | + var templateModel = $templateText.data( 'model' ); |
| 352 | + // Update the model if we need to |
| 353 | + if ( $templateText.html() != $templateText.data( 'oldHTML' ) ) { |
| 354 | + templateModel = $.wikiEditor.modules.templateEditor.fn.updateModel( $templateText ); |
| 355 | + } |
| 356 | + |
| 357 | + // Build the table |
| 358 | + // TODO: Be smart and recycle existing table |
| 359 | + var params = templateModel.getAllInitialParams(); |
| 360 | + var $fields = $( this ).find( '.wikiEditor-template-dialog-fields' ); |
| 361 | + // Do some bookkeeping so we can recycle existing rows |
| 362 | + var $rows = $fields.find( '.wikiEditor-template-dialog-field-wrapper' ); |
| 363 | + for ( var paramIndex in params ) { |
| 364 | + var param = params[paramIndex]; |
| 365 | + if ( typeof param.name == 'undefined' ) { |
| 366 | + // param is the template name, skip it |
| 367 | + continue; |
| 368 | + } |
| 369 | + var paramText = typeof param == 'string' ? |
| 370 | + param.name.replace( /[\_\-]/g, ' ' ) : |
| 371 | + param.name; |
| 372 | + var paramVal = templateModel.getValue( param.name ); |
| 373 | + if ( $rows.length > 0 ) { |
| 374 | + // We have another row to recycle |
| 375 | + var $row = $rows.eq( 0 ); |
| 376 | + $row.children( 'label' ).text( paramText ); |
| 377 | + $row.children( 'textarea' ) |
| 378 | + .data( 'name', param.name ) |
| 379 | + .val( paramVal ) |
| 380 | + .each( function() { |
| 381 | + $(this).css( 'height', $(this).val().length > 24 ? '4.5em' : '1.5em' ); |
| 382 | + } ) |
| 383 | + $rows = $rows.not( $row ); |
| 384 | + } else { |
| 385 | + // Create a new row |
| 386 | + var $paramRow = $( '<div />' ) |
| 387 | + .addClass( 'wikiEditor-template-dialog-field-wrapper' ); |
| 388 | + $( '<label />' ) |
| 389 | + .text( paramText ) |
| 390 | + .appendTo( $paramRow ); |
| 391 | + $( '<textarea />' ) |
| 392 | + .data( 'name', param.name ) |
| 393 | + .val( paramVal ) |
| 394 | + .each( function() { |
| 395 | + $(this).css( 'height', $(this).val().length > 24 ? '4.5em' : '1.5em' ); |
| 396 | + } ) |
| 397 | + .data( 'expanded', false ) |
| 398 | + .bind( 'cut paste keypress click change', function( e ) { |
| 399 | + // If this was fired by a tab keypress, let it go |
| 400 | + if ( e.keyCode == '9' ) return true; |
| 401 | + var $this = $( this ); |
| 402 | + setTimeout( function() { |
| 403 | + var expanded = $this.data( 'expanded' ); |
| 404 | + if ( $this.val().indexOf( '\n' ) != -1 || $this.val().length > 24 ) { |
| 405 | + if ( !expanded ) { |
| 406 | + $this.animate( { 'height': '4.5em' }, 'fast' ); |
| 407 | + $this.data( 'expanded', true ); |
| 408 | + } |
| 409 | + } else { |
| 410 | + if ( expanded ) { |
| 411 | + $this.animate( { 'height': '1.5em' }, 'fast' ); |
| 412 | + $this.data( 'expanded', false ); |
| 413 | + } |
| 414 | + } |
| 415 | + }, 0 ); |
| 416 | + } ) |
| 417 | + .appendTo( $paramRow ); |
| 418 | + $paramRow |
| 419 | + .append( '<div style="clear:both"></div>' ) |
| 420 | + .appendTo( $fields ); |
| 421 | + } |
| 422 | + } |
| 423 | + |
| 424 | + // Remove any leftover rows |
| 425 | + $rows.remove(); |
| 426 | + $fields.find( 'label' ).autoEllipsis(); |
| 427 | + // Ensure our close button doesn't recieve the ui-state-focus class |
| 428 | + $( this ).parent( '.ui-dialog' ).find( '.ui-dialog-titlebar-close' ) |
| 429 | + .removeClass( 'ui-state-focus' ); |
| 430 | + |
| 431 | + // Set tabindexes on form fields if needed |
| 432 | + // First unset the tabindexes on the buttons and existing form fields |
| 433 | + // so the order doesn't get messed up |
| 434 | + var $needTabindex = $( this ).closest( '.ui-dialog' ).find( 'button, textarea' ); |
| 435 | + if ( $needTabindex.not( '[tabindex]' ).length ) { |
| 436 | + // Only do this if there actually are elements missing a tabindex |
| 437 | + $needTabindex.removeAttr( 'tabindex' ); |
| 438 | + $.wikiEditor.modules.dialogs.fn.setTabindexes( $needTabindex ); |
| 439 | + } |
| 440 | + } |
| 441 | + } |
| 442 | + }; |
| 443 | + // Lazy-create the dialog at this time |
| 444 | + context.$textarea.wikiEditor( 'addDialog', { 'templateEditor': dialog } ); |
| 445 | + $( '#' + dialog.id ) |
| 446 | + .data( 'templateDiv', $template ) |
| 447 | + .dialog( 'open' ); |
| 448 | + }, |
| 449 | + /** |
| 450 | + * Update a template's model and HTML |
| 451 | + * @param $templateText Wrapper <span> containing the template text |
| 452 | + * @param model Template model to use, will be generated if not set |
| 453 | + * @return model object |
| 454 | + */ |
| 455 | + updateModel: function( $templateText, model ) { |
| 456 | + var context = $templateText.data( 'marker' ).context; |
| 457 | + var text; |
| 458 | + if ( typeof model == 'undefined' ) { |
| 459 | + text = context.fn.htmlToText( $templateText.html() ); |
| 460 | + } else { |
| 461 | + text = model.getText(); |
| 462 | + } |
| 463 | + // To keep stuff simple but not break it, we need to do encode newlines as <br>s |
| 464 | + $templateText.text( text ); |
| 465 | + $templateText.html( $templateText.html().replace( /\n/g, '<br />' ) ); |
| 466 | + $templateText.data( 'oldHTML', $templateText.html() ); |
| 467 | + if ( typeof model == 'undefined' ) { |
| 468 | + model = new $.wikiEditor.modules.templateEditor.fn.model( text ); |
| 469 | + $templateText.data( 'model', model ); |
| 470 | + } |
| 471 | + return model; |
| 472 | + }, |
| 473 | + |
| 474 | + /** |
| 475 | + * Gets template display name |
| 476 | + */ |
| 477 | + getTemplateDisplayName: function ( model ) { |
| 478 | + var tName = model.getName(); |
| 479 | + if( model.getValue( 'name' ) != '' ) { |
| 480 | + return tName + ': ' + model.getValue( 'name' ); |
| 481 | + } else if( model.getValue( 'Name' ) != '' ) { |
| 482 | + return tName + ': ' + model.getValue( 'Name' ); |
| 483 | + } else if( tName.toLowerCase() in $.wikiEditor.modules.templateEditor.nameMappings ) { |
| 484 | + return tName + ': ' + model.getValue( $.wikiEditor.modules.templateEditor.nameMappings[tName.toLowerCase()] ); |
| 485 | + } |
| 486 | + return tName; |
| 487 | + }, |
| 488 | + |
| 489 | + /** |
| 490 | + * Builds a template model from given wikitext representation, allowing object-oriented manipulation of the contents |
| 491 | + * of the template while preserving whitespace and formatting. |
| 492 | + * |
| 493 | + * @param wikitext String of wikitext content |
| 494 | + */ |
| 495 | + model: function( wikitext ) { |
| 496 | + |
| 497 | + /* Private members */ |
| 498 | + |
| 499 | + var collapsible = true; |
| 500 | + |
| 501 | + /* Private Functions */ |
| 502 | + |
| 503 | + /** |
| 504 | + * Builds a Param object. |
| 505 | + * |
| 506 | + * @param name |
| 507 | + * @param value |
| 508 | + * @param number |
| 509 | + * @param nameIndex |
| 510 | + * @param equalsIndex |
| 511 | + * @param valueIndex |
| 512 | + */ |
| 513 | + function Param( name, value, number, nameIndex, equalsIndex, valueIndex ) { |
| 514 | + this.name = name; |
| 515 | + this.value = value; |
| 516 | + this.number = number; |
| 517 | + this.nameIndex = nameIndex; |
| 518 | + this.equalsIndex = equalsIndex; |
| 519 | + this.valueIndex = valueIndex; |
| 520 | + } |
| 521 | + /** |
| 522 | + * Builds a Range object. |
| 523 | + * |
| 524 | + * @param begin |
| 525 | + * @param end |
| 526 | + */ |
| 527 | + function Range( begin, end ) { |
| 528 | + this.begin = begin; |
| 529 | + this.end = end; |
| 530 | + } |
| 531 | + /** |
| 532 | + * Set 'original' to true if you want the original value irrespective of whether the model's been changed |
| 533 | + * |
| 534 | + * @param name |
| 535 | + * @param value |
| 536 | + * @param original |
| 537 | + */ |
| 538 | + function getSetValue( name, value, original ) { |
| 539 | + var valueRange; |
| 540 | + var rangeIndex; |
| 541 | + var retVal; |
| 542 | + if ( isNaN( name ) ) { |
| 543 | + // It's a string! |
| 544 | + if ( typeof paramsByName[name] == 'undefined' ) { |
| 545 | + // Does not exist |
| 546 | + return ""; |
| 547 | + } |
| 548 | + rangeIndex = paramsByName[name]; |
| 549 | + } else { |
| 550 | + // It's a number! |
| 551 | + rangeIndex = parseInt( name ); |
| 552 | + } |
| 553 | + if ( typeof params[rangeIndex] == 'undefined' ) { |
| 554 | + // Does not exist |
| 555 | + return ""; |
| 556 | + } |
| 557 | + valueRange = ranges[params[rangeIndex].valueIndex]; |
| 558 | + if ( typeof valueRange.newVal == 'undefined' || original ) { |
| 559 | + // Value unchanged, return original wikitext |
| 560 | + retVal = wikitext.substring( valueRange.begin, valueRange.end ); |
| 561 | + } else { |
| 562 | + // New value exists, return new value |
| 563 | + retVal = valueRange.newVal; |
| 564 | + } |
| 565 | + if ( value != null ) { |
| 566 | + ranges[params[rangeIndex].valueIndex].newVal = value; |
| 567 | + } |
| 568 | + return retVal; |
| 569 | + }; |
| 570 | + |
| 571 | + /* Public Functions */ |
| 572 | + |
| 573 | + /** |
| 574 | + * Get template name |
| 575 | + */ |
| 576 | + this.getName = function() { |
| 577 | + if( typeof ranges[templateNameIndex].newVal == 'undefined' ) { |
| 578 | + return wikitext.substring( ranges[templateNameIndex].begin, ranges[templateNameIndex].end ); |
| 579 | + } else { |
| 580 | + return ranges[templateNameIndex].newVal; |
| 581 | + } |
| 582 | + }; |
| 583 | + /** |
| 584 | + * Set template name (if we want to support this) |
| 585 | + * |
| 586 | + * @param name |
| 587 | + */ |
| 588 | + this.setName = function( name ) { |
| 589 | + ranges[templateNameIndex].newVal = name; |
| 590 | + }; |
| 591 | + /** |
| 592 | + * Set value for a given param name / number |
| 593 | + * |
| 594 | + * @param name |
| 595 | + * @param value |
| 596 | + */ |
| 597 | + this.setValue = function( name, value ) { |
| 598 | + return getSetValue( name, value, false ); |
| 599 | + }; |
| 600 | + /** |
| 601 | + * Get value for a given param name / number |
| 602 | + * |
| 603 | + * @param name |
| 604 | + */ |
| 605 | + this.getValue = function( name ) { |
| 606 | + return getSetValue( name, null, false ); |
| 607 | + }; |
| 608 | + /** |
| 609 | + * Get original value of a param |
| 610 | + * |
| 611 | + * @param name |
| 612 | + */ |
| 613 | + this.getOriginalValue = function( name ) { |
| 614 | + return getSetValue( name, null, true ); |
| 615 | + }; |
| 616 | + /** |
| 617 | + * Get a list of all param names (numbers for the anonymous ones) |
| 618 | + */ |
| 619 | + this.getAllParamNames = function() { |
| 620 | + return paramsByName; |
| 621 | + }; |
| 622 | + /** |
| 623 | + * Get the initial params |
| 624 | + */ |
| 625 | + this.getAllInitialParams = function(){ |
| 626 | + return params; |
| 627 | + } |
| 628 | + /** |
| 629 | + * Get original template text |
| 630 | + */ |
| 631 | + this.getOriginalText = function() { |
| 632 | + return wikitext; |
| 633 | + }; |
| 634 | + /** |
| 635 | + * Get modified template text |
| 636 | + */ |
| 637 | + this.getText = function() { |
| 638 | + newText = ""; |
| 639 | + for ( i = 0 ; i < ranges.length; i++ ) { |
| 640 | + if( typeof ranges[i].newVal == 'undefined' ) { |
| 641 | + newText += wikitext.substring( ranges[i].begin, ranges[i].end ); |
| 642 | + } else { |
| 643 | + newText += ranges[i].newVal; |
| 644 | + } |
| 645 | + } |
| 646 | + return newText; |
| 647 | + }; |
| 648 | + |
| 649 | + this.isCollapsible = function() { |
| 650 | + return collapsible; |
| 651 | + } |
| 652 | + |
| 653 | + /** |
| 654 | + * Update ranges if there's been a change in one or more 'segments' of the template. |
| 655 | + * Removes adjustment function so adjustment is only made once ever. |
| 656 | + */ |
| 657 | + |
| 658 | + this.updateRanges = function() { |
| 659 | + var adjustment = 0; |
| 660 | + for (var i = 0 ; i < ranges.length; i++ ) { |
| 661 | + ranges[i].begin += adjustment; |
| 662 | + if( typeof ranges[i].adjust != 'undefined' ) { |
| 663 | + adjustment += ranges[i].adjust(); |
| 664 | + // NOTE: adjust should be a function that has the information necessary to calculate the length of |
| 665 | + // this 'segment' |
| 666 | + delete ranges[i].adjust; |
| 667 | + } |
| 668 | + ranges[i].end += adjustment; |
| 669 | + } |
| 670 | + }; |
| 671 | + |
| 672 | + // Whitespace* {{ whitespace* nonwhitespace: |
| 673 | + if ( wikitext.match( /\s*{{\s*[^\s|]*:/ ) ) { |
| 674 | + collapsible = false; // is a parser function |
| 675 | + } |
| 676 | + /* |
| 677 | + * Take all template-specific characters that are not particular to the template we're looking at, namely {|=}, |
| 678 | + * and convert them into something harmless, in this case 'X' |
| 679 | + */ |
| 680 | + // Get rid of first {{ with whitespace |
| 681 | + var sanatizedStr = wikitext.replace( /{{/, " " ); |
| 682 | + // Replace end |
| 683 | + endBraces = sanatizedStr.match( /}}\s*$/ ); |
| 684 | + if ( endBraces ) { |
| 685 | + sanatizedStr = sanatizedStr.substring( 0, endBraces.index ) + " " + |
| 686 | + sanatizedStr.substring( endBraces.index + 2 ); |
| 687 | + } |
| 688 | + |
| 689 | + |
| 690 | + //treat HTML comments like whitespace |
| 691 | + while ( sanatizedStr.indexOf( '<!' ) != -1 ) { |
| 692 | + startIndex = sanatizedStr.indexOf( '<!' ); |
| 693 | + endIndex = sanatizedStr.indexOf('-->') + 3; |
| 694 | + if( endIndex < 3 ){ |
| 695 | + break; |
| 696 | + } |
| 697 | + sanatizedSegment = sanatizedStr.substring( startIndex,endIndex ).replace( /\S/g , ' ' ); |
| 698 | + sanatizedStr = |
| 699 | + sanatizedStr.substring( 0, startIndex ) + sanatizedSegment + sanatizedStr.substring( endIndex ); |
| 700 | + } |
| 701 | + |
| 702 | + // Match the open braces we just found with equivalent closing braces note, works for any level of braces |
| 703 | + while ( sanatizedStr.indexOf( '{{' ) != -1 ) { |
| 704 | + startIndex = sanatizedStr.indexOf( '{{' ) + 1; |
| 705 | + openBraces = 2; |
| 706 | + endIndex = startIndex; |
| 707 | + while ( (openBraces > 0) && (endIndex < sanatizedStr.length) ) { |
| 708 | + var brace = sanatizedStr[++endIndex]; |
| 709 | + openBraces += brace == '}' ? -1 : brace == '{' ? 1 : 0; |
| 710 | + } |
| 711 | + sanatizedSegment = sanatizedStr.substring( startIndex,endIndex ).replace( /[{}|=]/g , 'X' ); |
| 712 | + sanatizedStr = |
| 713 | + sanatizedStr.substring( 0, startIndex ) + sanatizedSegment + sanatizedStr.substring( endIndex ); |
| 714 | + } |
| 715 | + //links, images, etc, which also can nest |
| 716 | + while ( sanatizedStr.indexOf( '[[' ) != -1 ) { |
| 717 | + startIndex = sanatizedStr.indexOf( '[[' ) + 1; |
| 718 | + openBraces = 2; |
| 719 | + endIndex = startIndex; |
| 720 | + while ( (openBraces > 0) && (endIndex < sanatizedStr.length) ) { |
| 721 | + var brace = sanatizedStr[++endIndex]; |
| 722 | + openBraces += brace == ']' ? -1 : brace == '[' ? 1 : 0; |
| 723 | + } |
| 724 | + sanatizedSegment = sanatizedStr.substring( startIndex,endIndex ).replace( /[\[\]|=]/g , 'X' ); |
| 725 | + sanatizedStr = |
| 726 | + sanatizedStr.substring( 0, startIndex ) + sanatizedSegment + sanatizedStr.substring( endIndex ); |
| 727 | + } |
| 728 | + |
| 729 | + /* |
| 730 | + * Parse 1 param at a time |
| 731 | + */ |
| 732 | + var ranges = []; |
| 733 | + var params = []; |
| 734 | + var templateNameIndex = 0; |
| 735 | + var doneParsing = false; |
| 736 | + oldDivider = 0; |
| 737 | + divider = sanatizedStr.indexOf( '|', oldDivider ); |
| 738 | + if ( divider == -1 ) { |
| 739 | + divider = sanatizedStr.length; |
| 740 | + doneParsing = true; |
| 741 | + collapsible = false; //zero params |
| 742 | + } |
| 743 | + nameMatch = sanatizedStr.substring( 0, divider ).match( /[^\s]/ ); |
| 744 | + if ( nameMatch != null ) { |
| 745 | + ranges.push( new Range( 0 ,nameMatch.index ) ); //whitespace and squiggles upto the name |
| 746 | + nameEndMatch = sanatizedStr.substring( 0 , divider ).match( /[^\s]\s*$/ ); //last nonwhitespace character |
| 747 | + templateNameIndex = ranges.push( new Range( nameMatch.index, |
| 748 | + nameEndMatch.index + 1 ) ); |
| 749 | + templateNameIndex--; //push returns 1 less than the array |
| 750 | + ranges[templateNameIndex].old = wikitext.substring( ranges[templateNameIndex].begin, |
| 751 | + ranges[templateNameIndex].end ); |
| 752 | + } else { |
| 753 | + ranges.push(new Range(0,0)); |
| 754 | + ranges[templateNameIndex].old = ""; |
| 755 | + } |
| 756 | + params.push( ranges[templateNameIndex].old ); //put something in params (0) |
| 757 | + /* |
| 758 | + * Start looping over params |
| 759 | + */ |
| 760 | + var currentParamNumber = 0; |
| 761 | + var valueEndIndex = ranges[templateNameIndex].end; |
| 762 | + var paramsByName = []; |
| 763 | + while ( !doneParsing ) { |
| 764 | + currentParamNumber++; |
| 765 | + oldDivider = divider; |
| 766 | + divider = sanatizedStr.indexOf( '|', oldDivider + 1 ); |
| 767 | + if ( divider == -1 ) { |
| 768 | + divider = sanatizedStr.length; |
| 769 | + doneParsing = true; |
| 770 | + } |
| 771 | + currentField = sanatizedStr.substring( oldDivider+1, divider ); |
| 772 | + if ( currentField.indexOf( '=' ) == -1 ) { |
| 773 | + // anonymous field, gets a number |
| 774 | + |
| 775 | + //default values, since we'll allow empty values |
| 776 | + valueBeginIndex = oldDivider + 1; |
| 777 | + valueEndIndex = oldDivider + 1; |
| 778 | + |
| 779 | + valueBegin = currentField.match( /\S+/ ); //first nonwhitespace character |
| 780 | + if( valueBegin != null ){ |
| 781 | + valueBeginIndex = valueBegin.index + oldDivider+1; |
| 782 | + valueEnd = currentField.match( /[^\s]\s*$/ ); //last nonwhitespace character |
| 783 | + if( valueEnd == null ){ //ie |
| 784 | + continue; |
| 785 | + } |
| 786 | + valueEndIndex = valueEnd.index + oldDivider + 2; |
| 787 | + } |
| 788 | + ranges.push( new Range( ranges[ranges.length-1].end, |
| 789 | + valueBeginIndex ) ); //all the chars upto now |
| 790 | + nameIndex = ranges.push( new Range( valueBeginIndex, valueBeginIndex ) ) - 1; |
| 791 | + equalsIndex = ranges.push( new Range( valueBeginIndex, valueBeginIndex ) ) - 1; |
| 792 | + valueIndex = ranges.push( new Range( valueBeginIndex, valueEndIndex ) ) - 1; |
| 793 | + params.push( new Param( |
| 794 | + currentParamNumber, |
| 795 | + wikitext.substring( ranges[valueIndex].begin, ranges[valueIndex].end ), |
| 796 | + currentParamNumber, |
| 797 | + nameIndex, |
| 798 | + equalsIndex, |
| 799 | + valueIndex |
| 800 | + ) ); |
| 801 | + paramsByName[currentParamNumber] = currentParamNumber; |
| 802 | + } else { |
| 803 | + // There's an equals, could be comment or a value pair |
| 804 | + currentName = currentField.substring( 0, currentField.indexOf( '=' ) ); |
| 805 | + // Still offset by oldDivider - first nonwhitespace character |
| 806 | + nameBegin = currentName.match( /\S+/ ); |
| 807 | + if ( nameBegin == null ) { |
| 808 | + // This is a comment inside a template call / parser abuse. let's not encourage it |
| 809 | + currentParamNumber--; |
| 810 | + continue; |
| 811 | + } |
| 812 | + nameBeginIndex = nameBegin.index + oldDivider + 1; |
| 813 | + // Last nonwhitespace and non } character |
| 814 | + nameEnd = currentName.match( /[^\s]\s*$/ ); |
| 815 | + if( nameEnd == null ){ //ie |
| 816 | + continue; |
| 817 | + } |
| 818 | + nameEndIndex = nameEnd.index + oldDivider + 2; |
| 819 | + // All the chars upto now |
| 820 | + ranges.push( new Range( ranges[ranges.length-1].end, nameBeginIndex ) ); |
| 821 | + nameIndex = ranges.push( new Range( nameBeginIndex, nameEndIndex ) ) - 1; |
| 822 | + currentValue = currentField.substring( currentField.indexOf( '=' ) + 1); |
| 823 | + oldDivider += currentField.indexOf( '=' ) + 1; |
| 824 | + |
| 825 | + //default values, since we'll allow empty values |
| 826 | + valueBeginIndex = oldDivider + 1; |
| 827 | + valueEndIndex = oldDivider + 1; |
| 828 | + |
| 829 | + // First nonwhitespace character |
| 830 | + valueBegin = currentValue.match( /\S+/ ); |
| 831 | + if( valueBegin != null ){ |
| 832 | + valueBeginIndex = valueBegin.index + oldDivider + 1; |
| 833 | + // Last nonwhitespace and non } character |
| 834 | + valueEnd = currentValue.match( /[^\s]\s*$/ ); |
| 835 | + if( valueEnd == null ){ //ie |
| 836 | + continue; |
| 837 | + } |
| 838 | + valueEndIndex = valueEnd.index + oldDivider + 2; |
| 839 | + } |
| 840 | + // All the chars upto now |
| 841 | + equalsIndex = ranges.push( new Range( ranges[ranges.length-1].end, valueBeginIndex) ) - 1; |
| 842 | + valueIndex = ranges.push( new Range( valueBeginIndex, valueEndIndex ) ) - 1; |
| 843 | + params.push( new Param( |
| 844 | + wikitext.substring( nameBeginIndex, nameEndIndex ), |
| 845 | + wikitext.substring( valueBeginIndex, valueEndIndex ), |
| 846 | + currentParamNumber, |
| 847 | + nameIndex, |
| 848 | + equalsIndex, |
| 849 | + valueIndex |
| 850 | + ) ); |
| 851 | + paramsByName[wikitext.substring( nameBeginIndex, nameEndIndex )] = currentParamNumber; |
| 852 | + } |
| 853 | + } |
| 854 | + // The rest of the string |
| 855 | + ranges.push( new Range( valueEndIndex, wikitext.length ) ); |
| 856 | + |
| 857 | + // Save vars |
| 858 | + this.ranges = ranges; |
| 859 | + this.wikitext = wikitext; |
| 860 | + this.params = params; |
| 861 | + this.paramsByName = paramsByName; |
| 862 | + this.templateNameIndex = templateNameIndex; |
| 863 | + } //model |
| 864 | +} |
| 865 | +}; } )( jQuery ); |
Property changes on: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.templateEditor.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 866 | + native |
Index: trunk/extensions/WikiEditor/modules/AddMediaWizard.js |
— | — | @@ -0,0 +1,10 @@ |
| 2 | +/* JavaScript for AddMediaWizard gadget */ |
| 3 | +if ( wgWikiEditorEnabledModules.addMediaWizard ) { |
| 4 | + if( typeof mwAddMediaConfig == 'undefined' ) { |
| 5 | + mwAddMediaConfig = {}; |
| 6 | + } |
| 7 | + mwAddMediaConfig['enabled_providers'] = [ 'wiki_commons', 'upload' ]; |
| 8 | + |
| 9 | + // Transclude mwEmbed support |
| 10 | + importScriptURI( 'http://prototype.wikimedia.org/s-2/js/mwEmbed/remotes/mediaWiki.js?&uselang=' + wgUserLanguage ); |
| 11 | +} |
Property changes on: trunk/extensions/WikiEditor/modules/AddMediaWizard.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 12 | + native |
Index: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.dialogs.js |
— | — | @@ -0,0 +1,213 @@ |
| 2 | +/** |
| 3 | + * Extend the RegExp object with an escaping function |
| 4 | + * From http://simonwillison.net/2006/Jan/20/escape/ |
| 5 | + */ |
| 6 | +RegExp.escape = function( s ) { return s.replace(/([.*+?^${}()|\/\\[\]])/g, '\\$1'); }; |
| 7 | + |
| 8 | +/** |
| 9 | + * Dialog Module for wikiEditor |
| 10 | + */ |
| 11 | +( function( $ ) { $.wikiEditor.modules.dialogs = { |
| 12 | + |
| 13 | +/** |
| 14 | + * Compatability map |
| 15 | + */ |
| 16 | +'browsers': { |
| 17 | + // Left-to-right languages |
| 18 | + 'ltr': { |
| 19 | + 'msie': [['>=', 7]], |
| 20 | + // jQuery UI appears to be broken in FF 2.0 - 2.0.0.4 |
| 21 | + 'firefox': [ |
| 22 | + ['>=', 2], ['!=', '2.0'], ['!=', '2.0.0.1'], ['!=', '2.0.0.2'], ['!=', '2.0.0.3'], ['!=', '2.0.0.4'] |
| 23 | + ], |
| 24 | + 'opera': [['>=', 9.6]], |
| 25 | + 'safari': [['>=', 3]], |
| 26 | + 'chrome': [['>=', 3]] |
| 27 | + }, |
| 28 | + // Right-to-left languages |
| 29 | + 'rtl': { |
| 30 | + 'msie': [['>=', 7]], |
| 31 | + // jQuery UI appears to be broken in FF 2.0 - 2.0.0.4 |
| 32 | + 'firefox': [ |
| 33 | + ['>=', 2], ['!=', '2.0'], ['!=', '2.0.0.1'], ['!=', '2.0.0.2'], ['!=', '2.0.0.3'], ['!=', '2.0.0.4'] |
| 34 | + ], |
| 35 | + 'opera': [['>=', 9.6]], |
| 36 | + 'safari': [['>=', 3]], |
| 37 | + 'chrome': [['>=', 3]] |
| 38 | + } |
| 39 | +}, |
| 40 | +/** |
| 41 | + * API accessible functions |
| 42 | + */ |
| 43 | +api: { |
| 44 | + addDialog: function( context, data ) { |
| 45 | + $.wikiEditor.modules.dialogs.fn.create( context, data ) |
| 46 | + }, |
| 47 | + openDialog: function( context, module ) { |
| 48 | + mw.usability.load( [ '$j.ui', '$j.ui.dialog', '$j.ui.draggable', '$j.ui.resizable' ], function() { |
| 49 | + if ( module in $.wikiEditor.modules.dialogs.modules ) { |
| 50 | + var mod = $.wikiEditor.modules.dialogs.modules[module]; |
| 51 | + var $dialog = $( '#' + mod.id ); |
| 52 | + if ( $dialog.length == 0 ) { |
| 53 | + $.wikiEditor.modules.dialogs.fn.reallyCreate( context, mod ); |
| 54 | + $dialog = $( '#' + mod.id ); |
| 55 | + } |
| 56 | + |
| 57 | + // Workaround for bug in jQuery UI: close button in top right retains focus |
| 58 | + $dialog.closest( '.ui-dialog' ) |
| 59 | + .find( '.ui-dialog-titlebar-close' ) |
| 60 | + .removeClass( 'ui-state-focus' ); |
| 61 | + |
| 62 | + $dialog.dialog( 'open' ); |
| 63 | + } |
| 64 | + } ); |
| 65 | + }, |
| 66 | + closeDialog: function( context, module ) { |
| 67 | + if ( module in $.wikiEditor.modules.dialogs.modules ) { |
| 68 | + $( '#' + $.wikiEditor.modules.dialogs.modules[module].id ).dialog( 'close' ); |
| 69 | + } |
| 70 | + } |
| 71 | +}, |
| 72 | +/** |
| 73 | + * Internally used functions |
| 74 | + */ |
| 75 | +fn: { |
| 76 | + /** |
| 77 | + * Creates a dialog module within a wikiEditor |
| 78 | + * |
| 79 | + * @param {Object} context Context object of editor to create module in |
| 80 | + * @param {Object} config Configuration object to create module from |
| 81 | + */ |
| 82 | + create: function( context, config ) { |
| 83 | + // Defer building of modules, but do check whether they need the iframe rightaway |
| 84 | + for ( mod in config ) { |
| 85 | + var module = config[mod]; |
| 86 | + // Only create the dialog if it's supported, isn't filtered and doesn't exist yet |
| 87 | + var filtered = false; |
| 88 | + if ( typeof module.filters != 'undefined' ) { |
| 89 | + for ( var i = 0; i < module.filters.length; i++ ) { |
| 90 | + if ( $( module.filters[i] ).length == 0 ) { |
| 91 | + filtered = true; |
| 92 | + break; |
| 93 | + } |
| 94 | + } |
| 95 | + } |
| 96 | + if ( !filtered && $.wikiEditor.isSupported( module ) && $( '#' + module.id ).size() == 0 ) { |
| 97 | + $.wikiEditor.modules.dialogs.modules[mod] = module; |
| 98 | + // If this dialog requires the iframe, set it up |
| 99 | + if ( typeof context.$iframe == 'undefined' && $.wikiEditor.isRequired( module, 'iframe' ) ) { |
| 100 | + context.fn.setupIframe(); |
| 101 | + } |
| 102 | + context.$textarea.trigger( 'wikiEditor-dialogs-setup-' + mod ); |
| 103 | + } |
| 104 | + } |
| 105 | + }, |
| 106 | + /** |
| 107 | + * Build the actual dialog. This done on-demand rather than in create() |
| 108 | + * @param {Object} context Context object of editor dialog belongs to |
| 109 | + * @param {Object} module Dialog module object |
| 110 | + */ |
| 111 | + reallyCreate: function( context, module ) { |
| 112 | + var configuration = module.dialog; |
| 113 | + // Add some stuff to configuration |
| 114 | + configuration.bgiframe = true; |
| 115 | + configuration.autoOpen = false; |
| 116 | + configuration.modal = true; |
| 117 | + configuration.title = $.wikiEditor.autoMsg( module, 'title' ); |
| 118 | + // Transform messages in keys |
| 119 | + // Stupid JS won't let us do stuff like |
| 120 | + // foo = { mw.usability.getMsg( 'bar' ): baz } |
| 121 | + configuration.newButtons = {}; |
| 122 | + for ( msg in configuration.buttons ) |
| 123 | + configuration.newButtons[mw.usability.getMsg( msg )] = configuration.buttons[msg]; |
| 124 | + configuration.buttons = configuration.newButtons; |
| 125 | + // Create the dialog <div> |
| 126 | + var dialogDiv = $( '<div />' ) |
| 127 | + .attr( 'id', module.id ) |
| 128 | + .html( module.html ) |
| 129 | + .data( 'context', context ) |
| 130 | + .appendTo( $( 'body' ) ) |
| 131 | + .each( module.init ) |
| 132 | + .dialog( configuration ); |
| 133 | + // Set tabindexes on buttons added by .dialog() |
| 134 | + $.wikiEditor.modules.dialogs.fn.setTabindexes( dialogDiv.closest( '.ui-dialog' ) |
| 135 | + .find( 'button' ).not( '[tabindex]' ) ); |
| 136 | + if ( !( 'resizeme' in module ) || module.resizeme ) { |
| 137 | + dialogDiv |
| 138 | + .bind( 'dialogopen', $.wikiEditor.modules.dialogs.fn.resize ) |
| 139 | + .find( '.ui-tabs' ).bind( 'tabsshow', function() { |
| 140 | + $(this).closest( '.ui-dialog-content' ).each( |
| 141 | + $.wikiEditor.modules.dialogs.fn.resize ); |
| 142 | + }); |
| 143 | + } |
| 144 | + dialogDiv.bind( 'dialogclose', function() { |
| 145 | + context.fn.restoreSelection(); |
| 146 | + } ); |
| 147 | + |
| 148 | + // Let the outside world know we set up this dialog |
| 149 | + context.$textarea.trigger( 'wikiEditor-dialogs-loaded-' + mod ); |
| 150 | + }, |
| 151 | + /** |
| 152 | + * Resize a dialog so its contents fit |
| 153 | + * |
| 154 | + * Usage: dialog.each( resize ); or dialog.bind( 'blah', resize ); |
| 155 | + * NOTE: This function assumes $j.ui.dialog has already been loaded |
| 156 | + */ |
| 157 | + resize: function() { |
| 158 | + var wrapper = $(this).closest( '.ui-dialog' ); |
| 159 | + var oldWidth = wrapper.width(); |
| 160 | + // Make sure elements don't wrapped so we get an accurate idea of whether they really fit. Also temporarily show |
| 161 | + // hidden elements. Work around jQuery bug where <div style="display:inline;" /> inside a dialog is both |
| 162 | + // :visible and :hidden |
| 163 | + var oldHidden = $(this).find( '*' ).not( ':visible' ); |
| 164 | + // Save the style attributes of the hidden elements to restore them later. Calling hide() after show() messes up |
| 165 | + // for elements hidden with a class |
| 166 | + oldHidden.each( function() { |
| 167 | + $(this).data( 'oldstyle', $(this).attr( 'style' ) ); |
| 168 | + }); |
| 169 | + oldHidden.show(); |
| 170 | + var oldWS = $(this).css( 'white-space' ); |
| 171 | + $(this).css( 'white-space', 'nowrap' ); |
| 172 | + if ( wrapper.width() <= $(this).get(0).scrollWidth ) { |
| 173 | + var thisWidth = $(this).data( 'thisWidth' ) ? $(this).data( 'thisWidth' ) : 0; |
| 174 | + thisWidth = Math.max( $(this).get(0).scrollWidth, thisWidth ); |
| 175 | + $(this).width( thisWidth ); |
| 176 | + $(this).data( 'thisWidth', thisWidth ); |
| 177 | + var wrapperWidth = $(this).data( 'wrapperWidth' ) ? $(this).data( 'wrapperWidth' ) : 0; |
| 178 | + wrapperWidth = Math.max( wrapper.get(0).scrollWidth, wrapperWidth ); |
| 179 | + wrapper.width( wrapperWidth ); |
| 180 | + $(this).data( 'wrapperWidth', wrapperWidth ); |
| 181 | + $(this).dialog( { 'width': wrapper.width() } ); |
| 182 | + wrapper.css( 'left', parseInt( wrapper.css( 'left' ) ) - ( wrapper.width() - oldWidth ) / 2 ); |
| 183 | + } |
| 184 | + $(this).css( 'white-space', oldWS ); |
| 185 | + oldHidden.each( function() { |
| 186 | + $(this).attr( 'style', $(this).data( 'oldstyle' ) ); |
| 187 | + }); |
| 188 | + }, |
| 189 | + /** |
| 190 | + * Set the right tabindexes on elements in a dialog |
| 191 | + * @param $elements Elements to set tabindexes on. If they already have tabindexes, this function can behave a bit weird |
| 192 | + */ |
| 193 | + setTabindexes: function( $elements ) { |
| 194 | + // Get the highest tab index |
| 195 | + var tabIndex = mw.usability.getMaxTabIndex() + 1; |
| 196 | + $elements.each( function() { |
| 197 | + $j(this).attr( 'tabindex', tabIndex++ ); |
| 198 | + } ); |
| 199 | + } |
| 200 | +}, |
| 201 | +// This stuff is just hanging here, perhaps we could come up with a better home for this stuff |
| 202 | +modules: {}, |
| 203 | +quickDialog: function( body, settings ) { |
| 204 | + $( '<div />' ) |
| 205 | + .text( body ) |
| 206 | + .appendTo( $( 'body' ) ) |
| 207 | + .dialog( $.extend( { |
| 208 | + bgiframe: true, |
| 209 | + modal: true |
| 210 | + }, settings ) ) |
| 211 | + .dialog( 'open' ); |
| 212 | +} |
| 213 | + |
| 214 | +}; } ) ( jQuery ); |
Property changes on: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.dialogs.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 215 | + native |
Index: trunk/extensions/WikiEditor/modules/wikiEditor.toc.css |
— | — | @@ -0,0 +1,217 @@ |
| 2 | +/* wikiEditor toc module */ |
| 3 | +.wikiEditor-ui-toc { |
| 4 | + /* height and width are set dynamically */ |
| 5 | + /*float: right;*/ |
| 6 | + padding: 0; |
| 7 | + overflow: auto; |
| 8 | + overflow-x: hidden; |
| 9 | +} |
| 10 | +.wikiEditor-ui-toc { |
| 11 | + border-left: solid silver 1px; |
| 12 | +} |
| 13 | +body.rtl .wikiEditor-ui-toc { |
| 14 | + border-right: solid silver 1px; |
| 15 | + border-left: none; |
| 16 | +} |
| 17 | +.wikiEditor-ui-toc ul { |
| 18 | + padding: 0; |
| 19 | + margin: 0; |
| 20 | + list-style: none; |
| 21 | + /* IE needs to be told in great detail how to act, or it misbehaves */ |
| 22 | + list-style-image: none; |
| 23 | + list-style-position: outside; |
| 24 | + list-style-type: none; |
| 25 | + width: 100%; |
| 26 | +} |
| 27 | +.tab-toc { |
| 28 | + /* Should match the toolbar */ |
| 29 | + background-image: url(../images/wikiEditor/toolbar/base.png?1); |
| 30 | + background-position: left top; |
| 31 | + background-repeat: repeat-x; |
| 32 | + height: 26px; |
| 33 | + padding: 3px 0; |
| 34 | + line-height: 26px; |
| 35 | + padding-left: 1em; |
| 36 | + border-bottom: solid 1px silver; |
| 37 | + white-space: nowrap; |
| 38 | + overflow: hidden; |
| 39 | +} |
| 40 | +body.rtl .tab-toc { |
| 41 | + background-position: right top; |
| 42 | + padding-right: 2em; |
| 43 | +} |
| 44 | +.tab-toc a { |
| 45 | + outline: none; |
| 46 | +} |
| 47 | +.wikiEditor-ui-toc li { |
| 48 | + padding: 0; |
| 49 | + margin: 0; |
| 50 | +} |
| 51 | +.wikiEditor-ui-toc ul ul { |
| 52 | + padding: 0; |
| 53 | + margin: 0; |
| 54 | + margin-bottom: 0 !important; |
| 55 | + margin-top: 0 !important; |
| 56 | + list-style: none; |
| 57 | + background-image: none; |
| 58 | +} |
| 59 | +.wikiEditor-ui-toc ul li div { |
| 60 | + display: block; |
| 61 | + font-size: 0.9em; |
| 62 | + cursor: pointer; |
| 63 | + color: #0645ad; |
| 64 | +} |
| 65 | +.wikiEditor-ui-toc ul li div { |
| 66 | + padding: 0.125em; |
| 67 | + padding-left: 1em; |
| 68 | +} |
| 69 | +body.rtl .wikiEditor-ui-toc ul li div { |
| 70 | + padding-right: 1em; |
| 71 | + padding-left: 0; |
| 72 | +} |
| 73 | +.wikiEditor-ui-toc ul ul li div { |
| 74 | + padding-left: 2em; |
| 75 | +} |
| 76 | +body.rtl .wikiEditor-ui-toc ul ul li div { |
| 77 | + padding-right: 2em; |
| 78 | + padding-left: 0; |
| 79 | +} |
| 80 | +.wikiEditor-ui-toc ul ul ul li div { |
| 81 | + padding-left: 3em; |
| 82 | +} |
| 83 | +body.rtl .wikiEditor-ui-toc ul ul ul li div { |
| 84 | + padding-right: 3em; |
| 85 | + padding-left: 0; |
| 86 | +} |
| 87 | +.wikiEditor-ui-toc ul ul ul ul li div { |
| 88 | + padding-left: 4em; |
| 89 | +} |
| 90 | +body.rtl .wikiEditor-ui-toc ul ul ul ul li div { |
| 91 | + padding-right: 4em; |
| 92 | + padding-left: 0; |
| 93 | +} |
| 94 | +.wikiEditor-ui-toc ul ul ul ul ul li div { |
| 95 | + padding-left: 5em; |
| 96 | +} |
| 97 | +body.rtl .wikiEditor-ui-toc ul ul ul ul ul li div { |
| 98 | + padding-right: 5em; |
| 99 | + padding-left: 0; |
| 100 | +} |
| 101 | +.wikiEditor-ui-toc ul ul ul ul ul ul li div { |
| 102 | + padding-left: 6em; |
| 103 | +} |
| 104 | +body.rtl wikiEditor-ui-toc ul ul ul ul ul ul li div { |
| 105 | + padding-right: 6em; |
| 106 | + padding-left: 0; |
| 107 | +} |
| 108 | +.wikiEditor-ui-toc ul li div.current { |
| 109 | + background-color: #FAFAFA; |
| 110 | + color: #333333; |
| 111 | +} |
| 112 | +.wikiEditor-ui-toc ul li div.section-0 { |
| 113 | + font-size: 1em; |
| 114 | + padding-top: 0.5em; |
| 115 | + padding-bottom: 0.5em; |
| 116 | + border-bottom: solid 1px #DDDDDD; |
| 117 | +} |
| 118 | + |
| 119 | +/* Collapsing changes */ |
| 120 | + |
| 121 | +.wikiEditor-ui-toc { |
| 122 | + overflow-y: hidden; |
| 123 | + position: relative; |
| 124 | +} |
| 125 | +.wikiEditor-ui-toc ul { |
| 126 | + overflow-y: auto; |
| 127 | + overflow-x: hidden; |
| 128 | + height: 100%; |
| 129 | + margin-bottom: 0 !important; |
| 130 | + |
| 131 | +} |
| 132 | + |
| 133 | +.wikiEditor-ui-toc ul ul { |
| 134 | + float: none; |
| 135 | + height: auto; |
| 136 | +} |
| 137 | +#wikiEditor-ui-toc-collapse { |
| 138 | + height: 100%; |
| 139 | + width: 18px; |
| 140 | + position: absolute; |
| 141 | + top: 0; |
| 142 | + left: 0; |
| 143 | +} |
| 144 | +.wikiEditor-ui-toc-collapse-open { |
| 145 | + background: #f3f3f3 url(../images/wikiEditor/toc/close.png?1) 4px 50% no-repeat; |
| 146 | + border-left: 1px solid #DDDDDD; |
| 147 | +} |
| 148 | +.wikiEditor-ui-toc-collapse-closed { |
| 149 | + background: #f3f3f3 url(../images/wikiEditor/toc/open.png?1) 4px 50% no-repeat; |
| 150 | +} |
| 151 | + |
| 152 | +/* Resizing Changes */ |
| 153 | +.wikiEditor-ui-toc-resize-vertical, |
| 154 | +.ui-resizable-w { |
| 155 | + width: 4px; |
| 156 | + position: absolute; |
| 157 | + top: 0; |
| 158 | + left: 0; |
| 159 | + height: 100%; |
| 160 | + cursor: ew-resize; |
| 161 | +} |
| 162 | +.wikiEditor-ui .wikiEditor-ui-right { |
| 163 | + overflow: visible; |
| 164 | +} |
| 165 | +.wikiEditor-ui-right .ui-resizable-w { |
| 166 | + left: 0px !important; |
| 167 | + z-index: 0; |
| 168 | +} |
| 169 | + |
| 170 | +.wikiEditor-ui-right .wikiEditor-ui-toc-resize-grip { |
| 171 | + width: 5px; |
| 172 | + height: 12px; |
| 173 | + padding: 3px; |
| 174 | + position: absolute; |
| 175 | + top: 7px; |
| 176 | + left: -12px !important; |
| 177 | + cursor: ew-resize; |
| 178 | + background: url(../images/wikiEditor/toc/grip.png?1) 50% 50% no-repeat; |
| 179 | + z-index: 0; |
| 180 | +} |
| 181 | +body.rtl .wikiEditor-ui-right .wikiEditor-ui-toc-resize-grip { |
| 182 | + right: 2px !important; |
| 183 | +} |
| 184 | +.wikiEditor-ui-toolbar .tab-toc { |
| 185 | + float: right; |
| 186 | + margin: 3px 16px 3px 3px; |
| 187 | + line-height: 26px; |
| 188 | +} |
| 189 | +.wikiEditor-ui-toc-expandControl { |
| 190 | + position: absolute; |
| 191 | + z-index: 2; |
| 192 | + top: 0px; |
| 193 | + right: 10px; |
| 194 | + height: 26px; |
| 195 | + padding: 3px 0; |
| 196 | + line-height: 26px; |
| 197 | + padding-right: 1em; |
| 198 | + white-space: nowrap; |
| 199 | + overflow: hidden; |
| 200 | +} |
| 201 | +body.rtl .wikiEditor-ui-toc-expandControl { |
| 202 | + padding-left: 1em; |
| 203 | + padding-right: 0; |
| 204 | + left: 10px; |
| 205 | + right: auto; |
| 206 | +} |
| 207 | +.wikiEditor-ui-text textarea { |
| 208 | + resize: none; |
| 209 | +} |
| 210 | +.wikiEditor-ui-text textarea:focus { |
| 211 | + outline: none; |
| 212 | +} |
| 213 | + |
| 214 | +/* Self Clearing for the wikiText view */ |
| 215 | +.wikiEditor-ui-view-wikiText { |
| 216 | + overflow: auto; |
| 217 | + width: 100%; |
| 218 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/WikiEditor/modules/wikiEditor.toc.css |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 219 | + native |
Index: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.toc.js |
— | — | @@ -0,0 +1,669 @@ |
| 2 | +/* TOC Module for wikiEditor */ |
| 3 | +( function( $ ) { $.wikiEditor.modules.toc = { |
| 4 | + |
| 5 | +/** |
| 6 | + * Compatability map |
| 7 | + */ |
| 8 | +'browsers': { |
| 9 | + // Left-to-right languages |
| 10 | + 'ltr': { |
| 11 | + 'msie': [['>=', 7]], |
| 12 | + 'firefox': [['>=', 3]], |
| 13 | + 'opera': [['>=', 10]], |
| 14 | + 'safari': [['>=', 4]], |
| 15 | + 'chrome': [['>=', 4]] |
| 16 | + }, |
| 17 | + // Right-to-left languages |
| 18 | + 'rtl': { |
| 19 | + 'msie': [['>=', 8]], |
| 20 | + 'firefox': [['>=', 3]], |
| 21 | + 'opera': [['>=', 10]], |
| 22 | + 'safari': [['>=', 4]], |
| 23 | + 'chrome': [['>=', 4]] |
| 24 | + } |
| 25 | +}, |
| 26 | +/** |
| 27 | + * Core Requirements |
| 28 | + */ |
| 29 | +'req': [ 'iframe' ], |
| 30 | +/** |
| 31 | + * Configuration |
| 32 | + */ |
| 33 | +cfg: { |
| 34 | + // Default width of table of contents |
| 35 | + defaultWidth: '166px', |
| 36 | + // Minimum width to allow resizing to before collapsing the table of contents - used when resizing and collapsing |
| 37 | + minimumWidth: '70px', |
| 38 | + // Minimum width of the wikiText area |
| 39 | + textMinimumWidth: '450px', |
| 40 | + // The style property to be used for positioning the flexible module in regular mode |
| 41 | + flexProperty: 'marginRight', |
| 42 | + // Boolean var indicating text direction |
| 43 | + rtl: false |
| 44 | +}, |
| 45 | +/** |
| 46 | + * API accessible functions |
| 47 | + */ |
| 48 | +api: { |
| 49 | + // |
| 50 | +}, |
| 51 | +/** |
| 52 | + * Event handlers |
| 53 | + */ |
| 54 | +evt: { |
| 55 | + change: function( context, event ) { |
| 56 | + $.wikiEditor.modules.toc.fn.update( context ); |
| 57 | + }, |
| 58 | + ready: function( context, event ) { |
| 59 | + // Add the TOC to the document |
| 60 | + $.wikiEditor.modules.toc.fn.build( context ); |
| 61 | + if ( !context.$content ) { |
| 62 | + return; |
| 63 | + } |
| 64 | + context.$content.parent() |
| 65 | + .blur( function() { |
| 66 | + var context = event.data.context; |
| 67 | + $.wikiEditor.modules.toc.fn.unhighlight( context ); |
| 68 | + }); |
| 69 | + $.wikiEditor.modules.toc.fn.improveUI(); |
| 70 | + $.wikiEditor.modules.toc.evt.resize( context ); |
| 71 | + }, |
| 72 | + resize: function( context, event ) { |
| 73 | + var availableWidth = context.$wikitext.width() - parseFloat( $.wikiEditor.modules.toc.cfg.textMinimumWidth ), |
| 74 | + totalMinWidth = parseFloat( $.wikiEditor.modules.toc.cfg.minimumWidth ) + |
| 75 | + parseFloat( $.wikiEditor.modules.toc.cfg.textMinimumWidth ); |
| 76 | + context.$ui.find( '.wikiEditor-ui-right' ) |
| 77 | + .resizable( 'option', 'maxWidth', availableWidth ); |
| 78 | + if ( context.modules.toc.$toc.data( 'positionMode' ) != 'disabled' && |
| 79 | + context.$wikitext.width() < totalMinWidth ) { |
| 80 | + $.wikiEditor.modules.toc.fn.disable( context ); |
| 81 | + } else if ( context.modules.toc.$toc.data( 'positionMode' ) == 'disabled' && |
| 82 | + context.$wikitext.width() > totalMinWidth ) { |
| 83 | + $.wikiEditor.modules.toc.fn.enable( context ); |
| 84 | + } else if ( context.modules.toc.$toc.data( 'positionMode' ) == 'regular' && |
| 85 | + context.$ui.find( '.wikiEditor-ui-right' ).width() > availableWidth ) { |
| 86 | + //switch mode |
| 87 | + $.wikiEditor.modules.toc.fn.switchLayout( context ); |
| 88 | + } else if ( context.modules.toc.$toc.data( 'positionMode' ) == 'goofy' && |
| 89 | + context.modules.toc.$toc.data( 'previousWidth' ) < context.$wikitext.width() ) { |
| 90 | + //switch mode |
| 91 | + $.wikiEditor.modules.toc.fn.switchLayout( context ); |
| 92 | + } |
| 93 | + if ( context.modules.toc.$toc.data( 'positionMode' ) == 'goofy' ) { |
| 94 | + context.modules.toc.$toc.find( 'div' ).autoEllipsis( |
| 95 | + { 'position': 'right', 'tooltip': true, 'restoreText': true } |
| 96 | + ); |
| 97 | + } |
| 98 | + // reset the height of the TOC |
| 99 | + if ( !context.modules.toc.$toc.data( 'collapsed' ) ){ |
| 100 | + context.modules.toc.$toc.height( |
| 101 | + context.$ui.find( '.wikiEditor-ui-left' ).height() - |
| 102 | + context.$ui.find( '.tab-toc' ).outerHeight() |
| 103 | + ); |
| 104 | + } |
| 105 | + |
| 106 | + // store the width of the view for comparison on next resize |
| 107 | + context.modules.toc.$toc.data( 'previousWidth', context.$wikitext.width() ); |
| 108 | + }, |
| 109 | + mark: function( context, event ) { |
| 110 | + var hash = ''; |
| 111 | + var markers = context.modules.highlight.markers; |
| 112 | + var tokenArray = context.modules.highlight.tokenArray; |
| 113 | + var outline = context.data.outline = []; |
| 114 | + var h = 0; |
| 115 | + for ( var i = 0; i < tokenArray.length; i++ ) { |
| 116 | + if ( tokenArray[i].label != 'TOC_HEADER' ) { |
| 117 | + continue; |
| 118 | + } |
| 119 | + h++; |
| 120 | + markers.push( { |
| 121 | + index: h, |
| 122 | + start: tokenArray[i].tokenStart, |
| 123 | + end: tokenArray[i].offset, |
| 124 | + type: 'toc', |
| 125 | + anchor: 'tag', |
| 126 | + afterWrap: function( node ) { |
| 127 | + var marker = $( node ).data( 'marker' ); |
| 128 | + $( node ).addClass( 'wikiEditor-toc-header' ) |
| 129 | + .addClass( 'wikiEditor-toc-section-' + marker.index ) |
| 130 | + .data( 'section', marker.index ); |
| 131 | + }, |
| 132 | + beforeUnwrap: function( node ) { |
| 133 | + $( node ).removeClass( 'wikiEditor-toc-header' ) |
| 134 | + .removeClass( 'wikiEditor-toc-section-' + $( node ).data( 'section' ) ); |
| 135 | + }, |
| 136 | + onSkip: function( node ) { |
| 137 | + var marker = $( node ).data( 'marker' ); |
| 138 | + if ( $( node ).data( 'section' ) != marker.index ) { |
| 139 | + $( node ) |
| 140 | + .removeClass( 'wikiEditor-toc-section-' + $( node ).data( 'section' ) ) |
| 141 | + .addClass( 'wikiEditor-toc-section-' + marker.index ) |
| 142 | + .data( 'section', marker.index ); |
| 143 | + } |
| 144 | + }, |
| 145 | + getAnchor: function( ca1, ca2 ) { |
| 146 | + return $( ca1.parentNode ).is( '.wikiEditor-toc-header' ) ? |
| 147 | + ca1.parentNode : null; |
| 148 | + } |
| 149 | + } ); |
| 150 | + hash += tokenArray[i].match[2] + '\n'; |
| 151 | + outline.push ( { |
| 152 | + 'text': tokenArray[i].match[2], |
| 153 | + 'level': tokenArray[i].match[1].length, |
| 154 | + 'index': h |
| 155 | + } ); |
| 156 | + } |
| 157 | + // Only update the TOC if it's been changed - we do this by comparing a hash of the headings this time to last |
| 158 | + if ( typeof context.modules.toc.lastHash == 'undefined' || context.modules.toc.lastHash !== hash ) { |
| 159 | + $.wikiEditor.modules.toc.fn.build( context ); |
| 160 | + $.wikiEditor.modules.toc.fn.update( context ); |
| 161 | + // Remember the changed version |
| 162 | + context.modules.toc.lastHash = hash; |
| 163 | + } |
| 164 | + } |
| 165 | +}, |
| 166 | +exp: [ |
| 167 | + { 'regex': /^(={1,6})([^\r\n]+?)\1\s*$/m, 'label': 'TOC_HEADER', 'markAfter': true } |
| 168 | +], |
| 169 | +/** |
| 170 | + * Internally used functions |
| 171 | + */ |
| 172 | +fn: { |
| 173 | + /** |
| 174 | + * Creates a table of contents module within a wikiEditor |
| 175 | + * |
| 176 | + * @param {Object} context Context object of editor to create module in |
| 177 | + * @param {Object} config Configuration object to create module from |
| 178 | + */ |
| 179 | + create: function( context, config ) { |
| 180 | + if ( '$toc' in context.modules.toc ) { |
| 181 | + return; |
| 182 | + } |
| 183 | + $.wikiEditor.modules.toc.cfg.rtl = config.rtl; |
| 184 | + $.wikiEditor.modules.toc.cfg.flexProperty = config.rtl ? 'marginLeft' : 'marginRight'; |
| 185 | + var height = context.$ui.find( '.wikiEditor-ui-left' ).height(); |
| 186 | + context.modules.toc.$toc = $( '<div />' ) |
| 187 | + .addClass( 'wikiEditor-ui-toc' ) |
| 188 | + .data( 'context', context ) |
| 189 | + .data( 'positionMode', 'regular' ) |
| 190 | + .data( 'collapsed', false ); |
| 191 | + context.$ui.find( '.wikiEditor-ui-right' ) |
| 192 | + .append( context.modules.toc.$toc ); |
| 193 | + context.modules.toc.$toc.height( |
| 194 | + context.$ui.find( '.wikiEditor-ui-left' ).height() |
| 195 | + ); |
| 196 | + $.wikiEditor.modules.toc.fn.redraw( context, $.wikiEditor.modules.toc.cfg.defaultWidth ); |
| 197 | + }, |
| 198 | + |
| 199 | + |
| 200 | + redraw: function( context, fixedWidth ) { |
| 201 | + var fixedWidth = parseFloat( fixedWidth ); |
| 202 | + if( context.modules.toc.$toc.data( 'positionMode' ) == 'regular' ) { |
| 203 | + context.$ui.find( '.wikiEditor-ui-right' ) |
| 204 | + .css( 'width', fixedWidth + 'px' ); |
| 205 | + context.$ui.find( '.wikiEditor-ui-left' ) |
| 206 | + .css( $.wikiEditor.modules.toc.cfg.flexProperty, ( -1 * fixedWidth ) + 'px' ) |
| 207 | + .children() |
| 208 | + .css( $.wikiEditor.modules.toc.cfg.flexProperty, fixedWidth + 'px' ); |
| 209 | + } else if( context.modules.toc.$toc.data( 'positionMode' ) == 'goofy' ) { |
| 210 | + context.$ui.find( '.wikiEditor-ui-left' ) |
| 211 | + .css( 'width', fixedWidth ); |
| 212 | + context.$ui.find( '.wikiEditor-ui-right' ) |
| 213 | + .css( $.wikiEditor.modules.toc.cfg.rtl ? 'right': 'left', fixedWidth ); |
| 214 | + context.$wikitext.css( 'height', context.$ui.find( '.wikiEditor-ui-right' ).height() ); |
| 215 | + } |
| 216 | + }, |
| 217 | + switchLayout: function( context ) { |
| 218 | + var width, |
| 219 | + height = context.$ui.find( '.wikiEditor-ui-right' ).height(); |
| 220 | + if( context.modules.toc.$toc.data( 'positionMode' ) == 'regular' |
| 221 | + && !context.modules.toc.$toc.data( 'collapsed' ) ) { |
| 222 | + // store position mode |
| 223 | + context.modules.toc.$toc.data( 'positionMode', 'goofy' ); |
| 224 | + // store the width of the TOC, to ensure we dont allow it to be larger than this when switching back |
| 225 | + context.modules.toc.$toc.data( 'positionModeChangeAt', |
| 226 | + context.$ui.find( '.wikiEditor-ui-right' ).width() ); |
| 227 | + width = $.wikiEditor.modules.toc.cfg.textMinimumWidth; |
| 228 | + // set our styles for goofy mode |
| 229 | + context.$ui.find( '.wikiEditor-ui-left' ) |
| 230 | + .css( $.wikiEditor.modules.toc.cfg.flexProperty, '') |
| 231 | + .css( { 'position': 'absolute', 'float': 'none', |
| 232 | + 'left': $.wikiEditor.modules.toc.cfg.rtl ? 'auto': 0, |
| 233 | + 'right' : $.wikiEditor.modules.toc.cfg.rtl ? 0 : 'auto' } ) |
| 234 | + .children() |
| 235 | + .css( $.wikiEditor.modules.toc.cfg.flexProperty, '' ); |
| 236 | + context.$ui.find( '.wikiEditor-ui-right' ) |
| 237 | + .css( { 'width': 'auto', 'position': 'absolute', 'float': 'none', |
| 238 | + 'right': $.wikiEditor.modules.toc.cfg.rtl ? 'auto': 0, |
| 239 | + 'left' : $.wikiEditor.modules.toc.cfg.rtl ? 0 : 'auto' } ); |
| 240 | + context.$wikitext |
| 241 | + .css( 'position', 'relative' ); |
| 242 | + } else if ( context.modules.toc.$toc.data( 'positionMode' ) == 'goofy' ) { |
| 243 | + // store position mode |
| 244 | + context.modules.toc.$toc.data( 'positionMode', 'regular' ); |
| 245 | + // set width |
| 246 | + width = context.$wikitext.width() - context.$ui.find( '.wikiEditor-ui-left' ).width(); |
| 247 | + if ( width > context.modules.toc.$toc.data( 'positionModeChangeAt' ) ) { |
| 248 | + width = context.modules.toc.$toc.data( 'positionModeChangeAt' ); |
| 249 | + } |
| 250 | + // set our styles for regular mode |
| 251 | + context.$wikitext |
| 252 | + .css( { 'position': '', 'height': '' } ); |
| 253 | + context.$ui.find( '.wikiEditor-ui-right' ) |
| 254 | + .css( $.wikiEditor.modules.toc.cfg.flexProperty, '' ) |
| 255 | + .css( { 'position': '', 'left': '', 'right': '', 'float': '', 'top': '', 'height': '' } ); |
| 256 | + context.$ui.find( '.wikiEditor-ui-left' ) |
| 257 | + .css( { 'width': '', 'position': '', 'left': '', 'float': '', 'right': '' } ); |
| 258 | + } |
| 259 | + $.wikiEditor.modules.toc.fn.redraw( context, width ); |
| 260 | + }, |
| 261 | + disable: function( context ) { |
| 262 | + if ( context.modules.toc.$toc.data( 'collapsed' ) ) { |
| 263 | + context.$ui.find( '.wikiEditor-ui-toc-expandControl' ).hide(); |
| 264 | + } else { |
| 265 | + if( context.modules.toc.$toc.data( 'positionMode' ) == 'goofy' ) { |
| 266 | + $.wikiEditor.modules.toc.fn.switchLayout( context ); |
| 267 | + } |
| 268 | + context.$ui.find( '.wikiEditor-ui-right' ).hide(); |
| 269 | + context.$ui.find( '.wikiEditor-ui-left' ) |
| 270 | + .css( $.wikiEditor.modules.toc.cfg.flexProperty, '' ) |
| 271 | + .children() |
| 272 | + .css( $.wikiEditor.modules.toc.cfg.flexProperty, '' ); |
| 273 | + } |
| 274 | + context.modules.toc.$toc.data( 'positionMode', 'disabled' ); |
| 275 | + }, |
| 276 | + enable: function( context ) { |
| 277 | + context.modules.toc.$toc.data( 'positionMode', 'regular' ); |
| 278 | + if ( context.modules.toc.$toc.data( 'collapsed' ) ) { |
| 279 | + context.$ui.find( '.wikiEditor-ui-toc-expandControl' ).show(); |
| 280 | + } else { |
| 281 | + context.$ui.find( '.wikiEditor-ui-right' ).show(); |
| 282 | + $.wikiEditor.modules.toc.fn.redraw( context, $.wikiEditor.modules.toc.cfg.minimumWidth ); |
| 283 | + context.modules.toc.$toc.find( 'div' ).autoEllipsis( |
| 284 | + { 'position': 'right', 'tooltip': true, 'restoreText': true } |
| 285 | + ); |
| 286 | + } |
| 287 | + }, |
| 288 | + unhighlight: function( context ) { |
| 289 | + // FIXME: For some reason, IE calls this function twice, the first time with context undefined |
| 290 | + // Investigate this when you have time please! In the meantime, the user interaction is working just |
| 291 | + // fine because the second call is valid |
| 292 | + if ( context ) { |
| 293 | + context.modules.toc.$toc.find( 'div' ).removeClass( 'current' ); |
| 294 | + } |
| 295 | + }, |
| 296 | + /** |
| 297 | + * Highlight the section the cursor is currently within |
| 298 | + * |
| 299 | + * @param {Object} context |
| 300 | + */ |
| 301 | + update: function( context ) { |
| 302 | + //temporarily commenting this out because it is causing all kinds of cursor |
| 303 | + //and text jumping issues in IE. WIll get back to this --pdhanda |
| 304 | + /* |
| 305 | + var div = context.fn.beforeSelection( 'wikiEditor-toc-header' ); |
| 306 | + if ( div === null ) { |
| 307 | + // beforeSelection couldn't figure it out, keep the old highlight state |
| 308 | + return; |
| 309 | + } |
| 310 | + |
| 311 | + $.wikiEditor.modules.toc.fn.unhighlight( context ); |
| 312 | + var section = div.data( 'section' ) || 0; |
| 313 | + if ( context.data.outline.length > 0 ) { |
| 314 | + var sectionLink = context.modules.toc.$toc.find( 'div.section-' + section ); |
| 315 | + sectionLink.addClass( 'current' ); |
| 316 | + |
| 317 | + // Scroll the highlighted link into view if necessary |
| 318 | + var relTop = sectionLink.offset().top - context.modules.toc.$toc.offset().top; |
| 319 | + |
| 320 | + var scrollTop = context.modules.toc.$toc.scrollTop(); |
| 321 | + var divHeight = context.modules.toc.$toc.height(); |
| 322 | + var sectionHeight = sectionLink.height(); |
| 323 | + if ( relTop < 0 ) |
| 324 | + // Scroll up |
| 325 | + context.modules.toc.$toc.scrollTop( scrollTop + relTop ); |
| 326 | + else if ( relTop + sectionHeight > divHeight ) |
| 327 | + // Scroll down |
| 328 | + context.modules.toc.$toc.scrollTop( scrollTop + relTop + sectionHeight - divHeight ); |
| 329 | + } |
| 330 | + */ |
| 331 | + }, |
| 332 | + |
| 333 | + /** |
| 334 | + * Collapse the contents module |
| 335 | + * |
| 336 | + * @param {Object} event Event object with context as data |
| 337 | + */ |
| 338 | + collapse: function( event ) { |
| 339 | + var $this = $( this ), |
| 340 | + context = $this.data( 'context' ); |
| 341 | + if( context.modules.toc.$toc.data( 'positionMode' ) == 'goofy' ) { |
| 342 | + $.wikiEditor.modules.toc.fn.switchLayout( context ); |
| 343 | + } |
| 344 | + var pT = $this.parent().position().top - 1; |
| 345 | + context.modules.toc.$toc.data( 'collapsed', true ); |
| 346 | + var leftParam = {}, leftChildParam = {}; |
| 347 | + leftParam[ $.wikiEditor.modules.toc.cfg.flexProperty ] = '-1px'; |
| 348 | + leftChildParam[ $.wikiEditor.modules.toc.cfg.flexProperty ] = '1px'; |
| 349 | + context.$ui.find( '.wikiEditor-ui-left' ) |
| 350 | + .animate( leftParam, 'fast', function() { |
| 351 | + $( this ).css( $.wikiEditor.modules.toc.cfg.flexProperty, 0 ); |
| 352 | + } ) |
| 353 | + .children() |
| 354 | + .animate( leftChildParam, 'fast', function() { |
| 355 | + $( this ).css( $.wikiEditor.modules.toc.cfg.flexProperty, 0 ); |
| 356 | + } ); |
| 357 | + context.$ui.find( '.wikiEditor-ui-right' ) |
| 358 | + .css( { |
| 359 | + 'marginTop' : '1px', |
| 360 | + 'position' : 'absolute', |
| 361 | + 'left' : $.wikiEditor.modules.toc.cfg.rtl ? 0 : 'auto', |
| 362 | + 'right' : $.wikiEditor.modules.toc.cfg.rtl ? 'auto' : 0, |
| 363 | + 'top' : pT } ) |
| 364 | + .fadeOut( 'fast', function() { |
| 365 | + $( this ).hide() |
| 366 | + .css( { 'marginTop': '0', 'width': '1px' } ); |
| 367 | + context.$ui.find( '.wikiEditor-ui-toc-expandControl' ).fadeIn( 'fast' ); |
| 368 | + // Let the UI know things have moved around |
| 369 | + context.fn.trigger( 'tocCollapse' ); |
| 370 | + context.fn.trigger( 'resize' ); |
| 371 | + } ); |
| 372 | + |
| 373 | + $.cookie( 'wikiEditor-' + context.instance + '-toc-width', 0 ); |
| 374 | + return false; |
| 375 | + }, |
| 376 | + |
| 377 | + /** |
| 378 | + * Expand the contents module |
| 379 | + * |
| 380 | + * @param {Object} event Event object with context as data |
| 381 | + */ |
| 382 | + expand: function( event ) { |
| 383 | + var $this = $( this ), |
| 384 | + context = $this.data( 'context' ), |
| 385 | + openWidth = parseFloat( context.modules.toc.$toc.data( 'openWidth' ) ), |
| 386 | + availableSpace = context.$wikitext.width() - parseFloat( $.wikiEditor.modules.toc.cfg.textMinimumWidth ); |
| 387 | + if ( availableSpace < $.wikiEditor.modules.toc.cfg.textMinmumWidth ) return false; |
| 388 | + context.modules.toc.$toc.data( 'collapsed', false ); |
| 389 | + // check if we've got enough room to open to our stored width |
| 390 | + if ( availableSpace < openWidth ) openWidth = availableSpace; |
| 391 | + context.$ui.find( '.wikiEditor-ui-toc-expandControl' ).hide(); |
| 392 | + var leftParam = {}, leftChildParam = {}; |
| 393 | + leftParam[ $.wikiEditor.modules.toc.cfg.flexProperty ] = parseFloat( openWidth ) * -1; |
| 394 | + leftChildParam[ $.wikiEditor.modules.toc.cfg.flexProperty ] = openWidth; |
| 395 | + context.$ui.find( '.wikiEditor-ui-left' ) |
| 396 | + .animate( leftParam, 'fast' ) |
| 397 | + .children() |
| 398 | + .animate( leftChildParam, 'fast' ); |
| 399 | + context.$ui.find( '.wikiEditor-ui-right' ) |
| 400 | + .show() |
| 401 | + .css( 'marginTop', '1px' ) |
| 402 | + .animate( { 'width' : openWidth }, 'fast', function() { |
| 403 | + context.$content.trigger( 'mouseup' ); |
| 404 | + $( this ).css( { |
| 405 | + 'marginTop' : '0', |
| 406 | + 'position' : 'relative', |
| 407 | + 'right' : 'auto', |
| 408 | + 'left' : 'auto', |
| 409 | + 'top': 'auto' } ); |
| 410 | + context.fn.trigger( 'tocExpand' ); |
| 411 | + context.fn.trigger( 'resize' ); |
| 412 | + } ); |
| 413 | + $.cookie( 'wikiEditor-' + context.instance + '-toc-width', |
| 414 | + context.modules.toc.$toc.data( 'openWidth' ) ); |
| 415 | + return false; |
| 416 | + }, |
| 417 | + /** |
| 418 | + * Builds table of contents |
| 419 | + * |
| 420 | + * @param {Object} context |
| 421 | + */ |
| 422 | + build: function( context ) { |
| 423 | + /** |
| 424 | + * Builds a structured outline from flat outline |
| 425 | + * |
| 426 | + * @param {Object} outline Array of objects with level fields |
| 427 | + */ |
| 428 | + function buildStructure( outline, offset, level ) { |
| 429 | + if ( offset == undefined ) offset = 0; |
| 430 | + if ( level == undefined ) level = 1; |
| 431 | + var sections = []; |
| 432 | + for ( var i = offset; i < outline.length; i++ ) { |
| 433 | + if ( outline[i].nLevel == level ) { |
| 434 | + var sub = buildStructure( outline, i + 1, level + 1 ); |
| 435 | + if ( sub.length ) { |
| 436 | + outline[i].sections = sub; |
| 437 | + } |
| 438 | + sections[sections.length] = outline[i]; |
| 439 | + } else if ( outline[i].nLevel < level ) { |
| 440 | + break; |
| 441 | + } |
| 442 | + } |
| 443 | + return sections; |
| 444 | + } |
| 445 | + /** |
| 446 | + * Builds unordered list HTML object from structured outline |
| 447 | + * |
| 448 | + * @param {Object} structure Structured outline |
| 449 | + */ |
| 450 | + function buildList( structure ) { |
| 451 | + var list = $( '<ul />' ); |
| 452 | + for ( i in structure ) { |
| 453 | + var div = $( '<div />' ) |
| 454 | + .addClass( 'section-' + structure[i].index ) |
| 455 | + .data( 'index', structure[i].index ) |
| 456 | + .mousedown( function() { |
| 457 | + // No dragging! |
| 458 | + return false; |
| 459 | + } ) |
| 460 | + .click( function( event ) { |
| 461 | + var wrapper = context.$content.find( |
| 462 | + '.wikiEditor-toc-section-' + $( this ).data( 'index' ) ); |
| 463 | + if ( wrapper.size() == 0 ) |
| 464 | + wrapper = context.$content; |
| 465 | + context.fn.scrollToTop( wrapper, true ); |
| 466 | + context.$textarea.textSelection( 'setSelection', { |
| 467 | + 'start': 0, |
| 468 | + 'startContainer': wrapper |
| 469 | + } ); |
| 470 | + // Bring user's eyes to the point we've now jumped to |
| 471 | + context.fn.highlightLine( $( wrapper ) ); |
| 472 | + // Highlight the clicked link |
| 473 | + //remove highlighting of toc after a second. Temporary hack till the highlight works --pdhanda |
| 474 | + //$.wikiEditor.modules.toc.fn.unhighlight( context ); |
| 475 | + $( this ).addClass( 'current' ); |
| 476 | + //$( this ).removeClass( 'current' ); |
| 477 | + setTimeout( function() { $.wikiEditor.modules.toc.fn.unhighlight( context ) }, 1000 ); |
| 478 | + |
| 479 | + if ( typeof $.trackAction != 'undefined' ) |
| 480 | + $.trackAction( 'ntoc.heading' ); |
| 481 | + event.preventDefault(); |
| 482 | + } ) |
| 483 | + .text( structure[i].text ); |
| 484 | + if ( structure[i].text == '' ) |
| 485 | + div.html( ' ' ); |
| 486 | + var item = $( '<li />' ).append( div ); |
| 487 | + if ( structure[i].sections !== undefined ) { |
| 488 | + item.append( buildList( structure[i].sections ) ); |
| 489 | + } |
| 490 | + list.append( item ); |
| 491 | + } |
| 492 | + return list; |
| 493 | + } |
| 494 | + /** |
| 495 | + * Builds controls for collapsing and expanding the TOC |
| 496 | + * |
| 497 | + */ |
| 498 | + function buildCollapseControls( ) { |
| 499 | + var $collapseControl = $( '<div />' ), $expandControl = $( '<div />' ); |
| 500 | + $collapseControl |
| 501 | + .addClass( 'tab' ) |
| 502 | + .addClass( 'tab-toc' ) |
| 503 | + .append( '<a href="#" />' ) |
| 504 | + .mousedown( function( e ) { |
| 505 | + // No dragging! |
| 506 | + e.preventDefault(); |
| 507 | + return false; |
| 508 | + } ) |
| 509 | + .bind( 'click.wikiEditor-toc', function( e ) { |
| 510 | + context.modules.toc.$toc.trigger( 'collapse.wikiEditor-toc' ); |
| 511 | + // No dragging! |
| 512 | + e.preventDefault(); |
| 513 | + return false; |
| 514 | + } ) |
| 515 | + .find( 'a' ) |
| 516 | + .text( mw.usability.getMsg( 'wikieditor-toc-hide' ) ); |
| 517 | + $expandControl |
| 518 | + .addClass( 'wikiEditor-ui-toc-expandControl' ) |
| 519 | + .append( '<a href="#" />' ) |
| 520 | + .mousedown( function( e ) { |
| 521 | + // No dragging! |
| 522 | + e.preventDefault(); |
| 523 | + return false; |
| 524 | + } ) |
| 525 | + .bind( 'click.wikiEditor-toc', function( e ) { |
| 526 | + context.modules.toc.$toc.trigger( 'expand.wikiEditor-toc' ); |
| 527 | + // No dragging! |
| 528 | + e.preventDefault(); |
| 529 | + return false; |
| 530 | + } ) |
| 531 | + .hide() |
| 532 | + .find( 'a' ) |
| 533 | + .text( mw.usability.getMsg( 'wikieditor-toc-show' ) ); |
| 534 | + $collapseControl.insertBefore( context.modules.toc.$toc ); |
| 535 | + context.$ui.find( '.wikiEditor-ui-left .wikiEditor-ui-top' ).append( $expandControl ); |
| 536 | + } |
| 537 | + /** |
| 538 | + * Initializes resizing controls on the TOC and sets the width of |
| 539 | + * the TOC based on it's previous state |
| 540 | + * |
| 541 | + */ |
| 542 | + function buildResizeControls( ) { |
| 543 | + context.$ui |
| 544 | + .data( 'resizableDone', true ) |
| 545 | + .find( '.wikiEditor-ui-right' ) |
| 546 | + .data( 'wikiEditor-ui-left', context.$ui.find( '.wikiEditor-ui-left' ) ) |
| 547 | + .resizable( { handles: 'w,e', preventPositionLeftChange: true, |
| 548 | + minWidth: parseFloat( $.wikiEditor.modules.toc.cfg.minimumWidth ), |
| 549 | + start: function( e, ui ) { |
| 550 | + var $this = $( this ); |
| 551 | + // Toss a transparent cover over our iframe |
| 552 | + $( '<div />' ) |
| 553 | + .addClass( 'wikiEditor-ui-resize-mask' ) |
| 554 | + .css( { |
| 555 | + 'position': 'absolute', |
| 556 | + 'z-index': 2, |
| 557 | + 'left': 0, |
| 558 | + 'top': 0, |
| 559 | + 'bottom': 0, |
| 560 | + 'right': 0 |
| 561 | + } ) |
| 562 | + .appendTo( context.$ui.find( '.wikiEditor-ui-left' ) ); |
| 563 | + $this.resizable( 'option', 'maxWidth', $this.parent().width() - |
| 564 | + parseFloat( $.wikiEditor.modules.toc.cfg.textMinimumWidth ) ); |
| 565 | + if(context.modules.toc.$toc.data( 'positionMode' ) == 'goofy' ) { |
| 566 | + $.wikiEditor.modules.toc.fn.switchLayout( context ); |
| 567 | + } |
| 568 | + }, |
| 569 | + resize: function( e, ui ) { |
| 570 | + // for some odd reason, ui.size.width seems a step ahead of what the *actual* width of |
| 571 | + // the resizable is |
| 572 | + $( this ).css( { 'width': ui.size.width, 'top': 'auto', 'height': 'auto' } ) |
| 573 | + .data( 'wikiEditor-ui-left' ) |
| 574 | + .css( $.wikiEditor.modules.toc.cfg.flexProperty, ( -1 * ui.size.width ) ) |
| 575 | + .children().css( $.wikiEditor.modules.toc.cfg.flexProperty, ui.size.width ); |
| 576 | + // Let the UI know things have moved around |
| 577 | + context.fn.trigger( 'resize' ); |
| 578 | + }, |
| 579 | + stop: function ( e, ui ) { |
| 580 | + context.$ui.find( '.wikiEditor-ui-resize-mask' ).remove(); |
| 581 | + context.$content.trigger( 'mouseup' ); |
| 582 | + if( ui.size.width <= parseFloat( $.wikiEditor.modules.toc.cfg.minimumWidth ) ) { |
| 583 | + context.modules.toc.$toc.trigger( 'collapse.wikiEditor-toc' ); |
| 584 | + } else { |
| 585 | + context.modules.toc.$toc.find( 'div' ).autoEllipsis( |
| 586 | + { 'position': 'right', 'tooltip': true, 'restoreText': true } |
| 587 | + ); |
| 588 | + context.modules.toc.$toc.data( 'openWidth', ui.size.width ); |
| 589 | + $.cookie( 'wikiEditor-' + context.instance + '-toc-width', ui.size.width ); |
| 590 | + } |
| 591 | + // Let the UI know things have moved around |
| 592 | + context.fn.trigger( 'resize' ); |
| 593 | + } |
| 594 | + }); |
| 595 | + // Convert our east resize handle into a secondary west resize handle |
| 596 | + var handle = $.wikiEditor.modules.toc.cfg.rtl ? 'w' : 'e'; |
| 597 | + context.$ui.find( '.ui-resizable-' + handle ) |
| 598 | + .removeClass( 'ui-resizable-' + handle ) |
| 599 | + .addClass( 'ui-resizable-' + ( handle == 'w' ? 'e' : 'w' ) ) |
| 600 | + .addClass( 'wikiEditor-ui-toc-resize-grip' ); |
| 601 | + // Bind collapse and expand event handlers to the TOC |
| 602 | + context.modules.toc.$toc |
| 603 | + .bind( 'collapse.wikiEditor-toc', $.wikiEditor.modules.toc.fn.collapse ) |
| 604 | + .bind( 'expand.wikiEditor-toc', $.wikiEditor.modules.toc.fn.expand ); |
| 605 | + context.modules.toc.$toc.data( 'openWidth', $.wikiEditor.modules.toc.cfg.defaultWidth ); |
| 606 | + // If the toc-width cookie is set, reset the widths based upon that |
| 607 | + if ( $.cookie( 'wikiEditor-' + context.instance + '-toc-width' ) == 0 ) { |
| 608 | + context.modules.toc.$toc.trigger( 'collapse.wikiEditor-toc', { data: context } ); |
| 609 | + } else if ( $.cookie( 'wikiEditor-' + context.instance + '-toc-width' ) > 0 ) { |
| 610 | + var initialWidth = $.cookie( 'wikiEditor-' + context.instance + '-toc-width' ); |
| 611 | + if( initialWidth < parseFloat( $.wikiEditor.modules.toc.cfg.minimumWidth ) ) |
| 612 | + initialWidth = parseFloat( $.wikiEditor.modules.toc.cfg.minimumWidth ) + 1; |
| 613 | + context.modules.toc.$toc.data( 'openWidth', initialWidth + 'px' ); |
| 614 | + $.wikiEditor.modules.toc.fn.redraw( context, initialWidth ); |
| 615 | + } |
| 616 | + } |
| 617 | + |
| 618 | + // Normalize heading levels for list creation |
| 619 | + // This is based on Linker::generateTOC(), so it should behave like the |
| 620 | + // TOC on rendered articles does - which is considdered to be correct |
| 621 | + // at this point in time. |
| 622 | + if ( context.data.outline ) { |
| 623 | + var outline = context.data.outline; |
| 624 | + var lastLevel = 0; |
| 625 | + var nLevel = 0; |
| 626 | + for ( var i = 0; i < outline.length; i++ ) { |
| 627 | + if ( outline[i].level > lastLevel ) { |
| 628 | + nLevel++; |
| 629 | + } |
| 630 | + else if ( outline[i].level < lastLevel ) { |
| 631 | + nLevel -= Math.max( 1, lastLevel - outline[i].level ); |
| 632 | + } |
| 633 | + if ( nLevel <= 0 ) { |
| 634 | + nLevel = 1; |
| 635 | + } |
| 636 | + outline[i].nLevel = nLevel; |
| 637 | + lastLevel = outline[i].level; |
| 638 | + } |
| 639 | + // Recursively build the structure and add special item for |
| 640 | + // section 0, if needed |
| 641 | + var structure = buildStructure( outline ); |
| 642 | + if ( $( 'input[name=wpSection]' ).val() == '' ) { |
| 643 | + structure.unshift( { 'text': wgPageName.replace( /_/g, ' ' ), 'level': 1, 'index': 0 } ); |
| 644 | + } |
| 645 | + context.modules.toc.$toc.html( buildList( structure ) ); |
| 646 | + |
| 647 | + if ( wgNavigableTOCResizable && !context.$ui.data( 'resizableDone' ) ) { |
| 648 | + buildResizeControls(); |
| 649 | + buildCollapseControls(); |
| 650 | + } |
| 651 | + context.modules.toc.$toc.find( 'div' ).autoEllipsis( |
| 652 | + { 'position': 'right', 'tooltip': true, 'restoreText': true } |
| 653 | + ); |
| 654 | + } |
| 655 | + }, |
| 656 | + improveUI: function() { |
| 657 | + /* |
| 658 | + * Extending resizable to allow west resizing without altering the left position attribute |
| 659 | + */ |
| 660 | + $.ui.plugin.add( "resizable", "preventPositionLeftChange", { |
| 661 | + resize: function( event, ui ) { |
| 662 | + $( this ).data( "resizable" ).position.left = 0; |
| 663 | + } |
| 664 | + } ); |
| 665 | + } |
| 666 | +} |
| 667 | + |
| 668 | +}; |
| 669 | + |
| 670 | +} ) ( jQuery ); |
Property changes on: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.toc.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 671 | + native |
Index: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.html |
— | — | @@ -0,0 +1,135 @@ |
| 2 | +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
| 3 | +<html> |
| 4 | +<head> |
| 5 | + <title>WikiEditor</title> |
| 6 | + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
| 7 | + <!--[if gte IE 8]> |
| 8 | + <style> |
| 9 | + /* IE8 ONLY - This is how we are fixing the double-height of BR tags when they are alone in a P tag */ |
| 10 | + p > br { |
| 11 | + display: none; |
| 12 | + } |
| 13 | + p > br + br { |
| 14 | + display: block; |
| 15 | + } |
| 16 | + </style> |
| 17 | + <![endif]--> |
| 18 | + <style> |
| 19 | + body { |
| 20 | + margin: 0; |
| 21 | + padding: 0; |
| 22 | + width: 100%; |
| 23 | + height: 100%; |
| 24 | + font-family: monospace; |
| 25 | + font-size: 9.5pt; |
| 26 | + line-height: 1.5em; |
| 27 | + overflow-x: auto; /* Use horizontal scroller if needed; for Firefox 2, not needed in Firefox 3 */ |
| 28 | + white-space: pre-wrap; /* css-3 */ |
| 29 | + white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */ |
| 30 | + white-space: -pre-wrap; /* Opera 4-6 */ |
| 31 | + white-space: -o-pre-wrap; /* Opera 7 */ |
| 32 | + word-wrap: break-word; /* Internet Explorer 5.5+ */ |
| 33 | + } |
| 34 | + body.pasting { |
| 35 | + white-space: normal; |
| 36 | + } |
| 37 | + p { |
| 38 | + margin: 0; |
| 39 | + padding: 0; |
| 40 | + } |
| 41 | + /* General WikiEditor stuff */ |
| 42 | + .wikiEditor-nodisplay { |
| 43 | + display: none !important; |
| 44 | + } |
| 45 | + .wikiEditor-tab { |
| 46 | + padding-left: 4em; |
| 47 | + } |
| 48 | + /* WikiEditor Templates */ |
| 49 | + .wikiEditor-templates .wikiEditor-template { |
| 50 | + color: silver; |
| 51 | + } |
| 52 | + /* WikiEditor TemplateEditor */ |
| 53 | + .wikiEditor-templateEditor .wikiEditor-template-text-shrunken{ |
| 54 | + height: 1px !important; |
| 55 | + width: 1px !important; |
| 56 | + overflow: hidden; |
| 57 | + float: right; |
| 58 | + } |
| 59 | + .wikiEditor-templateEditor .wikiEditor-template-text-visible{ |
| 60 | + padding: 0.5em 4px; |
| 61 | + padding-top: 1.25em; |
| 62 | + margin-top: -0.95em; |
| 63 | + background: #F3F3F3 url(../../images/wikiEditor/templateEditor/text-base.png) repeat-x scroll center top; |
| 64 | + display: block; |
| 65 | + width: 100%; |
| 66 | + border-bottom: solid 1px #cccccc; |
| 67 | + } |
| 68 | + .wikiEditor-templateEditor .wikiEditor-template { |
| 69 | + display: inline-block; |
| 70 | + font-size: 12px; |
| 71 | + } |
| 72 | + .wikiEditor-templateEditor .wikiEditor-template-name { |
| 73 | + cursor: pointer; |
| 74 | + vertical-align: -2px; |
| 75 | + display: inline-block; |
| 76 | + height: 16px; |
| 77 | + margin-bottom: -1px; |
| 78 | + margin-right: 2px; |
| 79 | + overflow: hidden; |
| 80 | + background: url( '../../images/wikiEditor/templateEditor/name-base.png' ) 0 0 repeat-x #e8e8e8; |
| 81 | + color: #000000; |
| 82 | + font-family: monospace; |
| 83 | + text-decoration: none; |
| 84 | + padding-left: 0.33em; |
| 85 | + line-height: 16px; |
| 86 | + } |
| 87 | + .wikiEditor-templateEditor .wikiEditor-template-expand { |
| 88 | + cursor: pointer; |
| 89 | + vertical-align: -2px; |
| 90 | + display: inline-block; |
| 91 | + margin-left: 2px; |
| 92 | + height: 16px; |
| 93 | + margin-bottom: -1px; |
| 94 | + line-height: 16px; |
| 95 | + overflow: hidden; |
| 96 | + width: 13px; |
| 97 | + background-position: 50%; |
| 98 | + } |
| 99 | + .wikiEditor-templateEditor .wikiEditor-template-dialog { |
| 100 | + cursor: pointer; |
| 101 | + vertical-align: -18%; |
| 102 | + display: inline-block; |
| 103 | + height: 16px; |
| 104 | + overflow: hidden; |
| 105 | + width: 22px; |
| 106 | + background-position: 50%; |
| 107 | + } |
| 108 | + .wikiEditor-templateEditor .wikiEditor-template-name:hover { |
| 109 | + text-decoration: underline; |
| 110 | + } |
| 111 | + .wikiEditor-templateEditor .wikiEditor-template-expanded .wikiEditor-template-expand { |
| 112 | + background-image: url(../../images/wikiEditor/templateEditor/collapse.png); |
| 113 | + } |
| 114 | + .wikiEditor-templateEditor .wikiEditor-template-expanded .wikiEditor-template-dialog { |
| 115 | + background-image: url(../../images/wikiEditor/templateEditor/dialog-expanded.png); |
| 116 | + } |
| 117 | + .wikiEditor-templateEditor .wikiEditor-template-collapsed .wikiEditor-template-expand { |
| 118 | + background-image: url(../../images/wikiEditor/templateEditor/expand.png); |
| 119 | + } |
| 120 | + .wikiEditor-templateEditor .wikiEditor-template-collapsed .wikiEditor-template-dialog { |
| 121 | + background-image: url(../../images/wikiEditor/templateEditor/dialog-collapsed.png); |
| 122 | + } |
| 123 | + .wikiEditor-templateEditor .wikiEditor-template-expanded { |
| 124 | + display: block; |
| 125 | + } |
| 126 | + .wikiEditor-templateEditor .wikiEditor-template .wikiEditor-template-text { |
| 127 | + |
| 128 | + } |
| 129 | + .wikiEditor-templateEditor .wikiEditor-template-end, .wikiEditor-template-start { |
| 130 | + color: blue; |
| 131 | + cursor: pointer; |
| 132 | + } |
| 133 | + </style> |
| 134 | +</head> |
| 135 | +<body></body> |
| 136 | +</html> |
Property changes on: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.html |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 137 | + native |
Index: trunk/extensions/WikiEditor/modules/Preview.js |
— | — | @@ -0,0 +1,12 @@ |
| 2 | +/* JavaScript for WikiEditor Preview module */ |
| 3 | + |
| 4 | +$j(document).ready( function() { |
| 5 | + // Check preferences for preview |
| 6 | + if ( !wgWikiEditorEnabledModules.preview ) { |
| 7 | + return true; |
| 8 | + } |
| 9 | + // Add the preview module |
| 10 | + if ( $j.fn.wikiEditor ) { |
| 11 | + $j( 'textarea#wpTextbox1' ).wikiEditor( 'addModule', 'preview' ); |
| 12 | + } |
| 13 | +}); |
Property changes on: trunk/extensions/WikiEditor/modules/Preview.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 14 | + native |
Index: trunk/extensions/WikiEditor/modules/TemplateEditor.js |
— | — | @@ -0,0 +1,16 @@ |
| 2 | +/* JavaScript for WikiEditor Template Editor module */ |
| 3 | + |
| 4 | +$j(document).ready( function() { |
| 5 | + // Check preferences for templateEditor |
| 6 | + if ( !wgWikiEditorEnabledModules.templateEditor ) { |
| 7 | + return true; |
| 8 | + } |
| 9 | + //disable if in template namespace |
| 10 | + if ( wgNamespaceNumber == 10 ) { |
| 11 | + return true; |
| 12 | + } |
| 13 | + // Add the templateEditor module |
| 14 | + if ( $j.fn.wikiEditor ) { |
| 15 | + $j( 'textarea#wpTextbox1' ).wikiEditor( 'addModule', 'templateEditor' ); |
| 16 | + } |
| 17 | +}); |
Property changes on: trunk/extensions/WikiEditor/modules/TemplateEditor.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 18 | + native |
Index: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.templates.js |
— | — | @@ -0,0 +1,69 @@ |
| 2 | +/* Templates Module for wikiEditor */ |
| 3 | +( function( $ ) { $.wikiEditor.modules.templates = { |
| 4 | + |
| 5 | +/** |
| 6 | + * Core Requirements |
| 7 | + */ |
| 8 | +'req': [ 'iframe' ], |
| 9 | +/** |
| 10 | + * Object Templates |
| 11 | + */ |
| 12 | +'tpl': { |
| 13 | + 'marker': { |
| 14 | + 'type': 'template', |
| 15 | + 'anchor': 'wrap', |
| 16 | + 'skipDivision': 'realchange', |
| 17 | + 'afterWrap': function( node ) { |
| 18 | + $( node ).addClass( 'wikiEditor-template' ); |
| 19 | + }, |
| 20 | + 'getAnchor': function( ca1, ca2 ) { |
| 21 | + return $( ca1.parentNode ).is( '.wikiEditor-template' ) ? ca1.parentNode : null; |
| 22 | + } |
| 23 | + } |
| 24 | +}, |
| 25 | +/** |
| 26 | + * Event handlers |
| 27 | + */ |
| 28 | +'evt': { |
| 29 | + 'mark': function( context, event ) { |
| 30 | + // The markers returned by this function are skipped on realchange, so don't regenerate them in that case |
| 31 | + if ( context.modules.highlight.currentScope == 'realchange' ) { |
| 32 | + return; |
| 33 | + } |
| 34 | + // Get references to the markers and tokens from the current context |
| 35 | + var markers = context.modules.highlight.markers; |
| 36 | + var tokens = context.modules.highlight.tokenArray; |
| 37 | + // Use depth-tracking to extract top-level templates from tokens |
| 38 | + var depth = 0, bias, start; |
| 39 | + for ( var i in tokens ) { |
| 40 | + depth += ( bias = tokens[i].label == 'TEMPLATE_BEGIN' ? 1 : ( tokens[i].label == 'TEMPLATE_END' ? -1 : 0 ) ); |
| 41 | + if ( bias > 0 && depth == 1 ) { |
| 42 | + // Top-level opening - use offset as start |
| 43 | + start = tokens[i].offset; |
| 44 | + } else if ( bias < 0 && depth == 0 ) { |
| 45 | + // Top-level closing - use offset as end |
| 46 | + markers[markers.length] = $.extend( |
| 47 | + { 'context': context, 'start': start, 'end': tokens[i].offset }, |
| 48 | + $.wikiEditor.modules.templates.tpl.marker |
| 49 | + ); |
| 50 | + } |
| 51 | + if ( depth < 0 ) { |
| 52 | + depth = 0; |
| 53 | + } |
| 54 | + } |
| 55 | + } |
| 56 | +}, |
| 57 | +'exp': [ |
| 58 | + { 'regex': /{{/, 'label': "TEMPLATE_BEGIN" }, |
| 59 | + { 'regex': /}}/, 'label': "TEMPLATE_END", 'markAfter': true } |
| 60 | +], |
| 61 | +/** |
| 62 | + * Internally used functions |
| 63 | + */ |
| 64 | +'fn': { |
| 65 | + 'create': function( context, config ) { |
| 66 | + // Do some stuff here... |
| 67 | + } |
| 68 | +} |
| 69 | + |
| 70 | +}; } ) ( jQuery ); |
Property changes on: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.templates.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 71 | + native |
Index: trunk/extensions/WikiEditor/modules/Toc.js |
— | — | @@ -0,0 +1,18 @@ |
| 2 | +/* JavaScript for WikiEditor Toc module */ |
| 3 | + |
| 4 | +$j(document).ready( function() { |
| 5 | + // Check preferences for toolbar |
| 6 | + if ( !wgWikiEditorPreferences || !( wgWikiEditorPreferences.toc && wgWikiEditorPreferences.toc.enable ) ) { |
| 7 | + return true; |
| 8 | + } |
| 9 | + // Add the toc module |
| 10 | + if ( $j.fn.wikiEditor ) { |
| 11 | + mw.usability.load( [ '$j.ui','$j.ui.draggable', '$j.ui.resizable' ], function() { |
| 12 | + // load the module and let it know were ready to go |
| 13 | + $j( '#wpTextbox1' ) |
| 14 | + .wikiEditor( 'addModule', { 'toc' : { 'rtl' : ( $j( 'body' ).is( '.rtl' ) ) } } ) |
| 15 | + //FIXME - should move the ready handler code to the create function so this isn't necissary |
| 16 | + .data( 'wikiEditor-context' ).fn.trigger( 'ready' ); |
| 17 | + } ); |
| 18 | + } |
| 19 | +}); |
Property changes on: trunk/extensions/WikiEditor/modules/Toc.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 20 | + native |
Index: trunk/extensions/WikiEditor/modules/wikiEditor.css |
— | — | @@ -0,0 +1,134 @@ |
| 2 | +/* wikiEditor plugin */ |
| 3 | + |
| 4 | +/* This ID (#editform) could change in MediaWiki */ |
| 5 | +form#editform { |
| 6 | + margin: 0; |
| 7 | + padding: 0; |
| 8 | +} |
| 9 | +/* These IDs (#wpSummaryLabel and #wpSummary) could change in MediaWiki */ |
| 10 | +#wpSummary, #wpSummaryLabel { |
| 11 | + margin-bottom: 1em; |
| 12 | +} |
| 13 | +/* This ID (#wpTextbox1) could change in MediaWiki */ |
| 14 | +.wikiEditor-ui textarea#wpTextbox1 { |
| 15 | + border: none; |
| 16 | + padding: 0; |
| 17 | + margin: -1px; |
| 18 | + line-height: 1.5em; |
| 19 | +} |
| 20 | +.wikiEditor-ui .wikiEditor-ui-text > textarea#wpTextbox1 { |
| 21 | + margin: 0; |
| 22 | +} |
| 23 | +.wikiEditor-ui { |
| 24 | + float: left; |
| 25 | + position: relative; |
| 26 | + clear: both; |
| 27 | + width: 100%; |
| 28 | + background-color: #E0EEf7; |
| 29 | + border: solid silver 1px; |
| 30 | +} |
| 31 | +body.rtl .wikiEditor-ui { |
| 32 | + float: right; |
| 33 | +} |
| 34 | +.wikiEditor-ui .wikiEditor-ui-bottom { |
| 35 | + |
| 36 | +} |
| 37 | +.wikiEditor-ui .wikiEditor-ui-text { |
| 38 | + line-height: 0; |
| 39 | +} |
| 40 | +.wikiEditor-ui .wikiEditor-ui-top { |
| 41 | + position: relative; |
| 42 | + border-bottom: solid silver 1px; |
| 43 | +} |
| 44 | +.wikiEditor-ui .wikiEditor-ui-left { |
| 45 | + float: left; |
| 46 | + width: 100%; |
| 47 | +} |
| 48 | +body.rtl .wikiEditor-ui .wikiEditor-ui-left { |
| 49 | + float: right; |
| 50 | +} |
| 51 | +.wikiEditor-ui .wikiEditor-ui-right { |
| 52 | + float: right; |
| 53 | + background: #F3F3F3; |
| 54 | + overflow: hidden; |
| 55 | +} |
| 56 | +body.rtl .wikiEditor-ui .wikiEditor-ui-right { |
| 57 | + float: left; |
| 58 | +} |
| 59 | +.wikiEditor-wikitext { |
| 60 | + float: left; |
| 61 | + width: 100%; |
| 62 | +} |
| 63 | +.wikiEditor-ui-controls { |
| 64 | + float: left; |
| 65 | + width: 100%; |
| 66 | + background-color: white; |
| 67 | + margin-top: -1px; |
| 68 | + border-bottom: solid 1px silver; |
| 69 | +} |
| 70 | +.wikiEditor-ui-tabs { |
| 71 | + float: left; |
| 72 | + height: 2.5em; |
| 73 | + margin-left: -1px; |
| 74 | + background-color: white; |
| 75 | + border-left: solid 1px silver; |
| 76 | + border-top: solid 1px silver; |
| 77 | +} |
| 78 | +.wikiEditor-ui-buttons { |
| 79 | + float: right; |
| 80 | + height: 2.5em; |
| 81 | + margin-right: -1px; |
| 82 | + background-color: white; |
| 83 | + padding-left: 1em; |
| 84 | + border-top: solid 1px white; |
| 85 | +} |
| 86 | +.wikiEditor-ui-buttons button { |
| 87 | + margin-left: 0.5em; |
| 88 | +} |
| 89 | +.wikiEditor-ui-tabs div { |
| 90 | + float: left; |
| 91 | + height: 2.5em; |
| 92 | + background-color: #f3f3f3; |
| 93 | + border-right: solid 1px silver; |
| 94 | + border-bottom: solid 1px silver; |
| 95 | +} |
| 96 | +.wikiEditor-ui-tabs div.current { |
| 97 | + border-bottom: solid 1px white; |
| 98 | + background-color: white; |
| 99 | +} |
| 100 | +.wikiEditor-ui-tabs div a { |
| 101 | + display: inline-block; |
| 102 | + padding: 0 0.75em; |
| 103 | + line-height: 2.5em; |
| 104 | + color: #0645AD; |
| 105 | +} |
| 106 | +.wikiEditor-ui-tabs div.current a { |
| 107 | + color: #333333; |
| 108 | +} |
| 109 | +.wikiEditor-ui-tabs div.current a:hover { |
| 110 | + text-decoration: none; |
| 111 | +} |
| 112 | + |
| 113 | +.wikiEditor-view-wikitext { |
| 114 | + line-height: 1em; |
| 115 | +} |
| 116 | +.wikiEditor-ui-loading { |
| 117 | + background: #f3f3f3; |
| 118 | + z-index: 10; |
| 119 | + position: absolute; |
| 120 | + top: 0; |
| 121 | + left: 0; |
| 122 | + text-align: center; |
| 123 | + height: 100%; |
| 124 | + width: 100%; |
| 125 | + border: 1px solid silver; |
| 126 | + margin: -1px; |
| 127 | +} |
| 128 | +.wikiEditor-ui-loading span { |
| 129 | + display: block; |
| 130 | + height: 24px; |
| 131 | + width: 24px; |
| 132 | + background: url( ../images/wikiEditor/toolbar/loading.gif ) 0 0 no-repeat; |
| 133 | + text-indent: -9999px; |
| 134 | + margin: 0 auto; |
| 135 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/WikiEditor/modules/wikiEditor.css |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 136 | + native |
Index: trunk/extensions/WikiEditor/modules/wikiEditor.previewDialog.css |
— | — | @@ -0,0 +1,28 @@ |
| 2 | +#wikiEditor-0-preview-dialog .wikiEditor-ui-loading { |
| 3 | + background: #f3f3f3; |
| 4 | + z-index: 10; |
| 5 | + position: absolute; |
| 6 | + left: 0; |
| 7 | + text-align: center; |
| 8 | + height: 100%; |
| 9 | + width: 100%; |
| 10 | + overflow: hidden; |
| 11 | + border: none; |
| 12 | +} |
| 13 | +#wikiEditor-0-preview-dialog .wikiEditor-ui-loading span { |
| 14 | + display: block; |
| 15 | + height: 24px; |
| 16 | + width: 24px; |
| 17 | + background: url( ../images/wikiEditor/toolbar/loading.gif ) 0 0 no-repeat; |
| 18 | + text-indent: -9999px; |
| 19 | + margin: 50px auto; |
| 20 | +} |
| 21 | +.ui-dialog .ui-dialog-buttonpane { |
| 22 | + margin: 0 !important; |
| 23 | +} |
| 24 | +.wikiEditor-preview-dialog-contents { |
| 25 | + font-size: 0.9em !important; |
| 26 | +} |
| 27 | +.wikiEditor-preview-dialog-contents #firstHeading { |
| 28 | + font-size: 2.1em; |
| 29 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/WikiEditor/modules/wikiEditor.previewDialog.css |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 30 | + native |
Index: trunk/extensions/WikiEditor/modules/wikiEditor.toolbar.css |
— | — | @@ -0,0 +1,408 @@ |
| 2 | +/* wikiEditor toolbar module */ |
| 3 | + |
| 4 | +.wikiEditor-ui-toolbar { |
| 5 | + position: relative; |
| 6 | + width: 100%; |
| 7 | +} |
| 8 | + |
| 9 | +/* Expandable Sections */ |
| 10 | +.wikiEditor-ui-toolbar .sections { |
| 11 | + float: left; |
| 12 | + width: 100%; |
| 13 | + clear: both; |
| 14 | + height: 0; |
| 15 | +} |
| 16 | +body.rtl .wikiEditor-ui-toolbar .sections { |
| 17 | + float: right; |
| 18 | +} |
| 19 | +.wikiEditor-ui-toolbar .sections .section { |
| 20 | + display: none; |
| 21 | + float: left; |
| 22 | + width: 100%; |
| 23 | + border-top: solid 1px #DDDDDD; |
| 24 | + background-color: #E0EEf7; |
| 25 | +} |
| 26 | +.wikiEditor-ui-toolbar { |
| 27 | + background-image: url(../images/wikiEditor/toolbar/base.png?1); |
| 28 | + background-position: left top; |
| 29 | + background-repeat: repeat-x; |
| 30 | +} |
| 31 | +/* |
| 32 | +.wikiEditor-ui-toolbar .toolbar { |
| 33 | + background-image: url(../images/wikiEditor/toolbar/base.png?1); |
| 34 | + background-position: left top; |
| 35 | +} |
| 36 | +*/ |
| 37 | +body.rtl .wikiEditor-ui-toolbar .sections .section { |
| 38 | + float: right; |
| 39 | +} |
| 40 | +/* Gets overridden when the section div is in class loading - see below */ |
| 41 | +.wikiEditor-ui-toolbar .sections div .spinner { |
| 42 | + display: none; |
| 43 | +} |
| 44 | +.wikiEditor-ui-toolbar .sections .loading .spinner { |
| 45 | + display: block; |
| 46 | + background-image: url(../images/wikiEditor/toolbar/loading.gif?2); |
| 47 | + background-position: left center; |
| 48 | + background-repeat: no-repeat; |
| 49 | + padding-left: 32px; |
| 50 | + margin-left: 0.5em; |
| 51 | + height: 32px; |
| 52 | + float: left; |
| 53 | + color: #666666; |
| 54 | +} |
| 55 | +body.rtl .wikiEditor-ui-toolbar .sections .loading .spinner { |
| 56 | + background-position: right center; |
| 57 | + padding-left: 0; |
| 58 | + padding-right: 32px; |
| 59 | + margin-left: 0; |
| 60 | + margin-right: 0.5em; |
| 61 | + float: right; |
| 62 | +} |
| 63 | +/* Top Level Containers */ |
| 64 | +.wikiEditor-ui-toolbar .tabs, |
| 65 | +.wikiEditor-ui-toolbar .section-main { |
| 66 | + position: relative; |
| 67 | + float: left; |
| 68 | + height: 26px; |
| 69 | +} |
| 70 | +body.rtl .wikiEditor-ui-toolbar .tabs, |
| 71 | +body.rtl .wikiEditor-ui-toolbar .section-main { |
| 72 | + float: right; |
| 73 | +} |
| 74 | +/* Groups */ |
| 75 | +.wikiEditor-ui-toolbar .group { |
| 76 | + float: left; |
| 77 | + height: 26px; |
| 78 | + padding-right: 6px; |
| 79 | + border-right: solid 1px #DDDDDD; |
| 80 | + margin: 3px; |
| 81 | +} |
| 82 | +body.rtl .wikiEditor-ui-toolbar .group { |
| 83 | + float: right; |
| 84 | + padding-right: 0; |
| 85 | + padding-left: 6px; |
| 86 | + border-right: none; |
| 87 | + border-left: solid 1px #DDDDDD; |
| 88 | +} |
| 89 | +.wikiEditor-ui-toolbar .group-search { |
| 90 | + float: right; |
| 91 | + padding: 0 0 0 6px; |
| 92 | + border-right: none; |
| 93 | + border-left: 1px solid #DDDDDD; |
| 94 | +} |
| 95 | +.wikiEditor-ui-toolbar .group-insert { |
| 96 | + border-right: none; |
| 97 | +} |
| 98 | +body.rtl .wikiEditor-ui-toolbar .group-search { |
| 99 | + float: left; |
| 100 | + padding: 0 6px 0 0; |
| 101 | + border-left: none; |
| 102 | + border-right: 1px solid #DDDDDD; |
| 103 | +} |
| 104 | +body.rtl .wikiEditor-ui-toolbar .group-insert { |
| 105 | + border-left: none; |
| 106 | +} |
| 107 | +/* Sprited Buttons */ |
| 108 | +.wikiEditor-toolbar-spritedButton { |
| 109 | + background: url(../images/wikiEditor/toolbar/button-sprite.png?1) 0 0 no-repeat; |
| 110 | + display: block; |
| 111 | + float: left; |
| 112 | + height: 22px; |
| 113 | + text-indent: -9999px; |
| 114 | + width: 22px; |
| 115 | + padding: 2px; |
| 116 | + cursor: pointer; |
| 117 | + overflow: hidden; |
| 118 | +} |
| 119 | +/* Tabs */ |
| 120 | +.wikiEditor-ui-toolbar .tabs { |
| 121 | + list-style: none; |
| 122 | + margin: 3px; |
| 123 | +} |
| 124 | +.wikiEditor-ui-toolbar .tabs span.tab { |
| 125 | + display: inline-block; |
| 126 | + float: left; |
| 127 | + line-height: 26px; |
| 128 | +} |
| 129 | +/* IGNORED BY IE6 */ |
| 130 | +.wikiEditor-ui-toolbar .tabs > span.tab { |
| 131 | + display: block; |
| 132 | +} |
| 133 | +/* IGNORED BY IE6 */ |
| 134 | +body.rtl .wikiEditor-ui-toolbar .tabs > span.tab { |
| 135 | + float: right; |
| 136 | +} |
| 137 | +.wikiEditor-ui-toolbar .tabs span.tab a, |
| 138 | +.wikiEditor-ui-toolbar .tabs span.tab a:visited { |
| 139 | + display: inline-block; |
| 140 | + float: left; |
| 141 | + padding-left: 18px; |
| 142 | + padding-right: 12px; |
| 143 | + height: 26px; |
| 144 | + cursor: pointer; |
| 145 | + color: #0645ad; |
| 146 | + background-image: url(../images/wikiEditor/toolbar/arrow-right.png?1); |
| 147 | + background-position: left center; |
| 148 | + background-repeat: no-repeat; |
| 149 | +} |
| 150 | +body.rtl .wikiEditor-ui-toolbar .tabs span.tab a, |
| 151 | +body.rtl .wikiEditor-ui-toolbar .tabs span.tab a:visited { |
| 152 | + padding-left: 12px; |
| 153 | + padding-right: 18px; |
| 154 | + background-image: url(../images/wikiEditor/toolbar/arrow-left.png?1); |
| 155 | + background-position: right center; |
| 156 | +} |
| 157 | +/* IGNORED BY IE6 */ |
| 158 | +body.rtl .wikiEditor-ui-toolbar .tabs > span.tab > a, |
| 159 | +body.rtl .wikiEditor-ui-toolbar .tabs > pan.tab > a:visited { |
| 160 | + float: right; |
| 161 | +} |
| 162 | +.wikiEditor-ui-toolbar .tabs span.tab a.current, |
| 163 | +.wikiEditor-ui-toolbar .tabs span.tab a.current:visited { |
| 164 | + color: #333333; |
| 165 | + background-image: url(../images/wikiEditor/toolbar/arrow-down.png?1); |
| 166 | +} |
| 167 | +body.rtl .wikiEditor-ui-toolbar .tabs span.tab a.current, |
| 168 | +body.rtl .wikiEditor-ui-toolbar .tabs span.tab a.current:visited { |
| 169 | + background-image: url(../images/wikiEditor/toolbar/arrow-down.png?1); |
| 170 | +} |
| 171 | +.wikiEditor-ui-toolbar .tabs span.tab a.current:hover { |
| 172 | + text-decoration: none; |
| 173 | +} |
| 174 | +.wikiEditor-ui-toolbar .tabs span.tab a.loading { |
| 175 | + background-image: url(../images/wikiEditor/toolbar/loading-small.gif?1) !important; |
| 176 | +} |
| 177 | +/* Toolbar */ |
| 178 | +.wikiEditor-ui-toolbar .group .label { |
| 179 | + float: left; |
| 180 | + border: 0px; |
| 181 | + height: 22px; |
| 182 | + line-height: 22px; |
| 183 | + margin: 2px; |
| 184 | + margin-left: 5px; |
| 185 | + margin-right: 8px; |
| 186 | + color: #777777; |
| 187 | + cursor: default; |
| 188 | +} |
| 189 | +/* IGNORED BY IE6 */ |
| 190 | +body.rtl .wikiEditor-ui-toolbar .group > .label { |
| 191 | + float: right; |
| 192 | + margin-left: 8px; |
| 193 | + margin-right: 5px; |
| 194 | +} |
| 195 | +.wikiEditor-ui-toolbar .group img.tool { |
| 196 | + float: left; |
| 197 | + border: 0px; |
| 198 | + height: 22px; |
| 199 | + width: 22px; |
| 200 | + padding: 2px; |
| 201 | + cursor: pointer; |
| 202 | +} |
| 203 | +/* IGNORED BY IE6 */ |
| 204 | +body.rtl .wikiEditor-ui-toolbar .group > img.tool { |
| 205 | + float: right; |
| 206 | +} |
| 207 | +.wikiEditor-ui-toolbar .group .tool-select { |
| 208 | + float: left; |
| 209 | + margin: 2px; |
| 210 | + height: 22px; |
| 211 | + cursor: pointer; |
| 212 | + border: solid 1px silver; |
| 213 | + padding: 0; |
| 214 | + margin-right: 0; |
| 215 | + cursor: pointer; |
| 216 | + background-color: #ffffff; |
| 217 | +} |
| 218 | +/* IGNORED BY IE6 */ |
| 219 | +body.rtl .wikiEditor-ui-toolbar .group > .tool-select { |
| 220 | + float: right; |
| 221 | +} |
| 222 | +.wikiEditor-ui-toolbar .group .tool-select .label { |
| 223 | + background-image: url(../images/wikiEditor/toolbar/arrow-down.png?1); |
| 224 | + background-position: center right; |
| 225 | + background-repeat: no-repeat; |
| 226 | + padding: 0; |
| 227 | + margin: 0; |
| 228 | + padding-left: 4px; |
| 229 | + padding-right: 22px; |
| 230 | + margin-right: 4px; |
| 231 | + cursor: pointer; |
| 232 | + text-decoration: none; |
| 233 | + color: #333333; |
| 234 | +} |
| 235 | +body.rtl .wikiEditor-ui-toolbar .group .tool-select .label { |
| 236 | + background-position: center left; |
| 237 | + padding-right: 4px; |
| 238 | + padding-left: 22px; |
| 239 | + margin-left: 4px; |
| 240 | + margin-right: 0; |
| 241 | +} |
| 242 | +body.rtl .wikiEditor-ui-toolbar .group .tool-select .menu { |
| 243 | + clear: both; |
| 244 | +} |
| 245 | +.wikiEditor-ui-toolbar .group .tool-select .menu .options { |
| 246 | + position: absolute; |
| 247 | + display: none; |
| 248 | + margin-left: -1px; |
| 249 | + border: solid 1px silver; |
| 250 | + background-color: #ffffff; |
| 251 | +} |
| 252 | +body.rtl .wikiEditor-ui-toolbar .group .tool-select .menu { |
| 253 | + margin-left: -1px; |
| 254 | + margin-right: -1px; |
| 255 | +} |
| 256 | +/* IGNORED BY IE6 */ |
| 257 | +.wikiEditor-ui-toolbar .group .tool-select .options { |
| 258 | + margin-top: 22px; |
| 259 | +} |
| 260 | +.wikiEditor-ui-toolbar .group .tool-select .options .option { |
| 261 | + display: block; |
| 262 | + padding: 0.5em; |
| 263 | + text-decoration: none; |
| 264 | + color: black; |
| 265 | + white-space: nowrap; |
| 266 | +} |
| 267 | +.wikiEditor-ui-toolbar .group .tool-select .options .option:hover { |
| 268 | + background-color: #E0EEf7; |
| 269 | +} |
| 270 | +.wikiEditor-ui-toolbar .group .tool-select .options .option[rel=heading-2] { |
| 271 | + font-size: 150%; |
| 272 | + font-weight: normal; |
| 273 | +} |
| 274 | +.wikiEditor-ui-toolbar .group .tool-select .options .option[rel=heading-3] { |
| 275 | + font-size: 132%; |
| 276 | + font-weight: normal; |
| 277 | +} |
| 278 | +.wikiEditor-ui-toolbar .group .tool-select .options .option[rel=heading-4] { |
| 279 | + font-size: 116%; |
| 280 | + font-weight: normal; |
| 281 | +} |
| 282 | +.wikiEditor-ui-toolbar .group .tool-select .options .option[rel=heading-5] { |
| 283 | + font-size: 100%; |
| 284 | + font-weight: bold; |
| 285 | +} |
| 286 | +/* Booklet */ |
| 287 | +.wikiEditor-ui-toolbar .booklet .index { |
| 288 | + float: left; |
| 289 | + width: 20%; |
| 290 | + height: 125px; |
| 291 | + overflow: auto; |
| 292 | +} |
| 293 | +body.rtl .wikiEditor-ui-toolbar .booklet .index { |
| 294 | + float: right; |
| 295 | +} |
| 296 | +.wikiEditor-ui-toolbar .booklet .index div { |
| 297 | + padding: 4px; |
| 298 | + padding-left: 6px; |
| 299 | + cursor: pointer; |
| 300 | + color: #0645ad; |
| 301 | +} |
| 302 | +body.rtl .wikiEditor-ui-toolbar .booklet .index div { |
| 303 | + padding-left: 4px; |
| 304 | + padding-right: 6px; |
| 305 | +} |
| 306 | +.wikiEditor-ui-toolbar .booklet .index .current { |
| 307 | + background-color: #FAFAFA; |
| 308 | + color: #333333; |
| 309 | + cursor: default; |
| 310 | +} |
| 311 | +.wikiEditor-ui-toolbar .booklet .pages { |
| 312 | + float: right; |
| 313 | + width: 80%; |
| 314 | + height: 125px; |
| 315 | + overflow: auto; |
| 316 | + background-color: #FAFAFA; |
| 317 | +} |
| 318 | +body.rtl .wikiEditor-ui-toolbar .booklet .pages { |
| 319 | + float: left; |
| 320 | +} |
| 321 | +/* Help Pages */ |
| 322 | +.wikiEditor-ui-toolbar .page-table table { |
| 323 | + padding-left: 5px; |
| 324 | + padding-right: 5px; |
| 325 | + background: none; |
| 326 | +} |
| 327 | +.wikiEditor-ui-toolbar .page-table th { |
| 328 | + color: #999999; |
| 329 | +} |
| 330 | +.wikiEditor-ui-toolbar .page-table td { |
| 331 | + color: black; |
| 332 | + border-top: solid 1px #EEEEEE; |
| 333 | +} |
| 334 | +.wikiEditor-ui-toolbar .page-table th, |
| 335 | +.wikiEditor-ui-toolbar .page-table td { |
| 336 | + text-align: left; |
| 337 | + padding: 5px; |
| 338 | + margin: 0px; |
| 339 | +} |
| 340 | +body.rtl .wikiEditor-ui-toolbar .page-table th, |
| 341 | +body.rtl .wikiEditor-ui-toolbar .page-table td { |
| 342 | + text-align: right; |
| 343 | +} |
| 344 | +.wikiEditor-ui-toolbar .section-help .page-table td.cell-syntax, |
| 345 | +.wikiEditor-ui-toolbar .section-help .page-table td.syntax { |
| 346 | + font-family: monospace; |
| 347 | +} |
| 348 | +.wikiEditor-ui-toolbar .section-help .page-table td.syntax, |
| 349 | +.wikiEditor-ui-toolbar .section-help .page-table td.cell-syntax, |
| 350 | +.wikiEditor-ui-toolbar .section-help .page-table td.cell-result, |
| 351 | +.wikiEditor-ui-toolbar .section-help .page-table td.result { |
| 352 | + width: 40%; |
| 353 | +} |
| 354 | +.wikiEditor-ui-toolbar .section-help .page-table td.description, |
| 355 | +.wikiEditor-ui-toolbar .section-help .page-table td.description { |
| 356 | + width: 20%; |
| 357 | +} |
| 358 | +/* Characters Pages */ |
| 359 | +.wikiEditor-ui-toolbar .page-characters div span { |
| 360 | + border: solid 1px #DDDDDD; |
| 361 | + padding: 5px; |
| 362 | + padding-left: 8px; |
| 363 | + padding-right: 8px; |
| 364 | + margin-left: 5px; |
| 365 | + margin-top: 5px; |
| 366 | + height: 1em; |
| 367 | + float: left; |
| 368 | + display: block; |
| 369 | + color: black; |
| 370 | + text-decoration: none; |
| 371 | + cursor: pointer; |
| 372 | + font-family: monospace; |
| 373 | + font-size: 1.25em; |
| 374 | +} |
| 375 | +body.rtl .wikiEditor-ui-toolbar .page-characters > div > span, |
| 376 | +.wikiEditor-ui-toolbar .page-characters div[dir=rtl] span { |
| 377 | + direction: rtl; |
| 378 | + float: right; |
| 379 | + margin-left: 0; |
| 380 | + margin-right: 5px; |
| 381 | +} |
| 382 | +.wikiEditor-ui-toolbar .page-characters div span:hover { |
| 383 | + background-color: white; |
| 384 | + text-decoration: none; |
| 385 | + border-color: #a8d7f9; |
| 386 | +} |
| 387 | +.ui-widget table td.wikieditor-toolbar-table-preview-wrapper span { |
| 388 | + padding: 4px 6px 0px; |
| 389 | + display: block; |
| 390 | +} |
| 391 | +.ui-widget table .wikieditor-toolbar-table-preview-frame { |
| 392 | + width: 340px; |
| 393 | + background: #fff; |
| 394 | + padding: 10px; |
| 395 | + overflow: hidden; |
| 396 | + display: block; |
| 397 | + position: relative; |
| 398 | +} |
| 399 | +.ui-widget table .wikieditor-toolbar-table-preview-content { |
| 400 | + width: 375px; |
| 401 | + display: block; |
| 402 | +} |
| 403 | +.ui-widget table .wikieditor-toolbar-table-preview { |
| 404 | + width: 340px; |
| 405 | +} |
| 406 | +.ui-widget table td.wikieditor-toolbar-table-preview-wrapper { |
| 407 | + background: #e5e5e5; |
| 408 | + padding: 10px; |
| 409 | +} |
Property changes on: trunk/extensions/WikiEditor/modules/wikiEditor.toolbar.css |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 410 | + native |
Index: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.previewDialog.js |
— | — | @@ -0,0 +1,130 @@ |
| 2 | +/* Publish module for wikiEditor */ |
| 3 | +( function( $ ) { $.wikiEditor.modules.previewDialog = { |
| 4 | + |
| 5 | +/** |
| 6 | + * Compatability map |
| 7 | + */ |
| 8 | +'browsers': { |
| 9 | + // Left-to-right languages |
| 10 | + 'ltr': { |
| 11 | + 'msie': [['>=', 7]], |
| 12 | + 'firefox': [['>=', 3]], |
| 13 | + 'opera': [['>=', 9.6]], |
| 14 | + 'safari': [['>=', 4]] |
| 15 | + }, |
| 16 | + // Right-to-left languages |
| 17 | + 'rtl': { |
| 18 | + 'msie': [['>=', 8]], |
| 19 | + 'firefox': [['>=', 3]], |
| 20 | + 'opera': [['>=', 9.6]], |
| 21 | + 'safari': [['>=', 4]] |
| 22 | + } |
| 23 | +}, |
| 24 | +/** |
| 25 | + * Internally used functions |
| 26 | + */ |
| 27 | +fn: { |
| 28 | + /** |
| 29 | + * Creates a publish module within a wikiEditor |
| 30 | + * @param context Context object of editor to create module in |
| 31 | + * @param config Configuration object to create module from |
| 32 | + */ |
| 33 | + create: function( context, config ) { |
| 34 | + // Build the dialog behind the Publish button |
| 35 | + var dialogID = 'wikiEditor-' + context.instance + '-preview-dialog'; |
| 36 | + $.wikiEditor.modules.dialogs.fn.create( |
| 37 | + context, |
| 38 | + { |
| 39 | + preview: { |
| 40 | + id: dialogID, |
| 41 | + titleMsg: 'wikieditor-preview-tab', |
| 42 | + html: '\ |
| 43 | + <div class="wikiEditor-ui-loading"><span></span></div>\ |
| 44 | + <div class="wikiEditor-preview-dialog-contents"></div>\ |
| 45 | + ', |
| 46 | + init: function() { |
| 47 | + }, |
| 48 | + dialog: { |
| 49 | + buttons: { |
| 50 | + 'wikieditor-publish-dialog-publish': function() { |
| 51 | + var minorChecked = $( '#wikiEditor-' + context.instance + |
| 52 | + '-dialog-minor' ).is( ':checked' ) ? |
| 53 | + 'checked' : ''; |
| 54 | + var watchChecked = $( '#wikiEditor-' + context.instance + |
| 55 | + '-dialog-watch' ).is( ':checked' ) ? |
| 56 | + 'checked' : ''; |
| 57 | + $( '#wpMinoredit' ).attr( 'checked', minorChecked ); |
| 58 | + $( '#wpWatchthis' ).attr( 'checked', watchChecked ); |
| 59 | + $( '#wpSummary' ).val( $j( '#wikiEditor-' + context.instance + |
| 60 | + '-dialog-summary' ).val() ); |
| 61 | + $( '#editform' ).submit(); |
| 62 | + }, |
| 63 | + 'wikieditor-publish-dialog-goback': function() { |
| 64 | + $(this).dialog( 'close' ); |
| 65 | + } |
| 66 | + }, |
| 67 | + resizable: false, |
| 68 | + height: $( 'body' ).height() - 100, |
| 69 | + width: $( 'body' ).width() - 300, |
| 70 | + position: ['center', 'top'], |
| 71 | + open: function() { |
| 72 | + // Gets the latest copy of the wikitext |
| 73 | + var wikitext = context.fn.getContents(); |
| 74 | + var $dialog = $( '#' + dialogID ); |
| 75 | + $dialog |
| 76 | + .css( 'position', 'relative' ) |
| 77 | + .css( 'height', $( 'body' ).height() - 200 ) |
| 78 | + .parent() |
| 79 | + .css( 'top', '25px' ); |
| 80 | + // $dialog.dialog( 'option', 'width', $( 'body' ).width() - 300 ); |
| 81 | + // Aborts when nothing has changed since the last preview |
| 82 | + if ( context.modules.preview.previewText == wikitext ) { |
| 83 | + return; |
| 84 | + } |
| 85 | + |
| 86 | + $dialog.find( '.wikiEditor-preview-dialog-contents' ).empty(); |
| 87 | + $dialog.find( '.wikiEditor-ui-loading' ).show(); |
| 88 | + $.post( |
| 89 | + wgScriptPath + '/api.php', |
| 90 | + { |
| 91 | + 'action': 'parse', |
| 92 | + 'title': wgPageName, |
| 93 | + 'text': wikitext, |
| 94 | + 'prop': 'text', |
| 95 | + 'pst': '', |
| 96 | + 'format': 'json' |
| 97 | + }, |
| 98 | + function( data ) { |
| 99 | + if ( |
| 100 | + typeof data.parse == 'undefined' || |
| 101 | + typeof data.parse.text == 'undefined' || |
| 102 | + typeof data.parse.text['*'] == 'undefined' |
| 103 | + ) { |
| 104 | + return; |
| 105 | + } |
| 106 | + context.modules.preview.previewText = wikitext; |
| 107 | + $dialog.find( '.wikiEditor-ui-loading' ).hide(); |
| 108 | + $dialog.find( '.wikiEditor-preview-dialog-contents' ) |
| 109 | + .html( '<h1 class="firstHeading" id="firstHeading">'+wgTitle+'</h1>' + |
| 110 | + data.parse.text['*'] ) |
| 111 | + .find( 'a:not([href^=#])' ).click( function() { return false; } ); |
| 112 | + }, |
| 113 | + 'json' |
| 114 | + ); |
| 115 | + } |
| 116 | + }, |
| 117 | + resizeme: false |
| 118 | + } |
| 119 | + } |
| 120 | + ); |
| 121 | + context.fn.addButton( { |
| 122 | + 'captionMsg': 'wikieditor-preview-tab', |
| 123 | + 'action': function() { |
| 124 | + context.$textarea.wikiEditor( 'openDialog', 'preview'); |
| 125 | + return false; |
| 126 | + } |
| 127 | + } ); |
| 128 | + } |
| 129 | +} |
| 130 | + |
| 131 | +}; } )( jQuery ); |
Property changes on: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.previewDialog.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 132 | + native |
Index: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.js |
— | — | @@ -0,0 +1,1894 @@ |
| 2 | +/** |
| 3 | + * This plugin provides a way to build a wiki-text editing user interface around a textarea. |
| 4 | + * |
| 5 | + * @example To intialize without any modules: |
| 6 | + * $j( 'div#edittoolbar' ).wikiEditor(); |
| 7 | + * |
| 8 | + * @example To initialize with one or more modules, or to add modules after it's already been initialized: |
| 9 | + * $j( 'textarea#wpTextbox1' ).wikiEditor( 'addModule', 'toolbar', { ... config ... } ); |
| 10 | + * |
| 11 | + */ |
| 12 | +( function( $ ) { |
| 13 | + |
| 14 | +/** |
| 15 | + * Global static object for wikiEditor that provides generally useful functionality to all modules and contexts. |
| 16 | + */ |
| 17 | +$.wikiEditor = { |
| 18 | + /** |
| 19 | + * For each module that is loaded, static code shared by all instances is loaded into this object organized by |
| 20 | + * module name. The existance of a module in this object only indicates the module is available. To check if a |
| 21 | + * module is in use by a specific context check the context.modules object. |
| 22 | + */ |
| 23 | + 'modules': {}, |
| 24 | + /** |
| 25 | + * In some cases like with the iframe's HTML file, it's convienent to have a lookup table of all instances of the |
| 26 | + * WikiEditor. Each context contains an instance field which contains a key that corrosponds to a reference to the |
| 27 | + * textarea which the WikiEditor was build around. This way, by passing a simple integer you can provide a way back |
| 28 | + * to a specific context. |
| 29 | + */ |
| 30 | + 'instances': [], |
| 31 | + /** |
| 32 | + * For each browser name, an array of conditions that must be met are supplied in [operaton, value]-form where |
| 33 | + * operation is a string containing a JavaScript compatible binary operator and value is either a number to be |
| 34 | + * compared with $.browser.versionNumber or a string to be compared with $.browser.version. If a browser is not |
| 35 | + * specifically mentioned, we just assume things will work. |
| 36 | + */ |
| 37 | + 'browsers': { |
| 38 | + // Left-to-right languages |
| 39 | + 'ltr': { |
| 40 | + // The toolbar layout is broken in IE6 |
| 41 | + 'msie': [['>=', 7]], |
| 42 | + // Layout issues in FF < 2 |
| 43 | + 'firefox': [['>=', 2]], |
| 44 | + // Text selection bugs galore - this may be a different situation with the new iframe-based solution |
| 45 | + 'opera': [['>=', 9.6]], |
| 46 | + // jQuery minimums |
| 47 | + 'safari': [['>=', 3]], |
| 48 | + 'chrome': [['>=', 3]], |
| 49 | + 'netscape': [['>=', 9]], |
| 50 | + 'blackberry': false, |
| 51 | + 'ipod': false, |
| 52 | + 'iphone': false |
| 53 | + }, |
| 54 | + // Right-to-left languages |
| 55 | + 'rtl': { |
| 56 | + // The toolbar layout is broken in IE 7 in RTL mode, and IE6 in any mode |
| 57 | + 'msie': [['>=', 8]], |
| 58 | + // Layout issues in FF < 2 |
| 59 | + 'firefox': [['>=', 2]], |
| 60 | + // Text selection bugs galore - this may be a different situation with the new iframe-based solution |
| 61 | + 'opera': [['>=', 9.6]], |
| 62 | + // jQuery minimums |
| 63 | + 'safari': [['>=', 3]], |
| 64 | + 'chrome': [['>=', 3]], |
| 65 | + 'netscape': [['>=', 9]], |
| 66 | + 'blackberry': false, |
| 67 | + 'ipod': false, |
| 68 | + 'iphone': false |
| 69 | + } |
| 70 | + }, |
| 71 | + /** |
| 72 | + * Path to images - this is a bit messy, and it would need to change if this code (and images) gets moved into the |
| 73 | + * core - or anywhere for that matter... |
| 74 | + */ |
| 75 | + 'imgPath' : wgScriptPath + '/extensions/UsabilityInitiative/images/wikiEditor/', |
| 76 | + /** |
| 77 | + * Checks the current browser against the browsers object to determine if the browser has been black-listed or not. |
| 78 | + * Because these rules are often very complex, the object contains configurable operators and can check against |
| 79 | + * either the browser version number or string. This process also involves checking if the current browser is amung |
| 80 | + * those which we have configured as compatible or not. If the browser was not configured as comptible we just go on |
| 81 | + * assuming things will work - the argument here is to prevent the need to update the code when a new browser comes |
| 82 | + * to market. The assumption here is that any new browser will be built on an existing engine or be otherwise so |
| 83 | + * similar to another existing browser that things actually do work as expected. The merrits of this argument, which |
| 84 | + * is essentially to blacklist rather than whitelist are debateable, but at this point we've decided it's the more |
| 85 | + * "open-web" way to go. |
| 86 | + * @param module Module object, defaults to $.wikiEditor |
| 87 | + */ |
| 88 | + 'isSupported': function( module ) { |
| 89 | + // Fallback to the wikiEditor browser map if no special map is provided in the module |
| 90 | + var mod = module && 'browsers' in module ? module : $.wikiEditor; |
| 91 | + // Check for and make use of cached value and early opportunities to bail |
| 92 | + if ( typeof mod.supported !== 'undefined' ) { |
| 93 | + // Cache hit |
| 94 | + return mod.supported; |
| 95 | + } |
| 96 | + // Run a browser support test and then cache and return the result |
| 97 | + return mod.supported = mw.usability.testBrowser( mod.browsers ); |
| 98 | + }, |
| 99 | + /** |
| 100 | + * Checks if a module has a specific requirement |
| 101 | + * @param module Module object |
| 102 | + * @param requirement String identifying requirement |
| 103 | + */ |
| 104 | + 'isRequired': function( module, requirement ) { |
| 105 | + if ( typeof module['req'] !== 'undefined' ) { |
| 106 | + for ( req in module['req'] ) { |
| 107 | + if ( module['req'][req] == requirement ) { |
| 108 | + return true; |
| 109 | + } |
| 110 | + } |
| 111 | + } |
| 112 | + return false; |
| 113 | + }, |
| 114 | + /** |
| 115 | + * Provides a way to extract messages from objects. Wraps the mw.usability.getMsg() function, which |
| 116 | + * may eventually become a wrapper for some kind of core MW functionality. |
| 117 | + * |
| 118 | + * @param object Object to extract messages from |
| 119 | + * @param property String of name of property which contains the message. This should be the base name of the |
| 120 | + * property, which means that in the case of the object { this: 'that', fooMsg: 'bar' }, passing property as 'this' |
| 121 | + * would return the raw text 'that', while passing property as 'foo' would return the internationalized message |
| 122 | + * with the key 'bar'. |
| 123 | + */ |
| 124 | + 'autoMsg': function( object, property ) { |
| 125 | + // Accept array of possible properties, of which the first one found will be used |
| 126 | + if ( typeof property == 'object' ) { |
| 127 | + for ( var i in property ) { |
| 128 | + if ( property[i] in object || property[i] + 'Msg' in object ) { |
| 129 | + property = property[i]; |
| 130 | + break; |
| 131 | + } |
| 132 | + } |
| 133 | + } |
| 134 | + if ( property in object ) { |
| 135 | + return object[property]; |
| 136 | + } else if ( property + 'Msg' in object ) { |
| 137 | + if ( typeof object[property + 'Msg' ] == 'object' ) { |
| 138 | + // [ messageKey, arg1, arg2, ... ] |
| 139 | + return mw.usability.getMsg.apply( mw.usability, object[property + 'Msg' ] ); |
| 140 | + } else { |
| 141 | + return mw.usability.getMsg( object[property + 'Msg'] ); |
| 142 | + } |
| 143 | + } else { |
| 144 | + return ''; |
| 145 | + } |
| 146 | + }, |
| 147 | + /** |
| 148 | + * Provides a way to extract a property of an object in a certain language, falling back on the property keyed as |
| 149 | + * 'default'. If such key doesn't exist, the object itself is considered the actual value, which should ideally |
| 150 | + * be the case so that you may use a string or object of any number of strings keyed by language with a default. |
| 151 | + * |
| 152 | + * @param object Object to extract property from |
| 153 | + * @param lang Language code, defaults to wgUserLanguage |
| 154 | + */ |
| 155 | + 'autoLang': function( object, lang ) { |
| 156 | + return object[lang || wgUserLanguage] || object['default'] || object; |
| 157 | + }, |
| 158 | + /** |
| 159 | + * Provides a way to extract the path of an icon in a certain language, automatically appending a version number for |
| 160 | + * caching purposes and prepending an image path when icon paths are relative. |
| 161 | + * |
| 162 | + * @param icon Icon object from e.g. toolbar config |
| 163 | + * @param path Default icon path, defaults to $.wikiEditor.imgPath |
| 164 | + * @param lang Language code, defaults to wgUserLanguage |
| 165 | + */ |
| 166 | + 'autoIcon': function( icon, path, lang ) { |
| 167 | + var src = $.wikiEditor.autoLang( icon, lang ); |
| 168 | + path = path || $.wikiEditor.imgPath; |
| 169 | + // Prepend path if src is not absolute |
| 170 | + if ( src.substr( 0, 7 ) != 'http://' && src.substr( 0, 8 ) != 'https://' && src[0] != '/' ) { |
| 171 | + src = path + src; |
| 172 | + } |
| 173 | + return src + '?' + wgWikiEditorIconVersion; |
| 174 | + }, |
| 175 | + /** |
| 176 | + * Get the sprite offset for a language if available, icon for a language if available, or the default offset or icon, |
| 177 | + * in that order of preference. |
| 178 | + * @param icon Icon object, see autoIcon() |
| 179 | + * @param offset Offset object |
| 180 | + * @param path Icon path, see autoIcon() |
| 181 | + * @param lang Language code, defaults to wgUserLanguage |
| 182 | + */ |
| 183 | + 'autoIconOrOffset': function( icon, offset, path, lang ) { |
| 184 | + lang = lang || wgUserLanguage; |
| 185 | + if ( typeof offset == 'object' && lang in offset ) { |
| 186 | + return offset[lang]; |
| 187 | + } else if ( typeof icon == 'object' && lang in icon ) { |
| 188 | + return $.wikiEditor.autoIcon( icon, undefined, lang ); |
| 189 | + } else { |
| 190 | + return $.wikiEditor.autoLang( offset, lang ); |
| 191 | + } |
| 192 | + } |
| 193 | +}; |
| 194 | + |
| 195 | +/** |
| 196 | + * jQuery plugin that provides a way to initialize a wikiEditor instance on a textarea. |
| 197 | + */ |
| 198 | +$.fn.wikiEditor = function() { |
| 199 | + |
| 200 | +// Skip any further work when running in browsers that are unsupported |
| 201 | +if ( !$j.wikiEditor.isSupported() ) { |
| 202 | + return $(this); |
| 203 | +} |
| 204 | + |
| 205 | +/* Initialization */ |
| 206 | + |
| 207 | +// The wikiEditor context is stored in the element's data, so when this function gets called again we can pick up right |
| 208 | +// where we left off |
| 209 | +var context = $(this).data( 'wikiEditor-context' ); |
| 210 | +// On first call, we need to set things up, but on all following calls we can skip right to the API handling |
| 211 | +if ( !context || typeof context == 'undefined' ) { |
| 212 | + |
| 213 | + // Star filling the context with useful data - any jQuery selections, as usual should be named with a preceding $ |
| 214 | + context = { |
| 215 | + // Reference to the textarea element which the wikiEditor is being built around |
| 216 | + '$textarea': $(this), |
| 217 | + // Container for any number of mutually exclusive views that are accessible by tabs |
| 218 | + 'views': {}, |
| 219 | + // Container for any number of module-specific data - only including data for modules in use on this context |
| 220 | + 'modules': {}, |
| 221 | + // General place to shouve bits of data into |
| 222 | + 'data': {}, |
| 223 | + // Unique numeric ID of this instance used both for looking up and differentiating instances of wikiEditor |
| 224 | + 'instance': $.wikiEditor.instances.push( $(this) ) - 1, |
| 225 | + // Array mapping elements in the textarea to character offsets |
| 226 | + 'offsets': null, |
| 227 | + // Cache for context.fn.htmlToText() |
| 228 | + 'htmlToTextMap': {}, |
| 229 | + // The previous HTML of the iframe, stored to detect whether something really changed. |
| 230 | + 'oldHTML': null, |
| 231 | + // Same for delayedChange() |
| 232 | + 'oldDelayedHTML': null, |
| 233 | + // The previous selection of the iframe, stored to detect whether the selection has changed |
| 234 | + 'oldDelayedSel': null, |
| 235 | + // Saved selection state for IE |
| 236 | + 'savedSelection': null, |
| 237 | + // Stack of states in { html: [string] } form |
| 238 | + 'history': [], |
| 239 | + // Current history state position - this is number of steps backwards, so it's always -1 or less |
| 240 | + 'historyPosition': -1, |
| 241 | + /// The previous historyPosition, stored to detect if change events were due to an undo or redo action |
| 242 | + 'oldDelayedHistoryPosition': -1 |
| 243 | + }; |
| 244 | + |
| 245 | + /* |
| 246 | + * Externally Accessible API |
| 247 | + * |
| 248 | + * These are available using calls to $j(selection).wikiEditor( call, data ) where selection is a jQuery selection |
| 249 | + * of the textarea that the wikiEditor instance was built around. |
| 250 | + */ |
| 251 | + |
| 252 | + context.api = { |
| 253 | + /** |
| 254 | + * Activates a module on a specific context with optional configuration data. |
| 255 | + * |
| 256 | + * @param data Either a string of the name of a module to add without any additional configuration parameters, |
| 257 | + * or an object with members keyed with module names and valued with configuration objects. |
| 258 | + */ |
| 259 | + 'addModule': function( context, data ) { |
| 260 | + var modules = {}; |
| 261 | + if ( typeof data == 'string' ) { |
| 262 | + modules[data] = {}; |
| 263 | + } else if ( typeof data == 'object' ) { |
| 264 | + modules = data; |
| 265 | + } |
| 266 | + for ( var module in modules ) { |
| 267 | + // Check for the existance of an available / supported module with a matching name and a create function |
| 268 | + if ( typeof module == 'string' && $.wikiEditor.isSupported( $.wikiEditor.modules[module] ) ) { |
| 269 | + // Extend the context's core API with this module's own API calls |
| 270 | + if ( 'api' in $.wikiEditor.modules[module] ) { |
| 271 | + for ( var call in $.wikiEditor.modules[module].api ) { |
| 272 | + // Modules may not overwrite existing API functions - first come, first serve |
| 273 | + if ( !( call in context.api ) ) { |
| 274 | + context.api[call] = $.wikiEditor.modules[module].api[call]; |
| 275 | + } |
| 276 | + } |
| 277 | + } |
| 278 | + // Activate the module on this context |
| 279 | + if ( 'fn' in $.wikiEditor.modules[module] && 'create' in $.wikiEditor.modules[module].fn ) { |
| 280 | + // Add a place for the module to put it's own stuff |
| 281 | + context.modules[module] = {}; |
| 282 | + // Tell the module to create itself on the context |
| 283 | + $.wikiEditor.modules[module].fn.create( context, modules[module] ); |
| 284 | + } |
| 285 | + } |
| 286 | + } |
| 287 | + } |
| 288 | + }; |
| 289 | + |
| 290 | + /* |
| 291 | + * Event Handlers |
| 292 | + * |
| 293 | + * These act as filters returning false if the event should be ignored or returning true if it should be passed |
| 294 | + * on to all modules. This is also where we can attach some extra information to the events. |
| 295 | + */ |
| 296 | + |
| 297 | + context.evt = { |
| 298 | + /** |
| 299 | + * Filters change events, which occur when the user interacts with the contents of the iframe. The goal of this |
| 300 | + * function is to both classify the scope of changes as 'division' or 'character' and to prevent further |
| 301 | + * processing of events which did not actually change the content of the iframe. |
| 302 | + */ |
| 303 | + 'keydown': function( event ) { |
| 304 | + switch ( event.which ) { |
| 305 | + case 90: // z |
| 306 | + case 89: // y |
| 307 | + if ( event.which == 89 && !$.browser.msie ) { |
| 308 | + // only handle y events for IE |
| 309 | + return true; |
| 310 | + } else if ( ( event.ctrlKey || event.metaKey ) && context.history.length ) { |
| 311 | + // HistoryPosition is a negative number between -1 and -context.history.length, in other words |
| 312 | + // it's the number of steps backwards from the latest state. |
| 313 | + var newPosition; |
| 314 | + if ( event.shiftKey || event.which == 89 ) { |
| 315 | + // Redo |
| 316 | + newPosition = context.historyPosition + 1; |
| 317 | + } else { |
| 318 | + // Undo |
| 319 | + newPosition = context.historyPosition - 1; |
| 320 | + } |
| 321 | + // Only act if we are switching to a valid state |
| 322 | + if ( newPosition >= ( context.history.length * -1 ) && newPosition < 0 ) { |
| 323 | + // Make sure we run the history storing code before we make this change |
| 324 | + context.fn.updateHistory( context.oldDelayedHTML != context.$content.html() ); |
| 325 | + context.oldDelayedHistoryPosition = context.historyPosition; |
| 326 | + context.historyPosition = newPosition; |
| 327 | + // Change state |
| 328 | + // FIXME: Destroys event handlers, will be a problem with template folding |
| 329 | + context.$content.html( |
| 330 | + context.history[context.history.length + context.historyPosition].html |
| 331 | + ); |
| 332 | + context.fn.purgeOffsets(); |
| 333 | + if( context.history[context.history.length + context.historyPosition].sel ) { |
| 334 | + context.fn.setSelection( { |
| 335 | + start: context.history[context.history.length + context.historyPosition].sel[0], |
| 336 | + end: context.history[context.history.length + context.historyPosition].sel[1] |
| 337 | + } ); |
| 338 | + } |
| 339 | + } |
| 340 | + // Prevent the browser from jumping in and doing its stuff |
| 341 | + return false; |
| 342 | + } |
| 343 | + break; |
| 344 | + // Intercept all tab events to provide consisten behavior across browsers |
| 345 | + // Webkit browsers insert tab characters by default into the iframe rather than changing input focus |
| 346 | + case 9: //tab |
| 347 | + // if any modifier keys are pressed, allow the browser to do it's thing |
| 348 | + if ( event.ctrlKey || event.altKey || event.shiftKey ) { |
| 349 | + return true; |
| 350 | + } else { |
| 351 | + var $tabindexList = $j( '[tabindex]:visible' ).sort( function( a, b ) { |
| 352 | + return a.tabIndex - b.tabIndex; |
| 353 | + } ); |
| 354 | + for( var i=0; i < $tabindexList.length; i++ ) { |
| 355 | + if( $tabindexList.eq( i ).attr('id') == context.$iframe.attr( 'id' ) ) { |
| 356 | + $tabindexList.get( i + 1 ).focus(); |
| 357 | + break; |
| 358 | + } |
| 359 | + } |
| 360 | + return false; |
| 361 | + } |
| 362 | + break; |
| 363 | + case 86: //v |
| 364 | + if ( event.ctrlKey && $.browser.msie ) { |
| 365 | + //paste, intercepted for IE |
| 366 | + context.evt.paste( event ); |
| 367 | + } |
| 368 | + break; |
| 369 | + } |
| 370 | + return true; |
| 371 | + }, |
| 372 | + 'change': function( event ) { |
| 373 | + event.data.scope = 'division'; |
| 374 | + var newHTML = context.$content.html(); |
| 375 | + if ( context.oldHTML != newHTML ) { |
| 376 | + context.fn.purgeOffsets(); |
| 377 | + context.oldHTML = newHTML; |
| 378 | + event.data.scope = 'realchange'; |
| 379 | + } |
| 380 | + // Never let the body be totally empty |
| 381 | + if ( context.$content.children().length == 0 ) { |
| 382 | + context.$content.append( '<p></p>' ); |
| 383 | + } |
| 384 | + return true; |
| 385 | + }, |
| 386 | + 'delayedChange': function( event ) { |
| 387 | + event.data.scope = 'division'; |
| 388 | + var newHTML = context.$content.html(); |
| 389 | + if ( context.oldDelayedHTML != newHTML ) { |
| 390 | + context.oldDelayedHTML = newHTML; |
| 391 | + event.data.scope = 'realchange'; |
| 392 | + // Surround by <p> if it does not already have it |
| 393 | + var cursorPos = context.fn.getCaretPosition(); |
| 394 | + var t = context.fn.getOffset( cursorPos[0] ); |
| 395 | + if ( ! $.browser.msie && t && t.node.nodeName == '#text' && t.node.parentNode.nodeName.toLowerCase() == 'body' ) { |
| 396 | + $( t.node ).wrap( "<p></p>" ); |
| 397 | + context.fn.purgeOffsets(); |
| 398 | + context.fn.setSelection( { start: cursorPos[0], end: cursorPos[1] } ); |
| 399 | + } |
| 400 | + } |
| 401 | + context.fn.updateHistory( event.data.scope == 'realchange' ); |
| 402 | + return true; |
| 403 | + }, |
| 404 | + 'cut': function( event ) { |
| 405 | + setTimeout( function() { |
| 406 | + context.$content.find( 'br' ).each( function() { |
| 407 | + if ( $(this).parent().is( 'body' ) ) { |
| 408 | + $(this).wrap( $( '<p></p>' ) ); |
| 409 | + } |
| 410 | + } ); |
| 411 | + }, 100 ); |
| 412 | + return true; |
| 413 | + }, |
| 414 | + 'paste': function( event ) { |
| 415 | + // Save the cursor position to restore it after all this voodoo |
| 416 | + var cursorPos = context.fn.getCaretPosition(); |
| 417 | + var oldLength = context.fn.getContents().length; |
| 418 | + var positionFromEnd = oldLength - cursorPos[1]; |
| 419 | + |
| 420 | + //give everything the wikiEditor class so that we can easily pick out things without that class as pasted |
| 421 | + context.$content.find( '*' ).addClass( 'wikiEditor' ); |
| 422 | + if ( $.layout.name !== 'webkit' ) { |
| 423 | + context.$content.addClass( 'pasting' ); |
| 424 | + } |
| 425 | + |
| 426 | + setTimeout( function() { |
| 427 | + // Kill stuff we know we don't want |
| 428 | + context.$content.find( 'script,style,img,input,select,textarea,hr,button,link,meta' ).remove(); |
| 429 | + var nodeToDelete = []; |
| 430 | + var pastedContent = []; |
| 431 | + var firstDirtyNode; |
| 432 | + var $lastDirtyNode; |
| 433 | + var elementAtCursor; |
| 434 | + if ( $.browser.msie && !context.offsets ) { |
| 435 | + elementAtCursor = null; |
| 436 | + } else { |
| 437 | + elementAtCursor = context.fn.getOffset( cursorPos[0] ); |
| 438 | + } |
| 439 | + if ( elementAtCursor == null || elementAtCursor.node == null ) { |
| 440 | + context.$content.prepend( '<p class = wikiEditor></p>' ); |
| 441 | + firstDirtyNode = context.$content.children()[0]; |
| 442 | + } else { |
| 443 | + firstDirtyNode = elementAtCursor.node; |
| 444 | + } |
| 445 | + |
| 446 | + //this is ugly but seems like the best way to handle the case where we select and replace all editor contents |
| 447 | + try { |
| 448 | + firstDirtyNode.parentNode; |
| 449 | + } catch ( err ) { |
| 450 | + context.$content.prepend( '<p class = wikiEditor></p>' ); |
| 451 | + firstDirtyNode = context.$content.children()[0]; |
| 452 | + } |
| 453 | + |
| 454 | + while ( firstDirtyNode != null ) { |
| 455 | + //we're going to replace the contents of the entire parent node. |
| 456 | + while ( firstDirtyNode.parentNode && firstDirtyNode.parentNode.nodeName != 'BODY' |
| 457 | + && ! $( firstDirtyNode ).hasClass( 'wikiEditor' ) |
| 458 | + ) { |
| 459 | + firstDirtyNode = firstDirtyNode.parentNode; |
| 460 | + } |
| 461 | + //go back till we find the first pasted node |
| 462 | + while ( firstDirtyNode.previousSibling != null |
| 463 | + && ! $( firstDirtyNode.previousSibling ).hasClass( 'wikiEditor' ) |
| 464 | + ) { |
| 465 | + |
| 466 | + if ( $( firstDirtyNode.previousSibling ).hasClass( '#comment' ) ) { |
| 467 | + $( firstDirtyNode ).remove(); |
| 468 | + } else { |
| 469 | + firstDirtyNode = firstDirtyNode.previousSibling; |
| 470 | + } |
| 471 | + } |
| 472 | + |
| 473 | + if ( firstDirtyNode.previousSibling != null ) { |
| 474 | + $lastDirtyNode = $( firstDirtyNode.previousSibling ); |
| 475 | + } else { |
| 476 | + $lastDirtyNode = $( firstDirtyNode ); |
| 477 | + } |
| 478 | + |
| 479 | + var cc = makeContentCollector( $.browser, null ); |
| 480 | + while ( firstDirtyNode != null ) { |
| 481 | + cc.collectContent(firstDirtyNode); |
| 482 | + cc.notifyNextNode(firstDirtyNode.nextSibling); |
| 483 | + |
| 484 | + nodeToDelete.push( firstDirtyNode ); |
| 485 | + |
| 486 | + firstDirtyNode = firstDirtyNode.nextSibling; |
| 487 | + if ( $( firstDirtyNode ).hasClass( 'wikiEditor' ) ) { |
| 488 | + break; |
| 489 | + } |
| 490 | + } |
| 491 | + |
| 492 | + var ccData = cc.finish(); |
| 493 | + pastedContent = ccData.lines; |
| 494 | + var pastedPretty = ''; |
| 495 | + for ( var i = 0; i < pastedContent.length; i++ ) { |
| 496 | + //escape html |
| 497 | + pastedPretty = pastedContent[i].replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\r?\n/g, '\\n'); |
| 498 | + //replace leading white spaces with |
| 499 | + match = pastedContent[i].match(/^[\s]+[^\s]/); |
| 500 | + if ( match != null && match.length > 0 ) { |
| 501 | + index = match[0].length; |
| 502 | + leadingSpace = match[0].replace(/[\s]/g, ' '); |
| 503 | + pastedPretty = leadingSpace + pastedPretty.substring(index, pastedPretty.length); |
| 504 | + } |
| 505 | + |
| 506 | + |
| 507 | + if( !pastedPretty && $.browser.msie && i == 0 ) { |
| 508 | + continue; |
| 509 | + } |
| 510 | + $newElement = $( '<p class="wikiEditor pasted" ></p>' ); |
| 511 | + if ( pastedPretty ) { |
| 512 | + $newElement.html( pastedPretty ); |
| 513 | + } else { |
| 514 | + $newElement.html( '<br class="wikiEditor">' ); |
| 515 | + } |
| 516 | + $newElement.insertAfter( $lastDirtyNode ); |
| 517 | + |
| 518 | + $lastDirtyNode = $newElement; |
| 519 | + |
| 520 | + } |
| 521 | + |
| 522 | + //now delete all the original nodes that we prettified already |
| 523 | + while ( nodeToDelete.length > 0 ) { |
| 524 | + $deleteNode = $( nodeToDelete.pop() ); |
| 525 | + $deleteNode.remove(); |
| 526 | + } |
| 527 | + |
| 528 | + //anything without wikiEditor class was pasted. |
| 529 | + $selection = context.$content.find( ':not(.wikiEditor)' ); |
| 530 | + if ( $selection.length == 0 ) { |
| 531 | + break; |
| 532 | + } else { |
| 533 | + firstDirtyNode = $selection.eq( 0 )[0]; |
| 534 | + } |
| 535 | + } |
| 536 | + context.$content.find( '.wikiEditor' ).removeClass( 'wikiEditor' ); |
| 537 | + |
| 538 | + //now place the cursor at the end of pasted content |
| 539 | + var newLength = context.fn.getContents().length; |
| 540 | + var newPos = newLength - positionFromEnd; |
| 541 | + |
| 542 | + context.fn.purgeOffsets(); |
| 543 | + context.fn.setSelection( { start: newPos, end: newPos } ); |
| 544 | + |
| 545 | + context.fn.scrollToCaretPosition(); |
| 546 | + |
| 547 | + |
| 548 | + }, 0 ); |
| 549 | + return true; |
| 550 | + }, |
| 551 | + 'ready': function( event ) { |
| 552 | + // Initialize our history queue |
| 553 | + if ( context.$content ) { |
| 554 | + context.history.push( { 'html': context.$content.html(), 'sel': context.fn.getCaretPosition() } ); |
| 555 | + } else { |
| 556 | + context.history.push( { 'html': '', 'sel': context.fn.getCaretPosition() } ); |
| 557 | + } |
| 558 | + return true; |
| 559 | + } |
| 560 | + }; |
| 561 | + |
| 562 | + /* Internal Functions */ |
| 563 | + |
| 564 | + context.fn = { |
| 565 | + /** |
| 566 | + * Executes core event filters as well as event handlers provided by modules. |
| 567 | + */ |
| 568 | + 'trigger': function( name, event ) { |
| 569 | + // Event is an optional argument, but from here on out, at least the type field should be dependable |
| 570 | + if ( typeof event == 'undefined' ) { |
| 571 | + event = { 'type': 'custom' }; |
| 572 | + } |
| 573 | + // Ensure there's a place for extra information to live |
| 574 | + if ( typeof event.data == 'undefined' ) { |
| 575 | + event.data = {}; |
| 576 | + } |
| 577 | + |
| 578 | + // Allow filtering to occur |
| 579 | + if ( name in context.evt ) { |
| 580 | + if ( !context.evt[name]( event ) ) { |
| 581 | + return false; |
| 582 | + } |
| 583 | + } |
| 584 | + var returnFromModules = null; //they return null by default |
| 585 | + // Pass the event around to all modules activated on this context |
| 586 | + |
| 587 | + for ( var module in context.modules ) { |
| 588 | + if ( |
| 589 | + module in $.wikiEditor.modules && |
| 590 | + 'evt' in $.wikiEditor.modules[module] && |
| 591 | + name in $.wikiEditor.modules[module].evt |
| 592 | + ) { |
| 593 | + var ret = $.wikiEditor.modules[module].evt[name]( context, event ); |
| 594 | + if (ret != null) { |
| 595 | + //if 1 returns false, the end result is false |
| 596 | + if( returnFromModules == null ) { |
| 597 | + returnFromModules = ret; |
| 598 | + } else { |
| 599 | + returnFromModules = returnFromModules && ret; |
| 600 | + } |
| 601 | + } |
| 602 | + } |
| 603 | + } |
| 604 | + if ( returnFromModules != null ) { |
| 605 | + return returnFromModules; |
| 606 | + } else { |
| 607 | + return true; |
| 608 | + } |
| 609 | + }, |
| 610 | + /** |
| 611 | + * Adds a button to the UI |
| 612 | + */ |
| 613 | + 'addButton': function( options ) { |
| 614 | + // Ensure that buttons and tabs are visible |
| 615 | + context.$controls.show(); |
| 616 | + context.$buttons.show(); |
| 617 | + return $( '<button />' ) |
| 618 | + .text( $.wikiEditor.autoMsg( options, 'caption' ) ) |
| 619 | + .click( options.action ) |
| 620 | + .appendTo( context.$buttons ); |
| 621 | + }, |
| 622 | + /** |
| 623 | + * Adds a view to the UI, which is accessed using a set of tabs. Views are mutually exclusive and by default a |
| 624 | + * wikitext view will be present. Only when more than one view exists will the tabs will be visible. |
| 625 | + */ |
| 626 | + 'addView': function( options ) { |
| 627 | + // Adds a tab |
| 628 | + function addTab( options ) { |
| 629 | + // Ensure that buttons and tabs are visible |
| 630 | + context.$controls.show(); |
| 631 | + context.$tabs.show(); |
| 632 | + // Return the newly appended tab |
| 633 | + return $( '<div></div>' ) |
| 634 | + .attr( 'rel', 'wikiEditor-ui-view-' + options.name ) |
| 635 | + .addClass( context.view == options.name ? 'current' : null ) |
| 636 | + .append( $( '<a></a>' ) |
| 637 | + .attr( 'href', '#' ) |
| 638 | + .mousedown( function() { |
| 639 | + // No dragging! |
| 640 | + return false; |
| 641 | + } ) |
| 642 | + .click( function( event ) { |
| 643 | + context.$ui.find( '.wikiEditor-ui-view' ).hide(); |
| 644 | + context.$ui.find( '.' + $(this).parent().attr( 'rel' ) ).show(); |
| 645 | + context.$tabs.find( 'div' ).removeClass( 'current' ); |
| 646 | + $(this).parent().addClass( 'current' ); |
| 647 | + $(this).blur(); |
| 648 | + if ( 'init' in options && typeof options.init == 'function' ) { |
| 649 | + options.init( context ); |
| 650 | + } |
| 651 | + event.preventDefault(); |
| 652 | + return false; |
| 653 | + } ) |
| 654 | + .text( $.wikiEditor.autoMsg( options, 'title' ) ) |
| 655 | + ) |
| 656 | + .appendTo( context.$tabs ); |
| 657 | + } |
| 658 | + // Automatically add the previously not-needed wikitext tab |
| 659 | + if ( !context.$tabs.children().size() ) { |
| 660 | + addTab( { 'name': 'wikitext', 'titleMsg': 'wikieditor-wikitext-tab' } ); |
| 661 | + } |
| 662 | + // Add the tab for the view we were actually asked to add |
| 663 | + addTab( options ); |
| 664 | + // Return newly appended view |
| 665 | + return $( '<div></div>' ) |
| 666 | + .addClass( 'wikiEditor-ui-view wikiEditor-ui-view-' + options.name ) |
| 667 | + .hide() |
| 668 | + .appendTo( context.$ui ); |
| 669 | + }, |
| 670 | + 'highlightLine': function( $element, mode ) { |
| 671 | + if ( !$element.is( 'p' ) ) { |
| 672 | + $element = $element.closest( 'p' ); |
| 673 | + } |
| 674 | + $element.css( 'backgroundColor', '#AACCFF' ); |
| 675 | + setTimeout( function() { $element.animate( { 'backgroundColor': 'white' }, 'slow' ); }, 100 ); |
| 676 | + setTimeout( function() { $element.css( 'backgroundColor', 'white' ); }, 1000 ); |
| 677 | + }, |
| 678 | + 'htmlToText': function( html ) { |
| 679 | + // This function is slow for large inputs, so aggressively cache input/output pairs |
| 680 | + if ( html in context.htmlToTextMap ) { |
| 681 | + return context.htmlToTextMap[html]; |
| 682 | + } |
| 683 | + var origHTML = html; |
| 684 | + |
| 685 | + // We use this elaborate trickery for cross-browser compatibility |
| 686 | + // IE does overzealous whitespace collapsing for $( '<pre />' ).html( html ); |
| 687 | + // We also do <br> and easy cases for <p> conversion here, complicated cases are handled later |
| 688 | + html = html |
| 689 | + .replace( /\r?\n/g, "" ) // IE7 inserts newlines before block elements |
| 690 | + .replace( / /g, " " ) // We inserted these to prevent IE from collapsing spaces |
| 691 | + .replace( /\<br[^\>]*\>\<\/p\>/gi, '</p>' ) // Remove trailing <br> from <p> |
| 692 | + .replace( /\<\/p\>\s*\<p[^\>]*\>/gi, "\n" ) // Easy case for <p> conversion |
| 693 | + .replace( /\<br[^\>]*\>/gi, "\n" ) // <br> conversion |
| 694 | + .replace( /\<\/p\>(\n*)\<p[^\>]*\>/gi, "$1\n" ) |
| 695 | + // Un-nest <p> tags |
| 696 | + .replace( /\<p[^\>]*\><p[^\>]*\>/gi, '<p>' ) |
| 697 | + .replace( /\<\/p\><\/p\>/gi, '</p>' ); |
| 698 | + // Save leading and trailing whitespace now and restore it later. IE eats it all, and even Firefox |
| 699 | + // won't leave everything alone |
| 700 | + var leading = html.match( /^\s*/ )[0]; |
| 701 | + var trailing = html.match( /\s*$/ )[0]; |
| 702 | + html = html.substr( leading.length, html.length - leading.length - trailing.length ); |
| 703 | + var $pre = $( '<pre>' + html + '</pre>' ); |
| 704 | + $pre.find( '.wikiEditor-noinclude' ).each( function() { $( this ).remove(); } ); |
| 705 | + // Convert tabs, <p>s and <br>s back |
| 706 | + $pre.find( '.wikiEditor-tab' ).each( function() { $( this ).text( "\t" ); } ); |
| 707 | + $pre.find( 'br' ).each( function() { $( this ).replaceWith( "\n" ); } ); |
| 708 | + // Converting <p>s is wrong if there's nothing before them, so check that. |
| 709 | + // .find( '* + p' ) isn't good enough because textnodes aren't considered |
| 710 | + $pre.find( 'p' ).each( function() { |
| 711 | + var text = $( this ).text(); |
| 712 | + // If this <p> is preceded by some text, add a \n at the beginning, and if |
| 713 | + // it's followed by a textnode, add a \n at the end |
| 714 | + // We need the traverser because there can be other weird stuff in between |
| 715 | + |
| 716 | + // Check for preceding text |
| 717 | + var t = new context.fn.rawTraverser( this.firstChild, this, $pre.get( 0 ), true ).prev(); |
| 718 | + while ( t && t.node.nodeName != '#text' && t.node.nodeName != 'BR' && t.node.nodeName != 'P' ) { |
| 719 | + t = t.prev(); |
| 720 | + } |
| 721 | + if ( t ) { |
| 722 | + text = "\n" + text; |
| 723 | + } |
| 724 | + |
| 725 | + // Check for following text |
| 726 | + t = new context.fn.rawTraverser( this.lastChild, this, $pre.get( 0 ), true ).next(); |
| 727 | + while ( t && t.node.nodeName != '#text' && t.node.nodeName != 'BR' && t.node.nodeName != 'P' ) { |
| 728 | + t = t.next(); |
| 729 | + } |
| 730 | + if ( t && !t.inP && t.node.nodeName == '#text' && t.node.nodeValue.charAt( 0 ) != '\n' |
| 731 | + && t.node.nodeValue.charAt( 0 ) != '\r' ) { |
| 732 | + text += "\n"; |
| 733 | + } |
| 734 | + $( this ).text( text ); |
| 735 | + } ); |
| 736 | + var retval; |
| 737 | + if ( $.browser.msie ) { |
| 738 | + // IE aggressively collapses whitespace in .text() after having done DOM manipulation, |
| 739 | + // but for some crazy reason this does work. Also convert \r back to \n |
| 740 | + retval = $( '<pre>' + $pre.html() + '</pre>' ).text().replace( /\r/g, '\n' ); |
| 741 | + } else { |
| 742 | + retval = $pre.text(); |
| 743 | + } |
| 744 | + return context.htmlToTextMap[origHTML] = leading + retval + trailing; |
| 745 | + }, |
| 746 | + /** |
| 747 | + * Get the first element before the selection that's in a certain class |
| 748 | + * @param classname Class to match. Defaults to '', meaning any class |
| 749 | + * @param strict If true, the element the selection starts in cannot match (default: false) |
| 750 | + * @return jQuery object or null if unknown |
| 751 | + */ |
| 752 | + 'beforeSelection': function( classname, strict ) { |
| 753 | + if ( typeof classname == 'undefined' ) { |
| 754 | + classname = ''; |
| 755 | + } |
| 756 | + var e = null, offset = null; |
| 757 | + if ( $.browser.msie && !context.$iframe[0].contentWindow.document.body ) { |
| 758 | + return null; |
| 759 | + } |
| 760 | + if ( context.$iframe[0].contentWindow.getSelection ) { |
| 761 | + // Firefox and Opera |
| 762 | + var selection = context.$iframe[0].contentWindow.getSelection(); |
| 763 | + // On load, webkit seems to not have a valid selection |
| 764 | + if ( selection.baseNode !== null ) { |
| 765 | + // Start at the selection's start and traverse the DOM backwards |
| 766 | + // This is done by traversing an element's children first, then the element itself, then its parent |
| 767 | + e = selection.getRangeAt( 0 ).startContainer; |
| 768 | + offset = selection.getRangeAt( 0 ).startOffset; |
| 769 | + } else { |
| 770 | + return null; |
| 771 | + } |
| 772 | + |
| 773 | + // When the cursor is on an empty line, Opera gives us a bogus range object with |
| 774 | + // startContainer=endContainer=body and startOffset=endOffset=1 |
| 775 | + var body = context.$iframe[0].contentWindow.document.body; |
| 776 | + if ( $.browser.opera && e == body && offset == 1 ) { |
| 777 | + return null; |
| 778 | + } |
| 779 | + } |
| 780 | + if ( !e && context.$iframe[0].contentWindow.document.selection ) { |
| 781 | + // IE |
| 782 | + // Because there's nothing like range.startContainer in IE, we need to do a DOM traversal |
| 783 | + // to find the element the start of the selection is in |
| 784 | + var range = context.$iframe[0].contentWindow.document.selection.createRange(); |
| 785 | + // Set range2 to the text before the selection |
| 786 | + var range2 = context.$iframe[0].contentWindow.document.body.createTextRange(); |
| 787 | + // For some reason this call throws errors in certain cases, e.g. when the selection is |
| 788 | + // not in the iframe |
| 789 | + try { |
| 790 | + range2.setEndPoint( 'EndToStart', range ); |
| 791 | + } catch ( ex ) { |
| 792 | + return null; |
| 793 | + } |
| 794 | + var seekPos = context.fn.htmlToText( range2.htmlText ).length; |
| 795 | + var offset = context.fn.getOffset( seekPos ); |
| 796 | + e = offset ? offset.node : null; |
| 797 | + offset = offset ? offset.offset : null; |
| 798 | + if ( !e ) { |
| 799 | + return null; |
| 800 | + } |
| 801 | + } |
| 802 | + if ( e.nodeName != '#text' ) { |
| 803 | + // The selection is not in a textnode, but between two non-text nodes |
| 804 | + // (usually inside the <body> between two <br>s). Go to the rightmost |
| 805 | + // child of the node just before the selection |
| 806 | + var newE = e.firstChild; |
| 807 | + for ( var i = 0; i < offset - 1 && newE; i++ ) { |
| 808 | + newE = newE.nextSibling; |
| 809 | + } |
| 810 | + while ( newE && newE.lastChild ) { |
| 811 | + newE = newE.lastChild; |
| 812 | + } |
| 813 | + e = newE || e; |
| 814 | + } |
| 815 | + |
| 816 | + // We'd normally use if( $( e ).hasClass( class ) in the while loop, but running the jQuery |
| 817 | + // constructor thousands of times is very inefficient |
| 818 | + var classStr = ' ' + classname + ' '; |
| 819 | + while ( e ) { |
| 820 | + if ( !strict && ( !classname || ( ' ' + e.className + ' ' ).indexOf( classStr ) != -1 ) ) { |
| 821 | + return $( e ); |
| 822 | + } |
| 823 | + var next = e.previousSibling; |
| 824 | + while ( next && next.lastChild ) { |
| 825 | + next = next.lastChild; |
| 826 | + } |
| 827 | + e = next || e.parentNode; |
| 828 | + strict = false; |
| 829 | + } |
| 830 | + return $( [] ); |
| 831 | + }, |
| 832 | + /** |
| 833 | + * Object used by traverser(). Don't use this unless you know what you're doing |
| 834 | + */ |
| 835 | + 'rawTraverser': function( node, inP, ancestor, skipNoinclude ) { |
| 836 | + this.node = node; |
| 837 | + this.inP = inP; |
| 838 | + this.ancestor = ancestor; |
| 839 | + this.skipNoinclude = skipNoinclude; |
| 840 | + this.next = function() { |
| 841 | + var p = this.node; |
| 842 | + var nextInP = this.inP; |
| 843 | + while ( p && !p.nextSibling ) { |
| 844 | + p = p.parentNode; |
| 845 | + if ( p == this.ancestor ) { |
| 846 | + // We're back at the ancestor, stop here |
| 847 | + p = null; |
| 848 | + } |
| 849 | + if ( p && p.nodeName == "P" ) { |
| 850 | + nextInP = null; |
| 851 | + } |
| 852 | + } |
| 853 | + p = p ? p.nextSibling : null; |
| 854 | + if ( p && p.nodeName == "P" ) { |
| 855 | + nextInP = p; |
| 856 | + } |
| 857 | + do { |
| 858 | + // Filter nodes with the wikiEditor-noinclude class |
| 859 | + // Don't use $( p ).hasClass( 'wikiEditor-noinclude' ) because |
| 860 | + // $() is slow in a tight loop |
| 861 | + if ( this.skipNoinclude ) { |
| 862 | + while ( p && ( ' ' + p.className + ' ' ).indexOf( ' wikiEditor-noinclude ' ) != -1 ) { |
| 863 | + p = p.nextSibling; |
| 864 | + } |
| 865 | + } |
| 866 | + if ( p && p.firstChild ) { |
| 867 | + p = p.firstChild; |
| 868 | + if ( p.nodeName == "P" ) { |
| 869 | + nextInP = p; |
| 870 | + } |
| 871 | + } |
| 872 | + } while ( p && p.firstChild ); |
| 873 | + // Instead of calling the rawTraverser constructor, inline it. This avoids function call overhead |
| 874 | + return p ? { 'node': p, 'inP': nextInP, 'ancestor': this.ancestor, |
| 875 | + 'skipNoinclude': this.skipNoinclude, 'next': this.next, 'prev': this.prev } : null; |
| 876 | + }; |
| 877 | + this.prev = function() { |
| 878 | + var p = this.node; |
| 879 | + var prevInP = this.inP; |
| 880 | + while ( p && !p.previousSibling ) { |
| 881 | + p = p.parentNode; |
| 882 | + if ( p == this.ancestor ) { |
| 883 | + // We're back at the ancestor, stop here |
| 884 | + p = null; |
| 885 | + } |
| 886 | + if ( p && p.nodeName == "P" ) { |
| 887 | + prevInP = null; |
| 888 | + } |
| 889 | + } |
| 890 | + p = p ? p.previousSibling : null; |
| 891 | + if ( p && p.nodeName == "P" ) { |
| 892 | + prevInP = p; |
| 893 | + } |
| 894 | + do { |
| 895 | + // Filter nodes with the wikiEditor-noinclude class |
| 896 | + // Don't use $( p ).hasClass( 'wikiEditor-noinclude' ) because |
| 897 | + // $() is slow in a tight loop |
| 898 | + if ( this.skipNoinclude ) { |
| 899 | + while ( p && ( ' ' + p.className + ' ' ).indexOf( ' wikiEditor-noinclude ' ) != -1 ) { |
| 900 | + p = p.previousSibling; |
| 901 | + } |
| 902 | + } |
| 903 | + if ( p && p.lastChild ) { |
| 904 | + p = p.lastChild; |
| 905 | + if ( p.nodeName == "P" ) { |
| 906 | + prevInP = p; |
| 907 | + } |
| 908 | + } |
| 909 | + } while ( p && p.lastChild ); |
| 910 | + // Instead of calling the rawTraverser constructor, inline it. This avoids function call overhead |
| 911 | + return p ? { 'node': p, 'inP': prevInP, 'ancestor': this.ancestor, |
| 912 | + 'skipNoinclude': this.skipNoinclude, 'next': this.next, 'prev': this.prev } : null; |
| 913 | + }; |
| 914 | + }, |
| 915 | + /** |
| 916 | + * Get an object used to traverse the leaf nodes in the iframe DOM. This traversal skips leaf nodes |
| 917 | + * inside an element with the wikiEditor-noinclude class. This basically wraps rawTraverser |
| 918 | + * |
| 919 | + * @param start Node to start at |
| 920 | + * @return Traverser object, use .next() or .prev() to get a traverser object referring to the |
| 921 | + * previous/next node |
| 922 | + */ |
| 923 | + 'traverser': function( start ) { |
| 924 | + // Find the leftmost leaf node in the tree |
| 925 | + var startNode = start.jquery ? start.get( 0 ) : start; |
| 926 | + var node = startNode; |
| 927 | + var inP = node.nodeName == "P" ? node : null; |
| 928 | + do { |
| 929 | + // Filter nodes with the wikiEditor-noinclude class |
| 930 | + // Don't use $( p ).hasClass( 'wikiEditor-noinclude' ) because |
| 931 | + // $() is slow in a tight loop |
| 932 | + while ( node && ( ' ' + node.className + ' ' ).indexOf( ' wikiEditor-noinclude ' ) != -1 ) { |
| 933 | + node = node.nextSibling; |
| 934 | + } |
| 935 | + if ( node && node.firstChild ) { |
| 936 | + node = node.firstChild; |
| 937 | + if ( node.nodeName == "P" ) { |
| 938 | + inP = node; |
| 939 | + } |
| 940 | + } |
| 941 | + } while ( node && node.firstChild ); |
| 942 | + return new context.fn.rawTraverser( node, inP, startNode, true ); |
| 943 | + }, |
| 944 | + 'getOffset': function( offset ) { |
| 945 | + if ( !context.offsets ) { |
| 946 | + context.fn.refreshOffsets(); |
| 947 | + } |
| 948 | + if ( offset in context.offsets ) { |
| 949 | + return context.offsets[offset]; |
| 950 | + } |
| 951 | + // Our offset is not pre-cached. Find the highest offset below it and interpolate |
| 952 | + // We need to traverse the entire object because for() doesn't traverse in order |
| 953 | + // We don't do in-order traversal because the object is sparse |
| 954 | + var lowerBound = -1; |
| 955 | + for ( var o in context.offsets ) { |
| 956 | + var realO = parseInt( o ); |
| 957 | + if ( realO < offset && realO > lowerBound) { |
| 958 | + lowerBound = realO; |
| 959 | + } |
| 960 | + } |
| 961 | + if ( !( lowerBound in context.offsets ) ) { |
| 962 | + // Weird edge case: either offset is too large or the document is empty |
| 963 | + return null; |
| 964 | + } |
| 965 | + var base = context.offsets[lowerBound]; |
| 966 | + return context.offsets[offset] = { |
| 967 | + 'node': base.node, |
| 968 | + 'offset': base.offset + offset - lowerBound, |
| 969 | + 'length': base.length, |
| 970 | + 'lastTextNode': base.lastTextNode |
| 971 | + }; |
| 972 | + }, |
| 973 | + 'purgeOffsets': function() { |
| 974 | + context.offsets = null; |
| 975 | + }, |
| 976 | + 'refreshOffsets': function() { |
| 977 | + context.offsets = [ ]; |
| 978 | + var t = context.fn.traverser( context.$content ); |
| 979 | + var pos = 0, lastTextNode = null; |
| 980 | + while ( t ) { |
| 981 | + if ( t.node.nodeName != '#text' && t.node.nodeName != 'BR' ) { |
| 982 | + t = t.next(); |
| 983 | + continue; |
| 984 | + } |
| 985 | + var nextPos = t.node.nodeName == '#text' ? pos + t.node.nodeValue.length : pos + 1; |
| 986 | + var nextT = t.next(); |
| 987 | + var leavingP = t.node.nodeName == '#text' && t.inP && nextT && ( !nextT.inP || nextT.inP != t.inP ); |
| 988 | + context.offsets[pos] = { |
| 989 | + 'node': t.node, |
| 990 | + 'offset': 0, |
| 991 | + 'length': nextPos - pos + ( leavingP ? 1 : 0 ), |
| 992 | + 'lastTextNode': lastTextNode |
| 993 | + }; |
| 994 | + if ( leavingP ) { |
| 995 | + // <p>Foo</p> looks like "Foo\n", make it quack like it too |
| 996 | + // Basically we're faking the \n character much like we're treating <br>s |
| 997 | + context.offsets[nextPos] = { |
| 998 | + 'node': t.node, |
| 999 | + 'offset': nextPos - pos, |
| 1000 | + 'length': nextPos - pos + 1, |
| 1001 | + 'lastTextNode': lastTextNode |
| 1002 | + }; |
| 1003 | + } |
| 1004 | + pos = nextPos + ( leavingP ? 1 : 0 ); |
| 1005 | + if ( t.node.nodeName == '#text' ) { |
| 1006 | + lastTextNode = t.node; |
| 1007 | + } |
| 1008 | + t = nextT; |
| 1009 | + } |
| 1010 | + }, |
| 1011 | + 'saveSelection': function() { |
| 1012 | + if ( !$.browser.msie ) { |
| 1013 | + // Only IE needs this |
| 1014 | + return; |
| 1015 | + } |
| 1016 | + if ( typeof context.$iframe != 'undefined' ) { |
| 1017 | + context.$iframe[0].contentWindow.focus(); |
| 1018 | + context.savedSelection = context.$iframe[0].contentWindow.document.selection.createRange(); |
| 1019 | + } else { |
| 1020 | + context.$textarea.focus(); |
| 1021 | + context.savedSelection = document.selection.createRange(); |
| 1022 | + } |
| 1023 | + }, |
| 1024 | + 'restoreSelection': function() { |
| 1025 | + if ( !$.browser.msie || context.savedSelection === null ) { |
| 1026 | + return; |
| 1027 | + } |
| 1028 | + if ( typeof context.$iframe != 'undefined' ) { |
| 1029 | + context.$iframe[0].contentWindow.focus(); |
| 1030 | + } else { |
| 1031 | + context.$textarea.focus(); |
| 1032 | + } |
| 1033 | + context.savedSelection.select(); |
| 1034 | + context.savedSelection = null; |
| 1035 | + }, |
| 1036 | + /** |
| 1037 | + * Update the history queue |
| 1038 | + * |
| 1039 | + * @param htmlChange pass true or false to inidicate if there was a text change that should potentially |
| 1040 | + * be given a new history state. |
| 1041 | + */ |
| 1042 | + 'updateHistory': function( htmlChange ) { |
| 1043 | + var newHTML = context.$content.html(); |
| 1044 | + var newSel = context.fn.getCaretPosition(); |
| 1045 | + // Was text changed? Was it because of a REDO or UNDO action? |
| 1046 | + if ( |
| 1047 | + context.history.length == 0 || |
| 1048 | + ( htmlChange && context.oldDelayedHistoryPosition == context.historyPosition ) |
| 1049 | + ) { |
| 1050 | + context.oldDelayedSel = newSel; |
| 1051 | + // Do we need to trim extras from our history? |
| 1052 | + // FIXME: this should really be happing on change, not on the delay |
| 1053 | + if ( context.historyPosition < -1 ) { |
| 1054 | + //clear out the extras |
| 1055 | + context.history.splice( context.history.length + context.historyPosition + 1 ); |
| 1056 | + context.historyPosition = -1; |
| 1057 | + } |
| 1058 | + context.history.push( { 'html': newHTML, 'sel': newSel } ); |
| 1059 | + // If the history has grown longer than 10 items, remove the earliest one |
| 1060 | + while ( context.history.length > 10 ) { |
| 1061 | + context.history.shift(); |
| 1062 | + } |
| 1063 | + } else if ( context.oldDelayedSel != newSel ) { |
| 1064 | + // If only the selection was changed, update it |
| 1065 | + context.oldDelayedSel = newSel; |
| 1066 | + context.history[context.history.length + context.historyPosition].sel = newSel; |
| 1067 | + } |
| 1068 | + // synch our old delayed history position until the next undo/redo action |
| 1069 | + context.oldDelayedHistoryPosition = context.historyPosition; |
| 1070 | + }, |
| 1071 | + /** |
| 1072 | + * Sets up the iframe in place of the textarea to allow more advanced operations |
| 1073 | + */ |
| 1074 | + 'setupIframe': function() { |
| 1075 | + context.$iframe = $( '<iframe></iframe>' ) |
| 1076 | + .attr( { |
| 1077 | + 'frameBorder': 0, |
| 1078 | + 'border': 0, |
| 1079 | + 'tabindex': 1, |
| 1080 | + 'src': wgScriptPath + '/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.html?' + |
| 1081 | + 'instance=' + context.instance + '&ts=' + ( new Date() ).getTime() + '&is=content', |
| 1082 | + 'id': 'wikiEditor-iframe-' + context.instance |
| 1083 | + } ) |
| 1084 | + .css( { |
| 1085 | + 'backgroundColor': 'white', |
| 1086 | + 'width': '100%', |
| 1087 | + 'height': context.$textarea.height(), |
| 1088 | + 'display': 'none', |
| 1089 | + 'overflow-y': 'scroll', |
| 1090 | + 'overflow-x': 'hidden' |
| 1091 | + } ) |
| 1092 | + .insertAfter( context.$textarea ) |
| 1093 | + .load( function() { |
| 1094 | + // Internet Explorer will reload the iframe once we turn on design mode, so we need to only turn it |
| 1095 | + // on during the first run, and then bail |
| 1096 | + if ( !this.isSecondRun ) { |
| 1097 | + // Turn the document's design mode on |
| 1098 | + context.$iframe[0].contentWindow.document.designMode = 'on'; |
| 1099 | + // Let the rest of this function happen next time around |
| 1100 | + if ( $.browser.msie ) { |
| 1101 | + this.isSecondRun = true; |
| 1102 | + return; |
| 1103 | + } |
| 1104 | + } |
| 1105 | + // Get a reference to the content area of the iframe |
| 1106 | + context.$content = $( context.$iframe[0].contentWindow.document.body ); |
| 1107 | + // Add classes to the body to influence the styles based on what's enabled |
| 1108 | + for ( module in context.modules ) { |
| 1109 | + context.$content.addClass( 'wikiEditor-' + module ); |
| 1110 | + } |
| 1111 | + // If we just do "context.$content.text( context.$textarea.val() )", Internet Explorer will strip |
| 1112 | + // out the whitespace charcters, specifically "\n" - so we must manually encode text and append it |
| 1113 | + // TODO: Refactor this into a textToHtml() function |
| 1114 | + var html = context.$textarea.val() |
| 1115 | + // We're gonna use &esc; as an escape sequence |
| 1116 | + .replace( /&esc;/g, '&esc;esc;' ) |
| 1117 | + // Escape existing uses of <p>, </p>, and <span class="wikiEditor-tab"></span> |
| 1118 | + .replace( /\<p\>/g, '&esc;<p>' ) |
| 1119 | + .replace( /\<\/p\>/g, '&esc;</p>' ) |
| 1120 | + .replace( |
| 1121 | + /\<span class="wikiEditor-tab"\>\<\/span\>/g, |
| 1122 | + '&esc;<span class="wikiEditor-tab"></span>' |
| 1123 | + ) |
| 1124 | + .replace( / /g, '&esc;&nbsp;' ); |
| 1125 | + // We must do some extra processing on IE to avoid dirty diffs, specifically IE will collapse |
| 1126 | + // leading spaces - browser sniffing is not ideal, but executing this code on a non-broken browser |
| 1127 | + // doesn't cause harm |
| 1128 | + if ( $.browser.msie ) { |
| 1129 | + html = html.replace( /\t/g, '<span class="wikiEditor-tab"></span>' ); |
| 1130 | + if ( $.browser.versionNumber <= 7 ) { |
| 1131 | + // Replace all spaces matching - IE <= 7 needs this because of its overzealous |
| 1132 | + // whitespace collapsing |
| 1133 | + html = html.replace( / /g, " " ); |
| 1134 | + } else { |
| 1135 | + // IE8 is happy if we just convert the first leading space to |
| 1136 | + html = html.replace( /(^|\n) /g, "$1 " ); |
| 1137 | + } |
| 1138 | + } |
| 1139 | + // Use a dummy div to escape all entities |
| 1140 | + // This'll also escape <br>, <span> and , so we unescape those after |
| 1141 | + // We also need to unescape the doubly-escaped things mentioned above |
| 1142 | + html = $( '<div />' ).text( '<p>' + html.replace( /\r?\n/g, '</p><p>' ) + '</p>' ).html() |
| 1143 | + .replace( /&nbsp;/g, ' ' ) |
| 1144 | + // Allow <p> tags to survive encoding |
| 1145 | + .replace( /<p>/g, '<p>' ) |
| 1146 | + .replace( /<\/p>/g, '</p>' ) |
| 1147 | + // And <span class="wikiEditor-tab"></span> too |
| 1148 | + .replace( |
| 1149 | + /<span( | )class=("|")wikiEditor-tab("|")><\/span>/g, |
| 1150 | + '<span class="wikiEditor-tab"></span>' |
| 1151 | + ) |
| 1152 | + // Empty <p> tags need <br> tags in them |
| 1153 | + .replace( /<p><\/p>/g, '<p><br></p>' ) |
| 1154 | + // Unescape &esc; stuff |
| 1155 | + .replace( /&esc;&amp;nbsp;/g, '&nbsp;' ) |
| 1156 | + .replace( /&esc;&lt;p&gt;/g, '<p>' ) |
| 1157 | + .replace( /&esc;&lt;\/p&gt;/g, '</p>' ) |
| 1158 | + .replace( |
| 1159 | + /&esc;&lt;span&nbsp;class=&quot;wikiEditor-tab&quot;&gt;&lt;\/span&gt;/g, |
| 1160 | + '<span class="wikiEditor-tab"><\/span>' |
| 1161 | + ) |
| 1162 | + .replace( /&esc;esc;/g, '&esc;' ); |
| 1163 | + context.$content.html( html ); |
| 1164 | + |
| 1165 | + // Reflect direction of parent frame into child |
| 1166 | + if ( $( 'body' ).is( '.rtl' ) ) { |
| 1167 | + context.$content.addClass( 'rtl' ).attr( 'dir', 'rtl' ); |
| 1168 | + } |
| 1169 | + // Activate the iframe, encoding the content of the textarea and copying it to the content of iframe |
| 1170 | + context.$textarea.attr( 'disabled', true ); |
| 1171 | + context.$textarea.hide(); |
| 1172 | + context.$iframe.show(); |
| 1173 | + // Let modules know we're ready to start working with the content |
| 1174 | + context.fn.trigger( 'ready' ); |
| 1175 | + // Only save HTML now: ready handlers may have modified it |
| 1176 | + context.oldHTML = context.oldDelayedHTML = context.$content.html(); |
| 1177 | + //remove our temporary loading |
| 1178 | + /* Disaling our loading div for now |
| 1179 | + $( '.wikiEditor-ui-loading' ).fadeOut( 'fast', function() { |
| 1180 | + $( this ).remove(); |
| 1181 | + } ); |
| 1182 | + */ |
| 1183 | + // Setup event handling on the iframe |
| 1184 | + $( context.$iframe[0].contentWindow.document ) |
| 1185 | + .bind( 'keydown', function( event ) { |
| 1186 | + event.jQueryNode = context.fn.getElementAtCursor(); |
| 1187 | + return context.fn.trigger( 'keydown', event ); |
| 1188 | + |
| 1189 | + } ) |
| 1190 | + .bind( 'keyup', function( event ) { |
| 1191 | + event.jQueryNode = context.fn.getElementAtCursor(); |
| 1192 | + return context.fn.trigger( 'keyup', event ); |
| 1193 | + } ) |
| 1194 | + .bind( 'keypress', function( event ) { |
| 1195 | + event.jQueryNode = context.fn.getElementAtCursor(); |
| 1196 | + return context.fn.trigger( 'keypress', event ); |
| 1197 | + } ) |
| 1198 | + .bind( 'paste', function( event ) { |
| 1199 | + return context.fn.trigger( 'paste', event ); |
| 1200 | + } ) |
| 1201 | + .bind( 'cut', function( event ) { |
| 1202 | + return context.fn.trigger( 'cut', event ); |
| 1203 | + } ) |
| 1204 | + .bind( 'keyup paste mouseup cut encapsulateSelection', function( event ) { |
| 1205 | + return context.fn.trigger( 'change', event ); |
| 1206 | + } ) |
| 1207 | + .delayedBind( 250, 'keyup paste mouseup cut encapsulateSelection', function( event ) { |
| 1208 | + context.fn.trigger( 'delayedChange', event ); |
| 1209 | + } ); |
| 1210 | + } ); |
| 1211 | + // Attach a submit handler to the form so that when the form is submitted the content of the iframe gets |
| 1212 | + // decoded and copied over to the textarea |
| 1213 | + context.$textarea.closest( 'form' ).submit( function() { |
| 1214 | + context.$textarea.attr( 'disabled', false ); |
| 1215 | + context.$textarea.val( context.$textarea.textSelection( 'getContents' ) ); |
| 1216 | + } ); |
| 1217 | + /* FIXME: This was taken from EditWarning.js - maybe we could do a jquery plugin for this? */ |
| 1218 | + // Attach our own handler for onbeforeunload which respects the current one |
| 1219 | + context.fallbackWindowOnBeforeUnload = window.onbeforeunload; |
| 1220 | + window.onbeforeunload = function() { |
| 1221 | + context.$textarea.val( context.$textarea.textSelection( 'getContents' ) ); |
| 1222 | + if ( context.fallbackWindowOnBeforeUnload ) { |
| 1223 | + return context.fallbackWindowOnBeforeUnload(); |
| 1224 | + } |
| 1225 | + }; |
| 1226 | + }, |
| 1227 | + |
| 1228 | + /* |
| 1229 | + * Compatibility with the $.textSelection jQuery plug-in. When the iframe is in use, these functions provide |
| 1230 | + * equivilant functionality to the otherwise textarea-based functionality. |
| 1231 | + */ |
| 1232 | + |
| 1233 | + 'getElementAtCursor': function() { |
| 1234 | + if ( context.$iframe[0].contentWindow.getSelection ) { |
| 1235 | + // Firefox and Opera |
| 1236 | + var selection = context.$iframe[0].contentWindow.getSelection(); |
| 1237 | + if ( selection.rangeCount == 0 ) { |
| 1238 | + // We don't know where the cursor is |
| 1239 | + return $( [] ); |
| 1240 | + } |
| 1241 | + var sc = selection.getRangeAt( 0 ).startContainer; |
| 1242 | + if ( sc.nodeName == "#text" ) sc = sc.parentNode; |
| 1243 | + return $( sc ); |
| 1244 | + } else if ( context.$iframe[0].contentWindow.document.selection ) { // should come last; Opera! |
| 1245 | + // IE |
| 1246 | + var selection = context.$iframe[0].contentWindow.document.selection.createRange(); |
| 1247 | + return $( selection.parentElement() ); |
| 1248 | + } |
| 1249 | + }, |
| 1250 | + |
| 1251 | + /** |
| 1252 | + * Gets the complete contents of the iframe (in plain text, not HTML) |
| 1253 | + */ |
| 1254 | + 'getContents': function() { |
| 1255 | + // For <p></p>, .html() returns <p> </p> in IE |
| 1256 | + // This seems to convince IE while not affecting display |
| 1257 | + if ( !context.$content ) { |
| 1258 | + return ''; |
| 1259 | + } |
| 1260 | + var html; |
| 1261 | + if ( $.browser.msie ) { |
| 1262 | + // Don't manipulate the iframe DOM itself, causes cursor jumping issues |
| 1263 | + var $c = $( context.$content.get( 0 ).cloneNode( true ) ); |
| 1264 | + $c.find( 'p' ).each( function() { |
| 1265 | + if ( $(this).html() == '' ) { |
| 1266 | + $(this).replaceWith( '<p></p>' ); |
| 1267 | + } |
| 1268 | + } ); |
| 1269 | + html = $c.html(); |
| 1270 | + } else { |
| 1271 | + html = context.$content.html(); |
| 1272 | + } |
| 1273 | + return context.fn.htmlToText( html ); |
| 1274 | + }, |
| 1275 | + /** |
| 1276 | + * Gets the currently selected text in the content |
| 1277 | + * DO NOT CALL THIS DIRECTLY, use $.textSelection( 'functionname', options ) instead |
| 1278 | + */ |
| 1279 | + 'getSelection': function() { |
| 1280 | + var retval; |
| 1281 | + if ( context.$iframe[0].contentWindow.getSelection ) { |
| 1282 | + // Firefox and Opera |
| 1283 | + retval = context.$iframe[0].contentWindow.getSelection(); |
| 1284 | + if ( $.browser.opera ) { |
| 1285 | + // Opera strips newlines in getSelection(), so we need something more sophisticated |
| 1286 | + if ( retval.rangeCount > 0 ) { |
| 1287 | + retval = context.fn.htmlToText( $( '<pre />' ) |
| 1288 | + .append( retval.getRangeAt( 0 ).cloneContents() ) |
| 1289 | + .html() |
| 1290 | + ); |
| 1291 | + } else { |
| 1292 | + retval = ''; |
| 1293 | + } |
| 1294 | + } |
| 1295 | + } else if ( context.$iframe[0].contentWindow.document.selection ) { // should come last; Opera! |
| 1296 | + // IE |
| 1297 | + retval = context.$iframe[0].contentWindow.document.selection.createRange(); |
| 1298 | + } |
| 1299 | + if ( typeof retval.text != 'undefined' ) { |
| 1300 | + // In IE8, retval.text is stripped of newlines, so we need to process retval.htmlText |
| 1301 | + // to get a reliable answer. IE7 does get this right though |
| 1302 | + // Run this fix for all IE versions anyway, it doesn't hurt |
| 1303 | + retval = context.fn.htmlToText( retval.htmlText ); |
| 1304 | + } else if ( typeof retval.toString != 'undefined' ) { |
| 1305 | + retval = retval.toString(); |
| 1306 | + } |
| 1307 | + return retval; |
| 1308 | + }, |
| 1309 | + /** |
| 1310 | + * Inserts text at the begining and end of a text selection, optionally inserting text at the caret when |
| 1311 | + * selection is empty. |
| 1312 | + * DO NOT CALL THIS DIRECTLY, use $.textSelection( 'functionname', options ) instead |
| 1313 | + */ |
| 1314 | + 'encapsulateSelection': function( options ) { |
| 1315 | + var selText = $(this).textSelection( 'getSelection' ); |
| 1316 | + var selTextArr; |
| 1317 | + var collapseToEnd = false; |
| 1318 | + var selectAfter = false; |
| 1319 | + var setSelectionTo = null; |
| 1320 | + var pre = options.pre, post = options.post; |
| 1321 | + if ( !selText ) { |
| 1322 | + selText = options.peri; |
| 1323 | + selectAfter = true; |
| 1324 | + } else if ( options.peri == selText.replace( /\s+$/, '' ) ) { |
| 1325 | + // Probably a successive button press |
| 1326 | + // strip any extra white space from selText |
| 1327 | + selText = selText.replace( /\s+$/, '' ); |
| 1328 | + // set the collapseToEnd flag to ensure our selection is collapsed to the end before any insertion is done |
| 1329 | + collapseToEnd = true; |
| 1330 | + // set selectAfter to true since we know we'll be populating with our default text |
| 1331 | + selectAfter = true; |
| 1332 | + } else if ( options.replace ) { |
| 1333 | + selText = options.peri; |
| 1334 | + } else if ( selText.charAt( selText.length - 1 ) == ' ' ) { |
| 1335 | + // Exclude ending space char |
| 1336 | + // FIXME: Why? |
| 1337 | + selText = selText.substring( 0, selText.length - 1 ); |
| 1338 | + post += ' '; |
| 1339 | + } |
| 1340 | + if ( options.splitlines ) { |
| 1341 | + selTextArr = selText.split( /\n/ ); |
| 1342 | + } |
| 1343 | + |
| 1344 | + if ( context.$iframe[0].contentWindow.getSelection ) { |
| 1345 | + // Firefox and Opera |
| 1346 | + var range = context.$iframe[0].contentWindow.getSelection().getRangeAt( 0 ); |
| 1347 | + // if our test above indicated that this was a sucessive button press, we need to collapse the |
| 1348 | + // selection to the end to avoid replacing text |
| 1349 | + if ( collapseToEnd ) { |
| 1350 | + // Make sure we're not collapsing ourselves into a BR tag |
| 1351 | + if ( range.endContainer.nodeName == 'BR' ) { |
| 1352 | + range.setEndBefore( range.endContainer ); |
| 1353 | + } |
| 1354 | + range.collapse( false ); |
| 1355 | + } |
| 1356 | + if ( options.ownline ) { |
| 1357 | + // We need to figure out if the cursor is at the start or end of a line |
| 1358 | + var atStart = false, atEnd = false; |
| 1359 | + var body = context.$content.get( 0 ); |
| 1360 | + if ( range.startOffset == 0 ) { |
| 1361 | + // Start of a line |
| 1362 | + // FIXME: Not necessarily the case with syntax highlighting or |
| 1363 | + // template collapsing |
| 1364 | + atStart = true; |
| 1365 | + } else if ( range.startContainer == body ) { |
| 1366 | + // Look up the node just before the start of the selection |
| 1367 | + // If it's a <BR>, we're at the start of a line that starts with a |
| 1368 | + // block element; if not, we're at the end of a line |
| 1369 | + var n = body.firstChild; |
| 1370 | + for ( var i = 0; i < range.startOffset - 1 && n; i++ ) { |
| 1371 | + n = n.nextSibling; |
| 1372 | + } |
| 1373 | + if ( n && n.nodeName == 'BR' ) { |
| 1374 | + atStart = true; |
| 1375 | + } else { |
| 1376 | + atEnd = true; |
| 1377 | + } |
| 1378 | + } |
| 1379 | + if ( ( range.endOffset == 0 && range.endContainer.nodeValue == null ) || |
| 1380 | + ( range.endContainer.nodeName == '#text' && |
| 1381 | + range.endOffset == range.endContainer.nodeValue.length ) || |
| 1382 | + ( range.endContainer.nodeName == 'P' && range.endContainer.nodeValue == null ) ) { |
| 1383 | + atEnd = true; |
| 1384 | + } |
| 1385 | + if ( !atStart ) { |
| 1386 | + pre = "\n" + options.pre; |
| 1387 | + } |
| 1388 | + if ( !atEnd ) { |
| 1389 | + post += "\n"; |
| 1390 | + } |
| 1391 | + } |
| 1392 | + var insertText = ""; |
| 1393 | + if ( options.splitlines ) { |
| 1394 | + for( var j = 0; j < selTextArr.length; j++ ) { |
| 1395 | + insertText = insertText + pre + selTextArr[j] + post; |
| 1396 | + if( j != selTextArr.length - 1 ) { |
| 1397 | + insertText += "\n"; |
| 1398 | + } |
| 1399 | + } |
| 1400 | + } else { |
| 1401 | + insertText = pre + selText + post; |
| 1402 | + } |
| 1403 | + var insertLines = insertText.split( "\n" ); |
| 1404 | + range.extractContents(); |
| 1405 | + // Insert the contents one line at a time - insertNode() inserts at the beginning, so this has to happen |
| 1406 | + // in reverse order |
| 1407 | + // Track the first and last inserted node, and if we need to also track where the text we need to select |
| 1408 | + // afterwards starts and ends |
| 1409 | + var firstNode = null, lastNode = null; |
| 1410 | + var selSC = null, selEC = null, selSO = null, selEO = null, offset = 0; |
| 1411 | + for ( var i = insertLines.length - 1; i >= 0; i-- ) { |
| 1412 | + firstNode = context.$iframe[0].contentWindow.document.createTextNode( insertLines[i] ); |
| 1413 | + range.insertNode( firstNode ); |
| 1414 | + lastNode = lastNode || firstNode; |
| 1415 | + var newOffset = offset + insertLines[i].length; |
| 1416 | + if ( !selEC && post.length <= newOffset ) { |
| 1417 | + selEC = firstNode; |
| 1418 | + selEO = selEC.nodeValue.length - ( post.length - offset ); |
| 1419 | + } |
| 1420 | + if ( selEC && !selSC && pre.length >= insertText.length - newOffset ) { |
| 1421 | + selSC = firstNode; |
| 1422 | + selSO = pre.length - ( insertText.length - newOffset ); |
| 1423 | + } |
| 1424 | + offset = newOffset; |
| 1425 | + if ( i > 0 ) { |
| 1426 | + firstNode = context.$iframe[0].contentWindow.document.createElement( 'br' ); |
| 1427 | + range.insertNode( firstNode ); |
| 1428 | + newOffset = offset + 1; |
| 1429 | + if ( !selEC && post.length <= newOffset ) { |
| 1430 | + selEC = firstNode; |
| 1431 | + selEO = 1 - ( post.length - offset ); |
| 1432 | + } |
| 1433 | + if ( selEC && !selSC && pre.length >= insertText.length - newOffset ) { |
| 1434 | + selSC = firstNode; |
| 1435 | + selSO = pre.length - ( insertText.length - newOffset ); |
| 1436 | + } |
| 1437 | + offset = newOffset; |
| 1438 | + } |
| 1439 | + } |
| 1440 | + if ( firstNode ) { |
| 1441 | + context.fn.scrollToTop( $( firstNode.parentNode ) ); |
| 1442 | + } |
| 1443 | + if ( selectAfter ) { |
| 1444 | + setSelectionTo = { |
| 1445 | + startContainer: selSC, |
| 1446 | + endContainer: selEC, |
| 1447 | + start: selSO, |
| 1448 | + end: selEO |
| 1449 | + }; |
| 1450 | + } else if ( lastNode ) { |
| 1451 | + setSelectionTo = { |
| 1452 | + startContainer: lastNode, |
| 1453 | + endContainer: lastNode, |
| 1454 | + start: lastNode.nodeValue.length, |
| 1455 | + end: lastNode.nodeValue.length |
| 1456 | + }; |
| 1457 | + } |
| 1458 | + } else if ( context.$iframe[0].contentWindow.document.selection ) { |
| 1459 | + // IE |
| 1460 | + context.$iframe[0].contentWindow.focus(); |
| 1461 | + var range = context.$iframe[0].contentWindow.document.selection.createRange(); |
| 1462 | + if ( options.ownline && range.moveStart ) { |
| 1463 | + // Check if we're at the start of a line |
| 1464 | + // If not, prepend a newline |
| 1465 | + var range2 = context.$iframe[0].contentWindow.document.selection.createRange(); |
| 1466 | + range2.collapse(); |
| 1467 | + range2.moveStart( 'character', -1 ); |
| 1468 | + // FIXME: Which check is correct? |
| 1469 | + if ( range2.text != "\r" && range2.text != "\n" && range2.text != "" ) { |
| 1470 | + pre = "\n" + pre; |
| 1471 | + } |
| 1472 | + |
| 1473 | + // Check if we're at the end of a line |
| 1474 | + // If not, append a newline |
| 1475 | + var range3 = context.$iframe[0].contentWindow.document.selection.createRange(); |
| 1476 | + range3.collapse( false ); |
| 1477 | + range3.moveEnd( 'character', 1 ); |
| 1478 | + if ( range3.text != "\r" && range3.text != "\n" && range3.text != "" ) { |
| 1479 | + post += "\n"; |
| 1480 | + } |
| 1481 | + } |
| 1482 | + // if our test above indicated that this was a sucessive button press, we need to collapse the |
| 1483 | + // selection to the end to avoid replacing text |
| 1484 | + if ( collapseToEnd ) { |
| 1485 | + range.collapse( false ); |
| 1486 | + } |
| 1487 | + // TODO: Clean this up. Duplicate code due to the pre-existing browser specific structure of this |
| 1488 | + // function |
| 1489 | + var insertText = ""; |
| 1490 | + if ( options.splitlines ) { |
| 1491 | + for( var j = 0; j < selTextArr.length; j++ ) { |
| 1492 | + insertText = insertText + pre + selTextArr[j] + post; |
| 1493 | + if( j != selTextArr.length - 1 ) { |
| 1494 | + insertText += "\n"; |
| 1495 | + } |
| 1496 | + } |
| 1497 | + } else { |
| 1498 | + insertText = pre + selText + post; |
| 1499 | + } |
| 1500 | + // TODO: Maybe find a more elegant way of doing this like the Firefox code above? |
| 1501 | + range.pasteHTML( insertText |
| 1502 | + .replace( /\</g, '<' ) |
| 1503 | + .replace( />/g, '>' ) |
| 1504 | + .replace( /\r?\n/g, '<br />' ) |
| 1505 | + ); |
| 1506 | + if ( selectAfter ) { |
| 1507 | + range.moveStart( 'character', -post.length - selText.length ); |
| 1508 | + range.moveEnd( 'character', -post.length ); |
| 1509 | + range.select(); |
| 1510 | + } |
| 1511 | + } |
| 1512 | + |
| 1513 | + if ( setSelectionTo ) { |
| 1514 | + context.fn.setSelection( setSelectionTo ); |
| 1515 | + } |
| 1516 | + // Trigger the encapsulateSelection event (this might need to get named something else/done differently) |
| 1517 | + $( context.$iframe[0].contentWindow.document ).trigger( |
| 1518 | + 'encapsulateSelection', [ pre, options.peri, post, options.ownline, options.replace ] |
| 1519 | + ); |
| 1520 | + return context.$textarea; |
| 1521 | + }, |
| 1522 | + /** |
| 1523 | + * Gets the position (in resolution of bytes not nessecarily characters) in a textarea |
| 1524 | + * DO NOT CALL THIS DIRECTLY, use $.textSelection( 'functionname', options ) instead |
| 1525 | + */ |
| 1526 | + 'getCaretPosition': function( options ) { |
| 1527 | + var startPos = null, endPos = null; |
| 1528 | + if ( context.$iframe[0].contentWindow.getSelection ) { |
| 1529 | + var selection = context.$iframe[0].contentWindow.getSelection(); |
| 1530 | + if ( selection.rangeCount == 0 ) { |
| 1531 | + // We don't know where the cursor is |
| 1532 | + return [ 0, 0 ]; |
| 1533 | + } |
| 1534 | + var sc = selection.getRangeAt( 0 ).startContainer, ec = selection.getRangeAt( 0 ).endContainer; |
| 1535 | + var so = selection.getRangeAt( 0 ).startOffset, eo = selection.getRangeAt( 0 ).endOffset; |
| 1536 | + if ( sc.nodeName == 'BODY' ) { |
| 1537 | + // Grab the node just before the start of the selection |
| 1538 | + var n = sc.firstChild; |
| 1539 | + for ( var i = 0; i < so - 1 && n; i++ ) { |
| 1540 | + n = n.nextSibling; |
| 1541 | + } |
| 1542 | + sc = n; |
| 1543 | + so = 0; |
| 1544 | + } |
| 1545 | + if ( ec.nodeName == 'BODY' ) { |
| 1546 | + var n = ec.firstChild; |
| 1547 | + for ( var i = 0; i < eo - 1 && n; i++ ) { |
| 1548 | + n = n.nextSibling; |
| 1549 | + } |
| 1550 | + ec = n; |
| 1551 | + eo = 0; |
| 1552 | + } |
| 1553 | + |
| 1554 | + // Make sure sc and ec are leaf nodes |
| 1555 | + while ( sc.firstChild ) { |
| 1556 | + sc = sc.firstChild; |
| 1557 | + } |
| 1558 | + while ( ec.firstChild ) { |
| 1559 | + ec = ec.firstChild; |
| 1560 | + } |
| 1561 | + // Make sure the offsets are regenerated if necessary |
| 1562 | + context.fn.getOffset( 0 ); |
| 1563 | + var o; |
| 1564 | + for ( o in context.offsets ) { |
| 1565 | + if ( startPos === null && context.offsets[o].node == sc ) { |
| 1566 | + // For some wicked reason o is a string, even though |
| 1567 | + // we put it in as an integer. Use ~~ to coerce it too an int |
| 1568 | + startPos = ~~o + so - context.offsets[o].offset; |
| 1569 | + } |
| 1570 | + if ( startPos !== null && context.offsets[o].node == ec ) { |
| 1571 | + endPos = ~~o + eo - context.offsets[o].offset; |
| 1572 | + break; |
| 1573 | + } |
| 1574 | + } |
| 1575 | + } else if ( context.$iframe[0].contentWindow.document.selection ) { |
| 1576 | + // IE |
| 1577 | + // FIXME: This is mostly copypasted from the textSelection plugin |
| 1578 | + var d = context.$iframe[0].contentWindow.document; |
| 1579 | + var postFinished = false; |
| 1580 | + var periFinished = false; |
| 1581 | + var postFinished = false; |
| 1582 | + var preText, rawPreText, periText; |
| 1583 | + var rawPeriText, postText, rawPostText; |
| 1584 | + // Depending on the document state, and if the cursor has ever been manually placed within the document |
| 1585 | + // the following call such as setEndPoint can result in nasty errors. These cases are always cases |
| 1586 | + // in which the start and end points can safely be assumed to be 0, so we will just try our best to do |
| 1587 | + // the full process but fall back to 0. |
| 1588 | + try { |
| 1589 | + // Create range containing text in the selection |
| 1590 | + var periRange = d.selection.createRange().duplicate(); |
| 1591 | + // Create range containing text before the selection |
| 1592 | + var preRange = d.body.createTextRange(); |
| 1593 | + // Move the end where we need it |
| 1594 | + preRange.setEndPoint( "EndToStart", periRange ); |
| 1595 | + // Create range containing text after the selection |
| 1596 | + var postRange = d.body.createTextRange(); |
| 1597 | + // Move the start where we need it |
| 1598 | + postRange.setEndPoint( "StartToEnd", periRange ); |
| 1599 | + // Load the text values we need to compare |
| 1600 | + preText = rawPreText = preRange.text; |
| 1601 | + periText = rawPeriText = periRange.text; |
| 1602 | + postText = rawPostText = postRange.text; |
| 1603 | + /* |
| 1604 | + * Check each range for trimmed newlines by shrinking the range by 1 |
| 1605 | + * character and seeing if the text property has changed. If it has |
| 1606 | + * not changed then we know that IE has trimmed a \r\n from the end. |
| 1607 | + */ |
| 1608 | + do { |
| 1609 | + if ( !postFinished ) { |
| 1610 | + if ( preRange.compareEndPoints( "StartToEnd", preRange ) == 0 ) { |
| 1611 | + postFinished = true; |
| 1612 | + } else { |
| 1613 | + preRange.moveEnd( "character", -1 ) |
| 1614 | + if ( preRange.text == preText ) { |
| 1615 | + rawPreText += "\r\n"; |
| 1616 | + } else { |
| 1617 | + postFinished = true; |
| 1618 | + } |
| 1619 | + } |
| 1620 | + } |
| 1621 | + if ( !periFinished ) { |
| 1622 | + if ( periRange.compareEndPoints( "StartToEnd", periRange ) == 0 ) { |
| 1623 | + periFinished = true; |
| 1624 | + } else { |
| 1625 | + periRange.moveEnd( "character", -1 ) |
| 1626 | + if ( periRange.text == periText ) { |
| 1627 | + rawPeriText += "\r\n"; |
| 1628 | + } else { |
| 1629 | + periFinished = true; |
| 1630 | + } |
| 1631 | + } |
| 1632 | + } |
| 1633 | + if ( !postFinished ) { |
| 1634 | + if ( postRange.compareEndPoints("StartToEnd", postRange) == 0 ) { |
| 1635 | + postFinished = true; |
| 1636 | + } else { |
| 1637 | + postRange.moveEnd( "character", -1 ) |
| 1638 | + if ( postRange.text == postText ) { |
| 1639 | + rawPostText += "\r\n"; |
| 1640 | + } else { |
| 1641 | + postFinished = true; |
| 1642 | + } |
| 1643 | + } |
| 1644 | + } |
| 1645 | + } while ( ( !postFinished || !periFinished || !postFinished ) ); |
| 1646 | + startPos = rawPreText.replace( /\r\n/g, "\n" ).length; |
| 1647 | + endPos = startPos + rawPeriText.replace( /\r\n/g, "\n" ).length; |
| 1648 | + } catch( e ) { |
| 1649 | + startPos = endPos = 0; |
| 1650 | + } |
| 1651 | + } |
| 1652 | + return [ startPos, endPos ]; |
| 1653 | + }, |
| 1654 | + /** |
| 1655 | + * Sets the selection of the content |
| 1656 | + * DO NOT CALL THIS DIRECTLY, use $.textSelection( 'functionname', options ) instead |
| 1657 | + * |
| 1658 | + * @param start Character offset of selection start |
| 1659 | + * @param end Character offset of selection end |
| 1660 | + * @param startContainer Element in iframe to start selection in. If not set, start is a character offset |
| 1661 | + * @param endContainer Element in iframe to end selection in. If not set, end is a character offset |
| 1662 | + */ |
| 1663 | + 'setSelection': function( options ) { |
| 1664 | + var sc = options.startContainer, ec = options.endContainer; |
| 1665 | + sc = sc && sc.jquery ? sc[0] : sc; |
| 1666 | + ec = ec && ec.jquery ? ec[0] : ec; |
| 1667 | + if ( context.$iframe[0].contentWindow.getSelection ) { |
| 1668 | + // Firefox and Opera |
| 1669 | + var start = options.start, end = options.end; |
| 1670 | + if ( !sc || !ec ) { |
| 1671 | + var s = context.fn.getOffset( start ); |
| 1672 | + var e = context.fn.getOffset( end ); |
| 1673 | + sc = s ? s.node : null; |
| 1674 | + ec = e ? e.node : null; |
| 1675 | + start = s ? s.offset : null; |
| 1676 | + end = e ? e.offset : null; |
| 1677 | + // Don't try to set the selection past the end of a node, causes errors |
| 1678 | + // Just put the selection at the end of the node in this case |
| 1679 | + if ( sc != null && sc.nodeName == '#text' && start > sc.nodeValue.length ) { |
| 1680 | + start = sc.nodeValue.length - 1; |
| 1681 | + } |
| 1682 | + if ( ec != null && ec.nodeName == '#text' && end > ec.nodeValue.length ) { |
| 1683 | + end = ec.nodeValue.length - 1; |
| 1684 | + } |
| 1685 | + } |
| 1686 | + if ( !sc || !ec ) { |
| 1687 | + // The requested offset isn't in the offsets array |
| 1688 | + // Give up |
| 1689 | + return context.$textarea; |
| 1690 | + } |
| 1691 | + |
| 1692 | + var sel = context.$iframe[0].contentWindow.getSelection(); |
| 1693 | + while ( sc.firstChild && sc.nodeName != '#text' ) { |
| 1694 | + sc = sc.firstChild; |
| 1695 | + } |
| 1696 | + while ( ec.firstChild && ec.nodeName != '#text' ) { |
| 1697 | + ec = ec.firstChild; |
| 1698 | + } |
| 1699 | + var range = context.$iframe[0].contentWindow.document.createRange(); |
| 1700 | + range.setStart( sc, start ); |
| 1701 | + range.setEnd( ec, end ); |
| 1702 | + sel.removeAllRanges(); |
| 1703 | + sel.addRange( range ); |
| 1704 | + context.$iframe[0].contentWindow.focus(); |
| 1705 | + } else if ( context.$iframe[0].contentWindow.document.body.createTextRange ) { |
| 1706 | + // IE |
| 1707 | + var range = context.$iframe[0].contentWindow.document.body.createTextRange(); |
| 1708 | + if ( sc ) { |
| 1709 | + range.moveToElementText( sc ); |
| 1710 | + } |
| 1711 | + range.collapse(); |
| 1712 | + range.moveEnd( 'character', options.start ); |
| 1713 | + |
| 1714 | + var range2 = context.$iframe[0].contentWindow.document.body.createTextRange(); |
| 1715 | + if ( ec ) { |
| 1716 | + range2.moveToElementText( ec ); |
| 1717 | + } |
| 1718 | + range2.collapse(); |
| 1719 | + range2.moveEnd( 'character', options.end ); |
| 1720 | + |
| 1721 | + // IE does newline emulation for <p>s: <p>foo</p><p>bar</p> becomes foo\nbar just fine |
| 1722 | + // but <p>foo</p><br><br><p>bar</p> becomes foo\n\n\n\nbar , one \n too many |
| 1723 | + // Correct for this |
| 1724 | + var matches, counted = 0; |
| 1725 | + // while ( matches = range.htmlText.match( regex ) && matches.length <= counted ) doesn't work |
| 1726 | + // because the assignment side effect hasn't happened yet when the second term is evaluated |
| 1727 | + while ( matches = range.htmlText.match( /\<\/p\>(\<br[^\>]*\>)+\<p\>/gi ) ) { |
| 1728 | + if ( matches.length <= counted ) |
| 1729 | + break; |
| 1730 | + range.moveEnd( 'character', matches.length ); |
| 1731 | + counted += matches.length; |
| 1732 | + } |
| 1733 | + range2.moveEnd( 'character', counted ); |
| 1734 | + while ( matches = range2.htmlText.match( /\<\/p\>(\<br[^\>]*\>)+\<p\>/gi ) ) { |
| 1735 | + if ( matches.length <= counted ) |
| 1736 | + break; |
| 1737 | + range2.moveEnd( 'character', matches.length ); |
| 1738 | + counted += matches.length; |
| 1739 | + } |
| 1740 | + |
| 1741 | + range2.setEndPoint( 'StartToEnd', range ); |
| 1742 | + range2.select(); |
| 1743 | + } |
| 1744 | + return context.$textarea; |
| 1745 | + }, |
| 1746 | + /** |
| 1747 | + * Scroll a textarea to the current cursor position. You can set the cursor position with setSelection() |
| 1748 | + * DO NOT CALL THIS DIRECTLY, use $.textSelection( 'functionname', options ) instead |
| 1749 | + */ |
| 1750 | + 'scrollToCaretPosition': function( options ) { |
| 1751 | + context.fn.scrollToTop( context.fn.getElementAtCursor(), true ); |
| 1752 | + }, |
| 1753 | + /** |
| 1754 | + * Scroll an element to the top of the iframe |
| 1755 | + * DO NOT CALL THIS DIRECTLY, use $.textSelection( 'functionname', options ) instead |
| 1756 | + * |
| 1757 | + * @param $element jQuery object containing an element in the iframe |
| 1758 | + * @param force If true, scroll the element even if it's already visible |
| 1759 | + */ |
| 1760 | + 'scrollToTop': function( $element, force ) { |
| 1761 | + var html = context.$content.closest( 'html' ), |
| 1762 | + body = context.$content.closest( 'body' ), |
| 1763 | + parentHtml = $( 'html' ), |
| 1764 | + parentBody = $( 'body' ); |
| 1765 | + var y = $element.offset().top; |
| 1766 | + if ( !$.browser.msie && ! $element.is( 'body' ) ) { |
| 1767 | + y = parentHtml.scrollTop() > 0 ? y + html.scrollTop() - parentHtml.scrollTop() : y; |
| 1768 | + y = parentBody.scrollTop() > 0 ? y + body.scrollTop() - parentBody.scrollTop() : y; |
| 1769 | + } |
| 1770 | + var topBound = html.scrollTop() > body.scrollTop() ? html.scrollTop() : body.scrollTop(), |
| 1771 | + bottomBound = topBound + context.$iframe.height(); |
| 1772 | + if ( force || y < topBound || y > bottomBound ) { |
| 1773 | + html.scrollTop( y ); |
| 1774 | + body.scrollTop( y ); |
| 1775 | + } |
| 1776 | + $element.trigger( 'scrollToTop' ); |
| 1777 | + }, |
| 1778 | + /** |
| 1779 | + * Save scrollTop and cursor position for IE. |
| 1780 | + */ |
| 1781 | + 'saveStuffForIE': function() { |
| 1782 | + // Only need this for IE in textarea mode |
| 1783 | + if ( !$.browser.msie || context.$iframe ) |
| 1784 | + return; |
| 1785 | + var IHateIE = { |
| 1786 | + 'scrollTop' : context.$textarea.scrollTop(), |
| 1787 | + 'pos': context.$textarea.textSelection( 'getCaretPosition', { startAndEnd: true } ) |
| 1788 | + }; |
| 1789 | + context.$textarea.data( 'IHateIE', IHateIE ); |
| 1790 | + }, |
| 1791 | + /** |
| 1792 | + * Restore scrollTo and cursor position for IE. |
| 1793 | + */ |
| 1794 | + 'restoreStuffForIE': function() { |
| 1795 | + // Only need this for IE in textarea mode |
| 1796 | + if ( !$.browser.msie || context.$iframe ) |
| 1797 | + return; |
| 1798 | + var IHateIE = context.$textarea.data( 'IHateIE' ); |
| 1799 | + if ( !IHateIE ) |
| 1800 | + return; |
| 1801 | + context.$textarea.scrollTop( IHateIE.scrollTop ); |
| 1802 | + context.$textarea.textSelection( 'setSelection', { start: IHateIE.pos[0], end: IHateIE.pos[1] } ); |
| 1803 | + context.$textarea.data( 'IHateIE', null ); |
| 1804 | + } |
| 1805 | + }; |
| 1806 | + |
| 1807 | + /* |
| 1808 | + * Base UI Construction |
| 1809 | + * |
| 1810 | + * The UI is built from several containers, the outer-most being a div classed as "wikiEditor-ui". These containers |
| 1811 | + * provide a certain amount of "free" layout, but in some situations procedural layout is needed, which is performed |
| 1812 | + * as a response to the "resize" event. |
| 1813 | + */ |
| 1814 | + |
| 1815 | + // Assemble a temporary div to place over the wikiEditor while it's being constructed |
| 1816 | + /* Disabling our loading div for now |
| 1817 | + var $loader = $( '<div></div>' ) |
| 1818 | + .addClass( 'wikiEditor-ui-loading' ) |
| 1819 | + .append( $( '<span>' + mw.usability.getMsg( 'wikieditor-loading' ) + '</span>' ) |
| 1820 | + .css( 'marginTop', context.$textarea.height() / 2 ) ); |
| 1821 | + */ |
| 1822 | + // Encapsulate the textarea with some containers for layout |
| 1823 | + context.$textarea |
| 1824 | + /* Disabling our loading div for now |
| 1825 | + .after( $loader ) |
| 1826 | + .add( $loader ) |
| 1827 | + */ |
| 1828 | + .wrapAll( $( '<div></div>' ).addClass( 'wikiEditor-ui' ) ) |
| 1829 | + .wrapAll( $( '<div></div>' ).addClass( 'wikiEditor-ui-view wikiEditor-ui-view-wikitext' ) ) |
| 1830 | + .wrapAll( $( '<div></div>' ).addClass( 'wikiEditor-ui-left' ) ) |
| 1831 | + .wrapAll( $( '<div></div>' ).addClass( 'wikiEditor-ui-bottom' ) ) |
| 1832 | + .wrapAll( $( '<div></div>' ).addClass( 'wikiEditor-ui-text' ) ); |
| 1833 | + // Get references to some of the newly created containers |
| 1834 | + context.$ui = context.$textarea.parent().parent().parent().parent().parent(); |
| 1835 | + context.$wikitext = context.$textarea.parent().parent().parent().parent(); |
| 1836 | + // Add in tab and button containers |
| 1837 | + context.$wikitext |
| 1838 | + .before( |
| 1839 | + $( '<div></div>' ).addClass( 'wikiEditor-ui-controls' ) |
| 1840 | + .append( $( '<div></div>' ).addClass( 'wikiEditor-ui-tabs' ).hide() ) |
| 1841 | + .append( $( '<div></div>' ).addClass( 'wikiEditor-ui-buttons' ) ) |
| 1842 | + ) |
| 1843 | + .before( $( '<div style="clear:both;"></div>' ) ); |
| 1844 | + // Get references to some of the newly created containers |
| 1845 | + context.$controls = context.$ui.find( '.wikiEditor-ui-buttons' ).hide(); |
| 1846 | + context.$buttons = context.$ui.find( '.wikiEditor-ui-buttons' ); |
| 1847 | + context.$tabs = context.$ui.find( '.wikiEditor-ui-tabs' ); |
| 1848 | + // Clear all floating after the UI |
| 1849 | + context.$ui.after( $( '<div style="clear:both;"></div>' ) ); |
| 1850 | + // Attach a right container |
| 1851 | + context.$wikitext.append( $( '<div></div>' ).addClass( 'wikiEditor-ui-right' ) ); |
| 1852 | + // Attach a top container to the left pane |
| 1853 | + context.$wikitext.find( '.wikiEditor-ui-left' ).prepend( $( '<div></div>' ).addClass( 'wikiEditor-ui-top' ) ); |
| 1854 | + // Setup the intial view |
| 1855 | + context.view = 'wikitext'; |
| 1856 | + // Trigger the "resize" event anytime the window is resized |
| 1857 | + $( window ).resize( function( event ) { context.fn.trigger( 'resize', event ); } ); |
| 1858 | +} |
| 1859 | + |
| 1860 | +/* API Execution */ |
| 1861 | + |
| 1862 | +// Since javascript gives arguments as an object, we need to convert them so they can be used more easily |
| 1863 | +var args = $.makeArray( arguments ); |
| 1864 | + |
| 1865 | +// Dynamically setup the Iframe when needed when adding modules |
| 1866 | +if ( typeof context.$iframe === 'undefined' && args[0] == 'addModule' && typeof args[1] != 'undefined' ) { |
| 1867 | + var modules = args[1]; |
| 1868 | + if ( typeof modules != "object" ) { |
| 1869 | + modules = {}; |
| 1870 | + modules[args[1]] = ''; |
| 1871 | + } |
| 1872 | + for ( module in modules ) { |
| 1873 | + // Only allow modules which are supported (and thus actually being turned on) affect this decision |
| 1874 | + if ( module in $.wikiEditor.modules && $.wikiEditor.isSupported( $.wikiEditor.modules[module] ) && |
| 1875 | + $.wikiEditor.isRequired( $.wikiEditor.modules[module], 'iframe' ) ) { |
| 1876 | + |
| 1877 | + context.fn.setupIframe(); |
| 1878 | + break; |
| 1879 | + } |
| 1880 | + } |
| 1881 | +} |
| 1882 | + |
| 1883 | +// There would need to be some arguments if the API is being called |
| 1884 | +if ( args.length > 0 ) { |
| 1885 | + // Handle API calls |
| 1886 | + var call = args.shift(); |
| 1887 | + if ( call in context.api ) { |
| 1888 | + context.api[call]( context, typeof args[0] == 'undefined' ? {} : args[0] ); |
| 1889 | + } |
| 1890 | +} |
| 1891 | + |
| 1892 | +// Store the context for next time, and support chaining |
| 1893 | +return $(this).data( 'wikiEditor-context', context ); |
| 1894 | + |
| 1895 | +}; } )( jQuery ); |
Property changes on: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 1896 | + native |
Index: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.toolbar.js |
— | — | @@ -0,0 +1,765 @@ |
| 2 | +/** |
| 3 | + * Toolbar module for wikiEditor |
| 4 | + */ |
| 5 | +( function( $ ) { $.wikiEditor.modules.toolbar = { |
| 6 | + |
| 7 | +/** |
| 8 | + * API accessible functions |
| 9 | + */ |
| 10 | +api : { |
| 11 | + addToToolbar : function( context, data ) { |
| 12 | + for ( type in data ) { |
| 13 | + switch ( type ) { |
| 14 | + case 'sections': |
| 15 | + var $sections = context.modules.toolbar.$toolbar.find( 'div.sections' ); |
| 16 | + var $tabs = context.modules.toolbar.$toolbar.find( 'div.tabs' ); |
| 17 | + for ( section in data[type] ) { |
| 18 | + if ( section == 'main' ) { |
| 19 | + // Section |
| 20 | + context.modules.toolbar.$toolbar.prepend( |
| 21 | + $.wikiEditor.modules.toolbar.fn.buildSection( |
| 22 | + context, section, data[type][section] |
| 23 | + ) |
| 24 | + ); |
| 25 | + continue; |
| 26 | + } |
| 27 | + // Section |
| 28 | + $sections.append( |
| 29 | + $.wikiEditor.modules.toolbar.fn.buildSection( context, section, data[type][section] ) |
| 30 | + ); |
| 31 | + // Tab |
| 32 | + $tabs.append( |
| 33 | + $.wikiEditor.modules.toolbar.fn.buildTab( context, section, data[type][section] ) |
| 34 | + ); |
| 35 | + // Update visibility of section |
| 36 | + $section = $sections.find( '.section:visible' ); |
| 37 | + if ( $section.size() ) { |
| 38 | + $sections.animate( { 'height': $section.outerHeight() }, 'fast' ); |
| 39 | + } |
| 40 | + } |
| 41 | + break; |
| 42 | + case 'groups': |
| 43 | + if ( ! ( 'section' in data ) ) { |
| 44 | + continue; |
| 45 | + } |
| 46 | + var $section = context.modules.toolbar.$toolbar.find( 'div[rel=' + data.section + '].section' ); |
| 47 | + for ( group in data[type] ) { |
| 48 | + // Group |
| 49 | + $section.append( |
| 50 | + $.wikiEditor.modules.toolbar.fn.buildGroup( context, group, data[type][group] ) |
| 51 | + ); |
| 52 | + } |
| 53 | + break; |
| 54 | + case 'tools': |
| 55 | + if ( ! ( 'section' in data && 'group' in data ) ) { |
| 56 | + continue; |
| 57 | + } |
| 58 | + var $group = context.modules.toolbar.$toolbar.find( |
| 59 | + 'div[rel=' + data.section + '].section ' + 'div[rel=' + data.group + '].group' |
| 60 | + ); |
| 61 | + for ( tool in data[type] ) { |
| 62 | + // Tool |
| 63 | + $group.append( $.wikiEditor.modules.toolbar.fn.buildTool( context, tool,data[type][tool] ) ); |
| 64 | + } |
| 65 | + if ( $group.children().length ) { |
| 66 | + $group.show(); |
| 67 | + } |
| 68 | + break; |
| 69 | + case 'pages': |
| 70 | + if ( ! ( 'section' in data ) ) { |
| 71 | + continue; |
| 72 | + } |
| 73 | + var $pages = context.modules.toolbar.$toolbar.find( |
| 74 | + 'div[rel=' + data.section + '].section .pages' |
| 75 | + ); |
| 76 | + var $index = context.modules.toolbar.$toolbar.find( |
| 77 | + 'div[rel=' + data.section + '].section .index' |
| 78 | + ); |
| 79 | + for ( page in data[type] ) { |
| 80 | + // Page |
| 81 | + $pages.append( $.wikiEditor.modules.toolbar.fn.buildPage( context, page, data[type][page] ) ); |
| 82 | + // Index |
| 83 | + $index.append( |
| 84 | + $.wikiEditor.modules.toolbar.fn.buildBookmark( context, page, data[type][page] ) |
| 85 | + ); |
| 86 | + } |
| 87 | + $.wikiEditor.modules.toolbar.fn.updateBookletSelection( context, page, $pages, $index ); |
| 88 | + break; |
| 89 | + case 'rows': |
| 90 | + if ( ! ( 'section' in data && 'page' in data ) ) { |
| 91 | + continue; |
| 92 | + } |
| 93 | + var $table = context.modules.toolbar.$toolbar.find( |
| 94 | + 'div[rel=' + data.section + '].section ' + 'div[rel=' + data.page + '].page table' |
| 95 | + ); |
| 96 | + for ( row in data[type] ) { |
| 97 | + // Row |
| 98 | + $table.append( $.wikiEditor.modules.toolbar.fn.buildRow( context, data[type][row] ) ); |
| 99 | + } |
| 100 | + break; |
| 101 | + case 'characters': |
| 102 | + if ( ! ( 'section' in data && 'page' in data ) ) { |
| 103 | + continue; |
| 104 | + } |
| 105 | + $characters = context.modules.toolbar.$toolbar.find( |
| 106 | + 'div[rel=' + data.section + '].section ' + 'div[rel=' + data.page + '].page div' |
| 107 | + ); |
| 108 | + var actions = $characters.data( 'actions' ); |
| 109 | + for ( character in data[type] ) { |
| 110 | + // Character |
| 111 | + $characters |
| 112 | + .append( |
| 113 | + $( $.wikiEditor.modules.toolbar.fn.buildCharacter( data[type][character], actions ) ) |
| 114 | + .mousedown( function( e ) { |
| 115 | + context.fn.saveStuffForIE(); |
| 116 | + // No dragging! |
| 117 | + e.preventDefault(); |
| 118 | + return false; |
| 119 | + } ) |
| 120 | + .click( function( e ) { |
| 121 | + $.wikiEditor.modules.toolbar.fn.doAction( $(this).parent().data( 'context' ), |
| 122 | + $(this).parent().data( 'actions' )[$(this).attr( 'rel' )] ); |
| 123 | + e.preventDefault(); |
| 124 | + return false; |
| 125 | + } ) |
| 126 | + ); |
| 127 | + } |
| 128 | + break; |
| 129 | + default: break; |
| 130 | + } |
| 131 | + } |
| 132 | + }, |
| 133 | + removeFromToolbar : function( context, data ) { |
| 134 | + if ( typeof data.section == 'string' ) { |
| 135 | + // Section |
| 136 | + var tab = 'div.tabs span[rel=' + data.section + '].tab'; |
| 137 | + var target = 'div[rel=' + data.section + '].section'; |
| 138 | + var group = null; |
| 139 | + if ( typeof data.group == 'string' ) { |
| 140 | + // Toolbar group |
| 141 | + target += ' div[rel=' + data.group + '].group'; |
| 142 | + if ( typeof data.tool == 'string' ) { |
| 143 | + // Save for later checking if empty |
| 144 | + group = target; |
| 145 | + // Tool |
| 146 | + target += ' div[rel=' + data.tool + '].tool'; |
| 147 | + } |
| 148 | + } else if ( typeof data.page == 'string' ) { |
| 149 | + // Booklet page |
| 150 | + var index = target + ' div.index div[rel=' + data.page + ']'; |
| 151 | + target += ' div.pages div[rel=' + data.page + '].page'; |
| 152 | + if ( typeof data.character == 'string' ) { |
| 153 | + // Character |
| 154 | + target += ' a[rel=' + data.character + ']'; |
| 155 | + } else if ( typeof data.row == 'number' ) { |
| 156 | + // Table row |
| 157 | + target += ' table tr:not(:has(th)):eq(' + data.row + ')'; |
| 158 | + } else { |
| 159 | + // Just a page, remove the index too! |
| 160 | + context.modules.toolbar.$toolbar.find( index ).remove(); |
| 161 | + $.wikiEditor.modules.toolbar.fn.updateBookletSelection( |
| 162 | + context, |
| 163 | + null, |
| 164 | + context.modules.toolbar.$toolbar.find( target ), |
| 165 | + context.modules.toolbar.$toolbar.find( index ) |
| 166 | + ); |
| 167 | + } |
| 168 | + } else { |
| 169 | + // Just a section, remove the tab too! |
| 170 | + context.modules.toolbar.$toolbar.find( tab ).remove(); |
| 171 | + } |
| 172 | + context.modules.toolbar.$toolbar.find( target ).remove(); |
| 173 | + // Hide empty groups |
| 174 | + if ( group ) { |
| 175 | + $group = context.modules.toolbar.$toolbar.find( group ); |
| 176 | + if ( $group.children().length == 0 ) { |
| 177 | + $group.hide(); |
| 178 | + } |
| 179 | + } |
| 180 | + } |
| 181 | + } |
| 182 | +}, |
| 183 | +/** |
| 184 | + * Event handlers |
| 185 | + */ |
| 186 | +evt: { |
| 187 | + resize: function( context, event ) { |
| 188 | + context.$ui.find( '.sections' ).height( context.$ui.find( '.sections .section-visible' ).outerHeight() ); |
| 189 | + }, |
| 190 | + tocCollapse: function( context, event ) { |
| 191 | + $.wikiEditor.modules.toolbar.evt.resize( context, event ); |
| 192 | + }, |
| 193 | + tocExpand: function( context, event ) { |
| 194 | + $.wikiEditor.modules.toolbar.evt.resize( context, event ); |
| 195 | + } |
| 196 | +}, |
| 197 | +/** |
| 198 | + * Internally used functions |
| 199 | + */ |
| 200 | +fn: { |
| 201 | + /** |
| 202 | + * Creates a toolbar module within a wikiEditor |
| 203 | + * |
| 204 | + * @param {Object} context Context object of editor to create module in |
| 205 | + * @param {Object} config Configuration object to create module from |
| 206 | + */ |
| 207 | + create : function( context, config ) { |
| 208 | + if ( '$toolbar' in context.modules.toolbar ) { |
| 209 | + return; |
| 210 | + } |
| 211 | + context.modules.toolbar.$toolbar = $( '<div />' ) |
| 212 | + .addClass( 'wikiEditor-ui-toolbar' ) |
| 213 | + .attr( 'id', 'wikiEditor-ui-toolbar' ); |
| 214 | + $.wikiEditor.modules.toolbar.fn.build( context, config ); |
| 215 | + context.$ui.find( '.wikiEditor-ui-top' ).append( context.modules.toolbar.$toolbar ); |
| 216 | + }, |
| 217 | + /** |
| 218 | + * Performs an operation based on parameters |
| 219 | + * |
| 220 | + * @param {Object} context |
| 221 | + * @param {Object} action |
| 222 | + * @param {Object} source |
| 223 | + */ |
| 224 | + doAction : function( context, action, source ) { |
| 225 | + // Verify that this has been called from a source that's within the toolbar |
| 226 | + // 'trackAction' defined in click tracking |
| 227 | + if ( $.trackAction != undefined && source.closest( '.wikiEditor-ui-toolbar' ).size() ) { |
| 228 | + // Build a unique id for this action by tracking the parent rel attributes up to the toolbar level |
| 229 | + var rels = []; |
| 230 | + var step = source; |
| 231 | + var i = 0; |
| 232 | + while ( !step.hasClass( 'wikiEditor-ui-toolbar' ) ) { |
| 233 | + if ( i > 25 ) { |
| 234 | + break; |
| 235 | + } |
| 236 | + i++; |
| 237 | + var rel = step.attr( 'rel' ); |
| 238 | + if ( rel ) { |
| 239 | + rels.push( step.attr( 'rel' ) ); |
| 240 | + } |
| 241 | + step = step.parent(); |
| 242 | + } |
| 243 | + rels.reverse(); |
| 244 | + var id = rels.join( '.' ); |
| 245 | + $.trackAction( id ); |
| 246 | + } |
| 247 | + switch ( action.type ) { |
| 248 | + case 'replace': |
| 249 | + case 'encapsulate': |
| 250 | + var parts = { |
| 251 | + 'pre' : $.wikiEditor.autoMsg( action.options, 'pre' ), |
| 252 | + 'peri' : $.wikiEditor.autoMsg( action.options, 'peri' ), |
| 253 | + 'post' : $.wikiEditor.autoMsg( action.options, 'post' ) |
| 254 | + }; |
| 255 | + var replace = action.type == 'replace'; |
| 256 | + if ( 'regex' in action.options && 'regexReplace' in action.options ) { |
| 257 | + var selection = context.$textarea.textSelection( 'getSelection' ); |
| 258 | + if ( selection != '' && selection.match( action.options.regex ) ) { |
| 259 | + parts.peri = selection.replace( action.options.regex, |
| 260 | + action.options.regexReplace ); |
| 261 | + parts.pre = parts.post = ''; |
| 262 | + replace = true; |
| 263 | + } |
| 264 | + } |
| 265 | + context.$textarea.textSelection( |
| 266 | + 'encapsulateSelection', |
| 267 | + $.extend( {}, action.options, parts, { 'replace': replace } ) |
| 268 | + ); |
| 269 | + if ( typeof context.$iframe !== 'undefined' ) { |
| 270 | + context.$iframe[0].contentWindow.focus(); |
| 271 | + } |
| 272 | + break; |
| 273 | + case 'callback': |
| 274 | + if ( typeof action.execute == 'function' ) { |
| 275 | + action.execute( context ); |
| 276 | + } |
| 277 | + break; |
| 278 | + case 'dialog': |
| 279 | + context.fn.saveSelection(); |
| 280 | + context.$textarea.wikiEditor( 'openDialog', action.module ); |
| 281 | + break; |
| 282 | + default: break; |
| 283 | + } |
| 284 | + }, |
| 285 | + buildGroup : function( context, id, group ) { |
| 286 | + var $group = $( '<div />' ).attr( { 'class' : 'group group-' + id, 'rel' : id } ); |
| 287 | + var label = $.wikiEditor.autoMsg( group, 'label' ); |
| 288 | + if ( label ) { |
| 289 | + $group.append( '<div class="label">' + label + '</div>' ) |
| 290 | + } |
| 291 | + var empty = true; |
| 292 | + if ( 'tools' in group ) { |
| 293 | + for ( tool in group.tools ) { |
| 294 | + var tool = $.wikiEditor.modules.toolbar.fn.buildTool( context, tool, group.tools[tool] ); |
| 295 | + if ( tool ) { |
| 296 | + // Consider a group with only hidden tools empty as well |
| 297 | + // .is( ':visible' ) always returns false because tool is not attached to the DOM yet |
| 298 | + empty = empty && tool.css( 'display' ) == 'none'; |
| 299 | + $group.append( tool ); |
| 300 | + } |
| 301 | + } |
| 302 | + } |
| 303 | + if ( empty ) { |
| 304 | + $group.hide(); |
| 305 | + } |
| 306 | + return $group; |
| 307 | + }, |
| 308 | + buildTool : function( context, id, tool ) { |
| 309 | + if ( 'filters' in tool ) { |
| 310 | + for ( filter in tool.filters ) { |
| 311 | + if ( $( tool.filters[filter] ).size() == 0 ) { |
| 312 | + return null; |
| 313 | + } |
| 314 | + } |
| 315 | + } |
| 316 | + var label = $.wikiEditor.autoMsg( tool, 'label' ); |
| 317 | + switch ( tool.type ) { |
| 318 | + case 'button': |
| 319 | + var src = $.wikiEditor.autoIcon( tool.icon, $.wikiEditor.imgPath + 'toolbar/' ); |
| 320 | + var $button = null; |
| 321 | + if ( 'offset' in tool ) { |
| 322 | + var offsetOrIcon = $.wikiEditor.autoIconOrOffset( tool.icon, tool.offset, |
| 323 | + $.wikiEditor.imgPath + 'toolbar/' |
| 324 | + ); |
| 325 | + if ( typeof offsetOrIcon == 'object' ) { |
| 326 | + $button = $( '<span />' ) |
| 327 | + .attr( { |
| 328 | + 'alt' : label, |
| 329 | + 'title' : label, |
| 330 | + 'rel' : id, |
| 331 | + 'class' : 'wikiEditor-toolbar-spritedButton' |
| 332 | + } ) |
| 333 | + .text( label ) |
| 334 | + .css( 'backgroundPosition', offsetOrIcon[0] + 'px ' + offsetOrIcon[1] + 'px' ); |
| 335 | + } |
| 336 | + } |
| 337 | + if ( !$button ) { |
| 338 | + $button = $( '<img />' ) |
| 339 | + .attr( { |
| 340 | + 'src' : src, |
| 341 | + 'width' : 22, |
| 342 | + 'height' : 22, |
| 343 | + 'alt' : label, |
| 344 | + 'title' : label, |
| 345 | + 'rel' : id, |
| 346 | + 'class' : 'tool tool-button' |
| 347 | + } ); |
| 348 | + } |
| 349 | + if ( 'action' in tool ) { |
| 350 | + $button |
| 351 | + .data( 'action', tool.action ) |
| 352 | + .data( 'context', context ) |
| 353 | + .mousedown( function( e ) { |
| 354 | + context.fn.saveStuffForIE(); |
| 355 | + // No dragging! |
| 356 | + e.preventDefault(); |
| 357 | + return false; |
| 358 | + } ) |
| 359 | + .click( function( e ) { |
| 360 | + $.wikiEditor.modules.toolbar.fn.doAction( |
| 361 | + $(this).data( 'context' ), $(this).data( 'action' ), $(this) |
| 362 | + ); |
| 363 | + e.preventDefault(); |
| 364 | + return false; |
| 365 | + } ); |
| 366 | + // If the action is a dialog that hasn't been set up yet, hide the button |
| 367 | + // until the dialog is loaded |
| 368 | + if ( tool.action.type == 'dialog' && |
| 369 | + !( tool.action.module in $.wikiEditor.modules.dialogs.modules ) ) { |
| 370 | + $button.hide(); |
| 371 | + // JavaScript won't propagate the $button variable itself, it needs help |
| 372 | + context.$textarea.bind( 'wikiEditor-dialogs-setup-' + tool.action.module, |
| 373 | + { button: $button }, function( event ) { |
| 374 | + event.data.button.show().parent().show(); |
| 375 | + } ); |
| 376 | + } |
| 377 | + } |
| 378 | + return $button; |
| 379 | + case 'select': |
| 380 | + var $select = $( '<div />' ) |
| 381 | + .attr( { 'rel' : id, 'class' : 'tool tool-select' } ); |
| 382 | + var $options = $( '<div />' ).addClass( 'options' ); |
| 383 | + if ( 'list' in tool ) { |
| 384 | + for ( option in tool.list ) { |
| 385 | + var optionLabel = $.wikiEditor.autoMsg( tool.list[option], 'label' ); |
| 386 | + $options.append( |
| 387 | + $( '<a />' ) |
| 388 | + .data( 'action', tool.list[option].action ) |
| 389 | + .data( 'context', context ) |
| 390 | + .mousedown( function( e ) { |
| 391 | + context.fn.saveStuffForIE(); |
| 392 | + // No dragging! |
| 393 | + e.preventDefault(); |
| 394 | + return false; |
| 395 | + } ) |
| 396 | + .click( function( e ) { |
| 397 | + $.wikiEditor.modules.toolbar.fn.doAction( |
| 398 | + $(this).data( 'context' ), $(this).data( 'action' ), $(this) |
| 399 | + ); |
| 400 | + // Hide the dropdown |
| 401 | + // Sanity check: if this somehow gets called while the dropdown |
| 402 | + // is hidden, don't show it |
| 403 | + if ( $(this).parent().is( ':visible' ) ) { |
| 404 | + $(this).parent().animate( { 'opacity': 'toggle' }, 'fast' ); |
| 405 | + } |
| 406 | + e.preventDefault(); |
| 407 | + return false; |
| 408 | + } ) |
| 409 | + .text( optionLabel ) |
| 410 | + .addClass( 'option' ) |
| 411 | + .attr( { 'rel': option, 'href': '#' } ) |
| 412 | + ); |
| 413 | + } |
| 414 | + } |
| 415 | + $select.append( $( '<div />' ).addClass( 'menu' ).append( $options ) ); |
| 416 | + $select.append( $( '<a />' ) |
| 417 | + .addClass( 'label' ) |
| 418 | + .text( label ) |
| 419 | + .data( 'options', $options ) |
| 420 | + .attr( 'href', '#' ) |
| 421 | + .mousedown( function( e ) { |
| 422 | + // No dragging! |
| 423 | + e.preventDefault(); |
| 424 | + return false; |
| 425 | + } ) |
| 426 | + .click( function( e ) { |
| 427 | + $(this).data( 'options' ).animate( { 'opacity': 'toggle' }, 'fast' ); |
| 428 | + e.preventDefault(); |
| 429 | + return false; |
| 430 | + } ) |
| 431 | + ); |
| 432 | + return $select; |
| 433 | + default: |
| 434 | + return null; |
| 435 | + } |
| 436 | + }, |
| 437 | + buildBookmark : function( context, id, page ) { |
| 438 | + var label = $.wikiEditor.autoMsg( page, |
| 439 | + 'label' ); |
| 440 | + return $( '<div />' ) |
| 441 | + .text( label ) |
| 442 | + .attr( 'rel', id ) |
| 443 | + .data( 'context', context ) |
| 444 | + .mousedown( function( e ) { |
| 445 | + // No dragging! |
| 446 | + e.preventDefault(); |
| 447 | + return false; |
| 448 | + } ) |
| 449 | + .click( function( event ) { |
| 450 | + $(this).parent().parent().find( '.page' ).hide(); |
| 451 | + $(this).parent().parent().find( '.page-' + $(this).attr( 'rel' ) ).show(); |
| 452 | + $(this).siblings().removeClass( 'current' ); |
| 453 | + $(this).addClass( 'current' ); |
| 454 | + var section = $(this).parent().parent().attr( 'rel' ); |
| 455 | + $.cookie( |
| 456 | + 'wikiEditor-' + $(this).data( 'context' ).instance + '-booklet-' + section + '-page', |
| 457 | + $(this).attr( 'rel' ), |
| 458 | + { expires: 30, path: '/' } |
| 459 | + ); |
| 460 | + // Click tracking |
| 461 | + if($.trackAction != undefined){ |
| 462 | + $.trackAction(section + '.' + $(this).attr('rel')); |
| 463 | + } |
| 464 | + // No dragging! |
| 465 | + event.preventDefault(); |
| 466 | + return false; |
| 467 | + } ) |
| 468 | + }, |
| 469 | + buildPage : function( context, id, page ) { |
| 470 | + var $page = $( '<div />' ).attr( { |
| 471 | + 'class' : 'page page-' + id, |
| 472 | + 'rel' : id |
| 473 | + } ); |
| 474 | + switch ( page.layout ) { |
| 475 | + case 'table': |
| 476 | + $page.addClass( 'page-table' ); |
| 477 | + var html = |
| 478 | + '<table cellpadding=0 cellspacing=0 ' + 'border=0 width="100%" class="table table-' + id + '">'; |
| 479 | + if ( 'headings' in page ) { |
| 480 | + html += $.wikiEditor.modules.toolbar.fn.buildHeading( context, page.headings ) |
| 481 | + } |
| 482 | + if ( 'rows' in page ) { |
| 483 | + for ( row in page.rows ) { |
| 484 | + html += $.wikiEditor.modules.toolbar.fn.buildRow( context, page.rows[row] ) |
| 485 | + } |
| 486 | + } |
| 487 | + $page.html( html ); |
| 488 | + break; |
| 489 | + case 'characters': |
| 490 | + $page.addClass( 'page-characters' ); |
| 491 | + $characters = $( '<div />' ).data( 'context', context ).data( 'actions', {} ); |
| 492 | + var actions = $characters.data( 'actions' ); |
| 493 | + if ( 'language' in page ) { |
| 494 | + $characters.attr( 'lang', page.language ); |
| 495 | + } |
| 496 | + if ( 'direction' in page ) { |
| 497 | + $characters.attr( 'dir', page.direction ); |
| 498 | + } |
| 499 | + if ( 'characters' in page ) { |
| 500 | + var html = ''; |
| 501 | + for ( var i = 0; i < page.characters.length; i++ ) { |
| 502 | + html += $.wikiEditor.modules.toolbar.fn.buildCharacter( page.characters[i], actions ); |
| 503 | + } |
| 504 | + $characters |
| 505 | + .html( html ) |
| 506 | + .children() |
| 507 | + .mousedown( function( e ) { |
| 508 | + context.fn.saveStuffForIE(); |
| 509 | + // No dragging! |
| 510 | + e.preventDefault(); |
| 511 | + return false; |
| 512 | + } ) |
| 513 | + .click( function( e ) { |
| 514 | + $.wikiEditor.modules.toolbar.fn.doAction( |
| 515 | + $(this).parent().data( 'context' ), |
| 516 | + $(this).parent().data( 'actions' )[$(this).attr( 'rel' )], |
| 517 | + $(this) |
| 518 | + ); |
| 519 | + e.preventDefault(); |
| 520 | + return false; |
| 521 | + } ); |
| 522 | + } |
| 523 | + $page.append( $characters ); |
| 524 | + break; |
| 525 | + } |
| 526 | + return $page; |
| 527 | + }, |
| 528 | + buildHeading : function( context, headings ) { |
| 529 | + var html = '<tr>'; |
| 530 | + for ( heading in headings ) { |
| 531 | + html += '<th>' + $.wikiEditor.autoMsg( headings[heading], ['html', 'text'] ) + '</th>'; |
| 532 | + } |
| 533 | + return html; |
| 534 | + }, |
| 535 | + buildRow : function( context, row ) { |
| 536 | + var html = '<tr>'; |
| 537 | + for ( cell in row ) { |
| 538 | + html += '<td class="cell cell-' + cell + '" valign="top"><span>' + |
| 539 | + $.wikiEditor.autoMsg( row[cell], ['html', 'text'] ) + '</span></td>'; |
| 540 | + } |
| 541 | + html += '</tr>'; |
| 542 | + return html; |
| 543 | + }, |
| 544 | + buildCharacter : function( character, actions ) { |
| 545 | + if ( typeof character == 'string' ) { |
| 546 | + character = { |
| 547 | + 'label' : character, |
| 548 | + 'action' : { |
| 549 | + 'type' : 'replace', |
| 550 | + 'options' : { |
| 551 | + 'peri' : character, |
| 552 | + 'selectPeri': false |
| 553 | + } |
| 554 | + } |
| 555 | + }; |
| 556 | + } else if ( 0 in character && 1 in character ) { |
| 557 | + character = { |
| 558 | + 'label' : character[0], |
| 559 | + 'action' : { |
| 560 | + 'type' : 'replace', |
| 561 | + 'options' : { |
| 562 | + 'peri' : character[1], |
| 563 | + 'selectPeri': false |
| 564 | + } |
| 565 | + } |
| 566 | + }; |
| 567 | + } |
| 568 | + if ( 'action' in character && 'label' in character ) { |
| 569 | + actions[character.label] = character.action; |
| 570 | + return '<span rel="' + character.label + '">' + character.label + '</span>'; |
| 571 | + } |
| 572 | + }, |
| 573 | + buildTab : function( context, id, section ) { |
| 574 | + var selected = $.cookie( 'wikiEditor-' + context.instance + '-toolbar-section' ); |
| 575 | + // Re-save cookie |
| 576 | + if ( selected != null ) { |
| 577 | + $.cookie( 'wikiEditor-' + context.instance + '-toolbar-section', selected, { expires: 30, path: '/' } ); |
| 578 | + } |
| 579 | + return $( '<span />' ) |
| 580 | + .attr( { 'class' : 'tab tab-' + id, 'rel' : id } ) |
| 581 | + .append( |
| 582 | + $( '<a />' ) |
| 583 | + .addClass( selected == id ? 'current' : null ) |
| 584 | + .attr( 'href', '#' ) |
| 585 | + .text( $.wikiEditor.autoMsg( section, 'label' ) ) |
| 586 | + .data( 'context', context ) |
| 587 | + .mouseup( function( e ) { |
| 588 | + $(this).blur(); |
| 589 | + } ) |
| 590 | + .mousedown( function( e ) { |
| 591 | + // No dragging! |
| 592 | + e.preventDefault(); |
| 593 | + return false; |
| 594 | + } ) |
| 595 | + .click( function( e ) { |
| 596 | + var $sections = $(this).data( 'context' ).$ui.find( '.sections' ); |
| 597 | + var $section = |
| 598 | + $(this).data( 'context' ).$ui.find( '.section-' + $(this).parent().attr( 'rel' ) ); |
| 599 | + var show = $section.css( 'display' ) == 'none'; |
| 600 | + $previousSections = $section.parent().find( '.section-visible' ); |
| 601 | + $previousSections.css( 'position', 'absolute' ); |
| 602 | + $previousSections.removeClass( 'section-visible' ); |
| 603 | + $previousSections.fadeOut( 'fast', function() { $(this).css( 'position', 'relative' ); } ); |
| 604 | + $(this).parent().parent().find( 'a' ).removeClass( 'current' ); |
| 605 | + $sections.css( 'overflow', 'hidden' ); |
| 606 | + function animate( $this ) { |
| 607 | + $sections |
| 608 | + .css( 'display', 'block' ) |
| 609 | + .animate( { 'height': $section.outerHeight() }, $section.outerHeight() * 2, function() { |
| 610 | + $( this ).css( 'overflow', 'visible' ).css( 'height', 'auto' ); |
| 611 | + context.fn.trigger( 'resize' ); |
| 612 | + } ); |
| 613 | + } |
| 614 | + if ( show ) { |
| 615 | + $section.addClass( 'section-visible' ); |
| 616 | + $section.fadeIn( 'fast' ); |
| 617 | + if ( $section.hasClass( 'loading' ) ) { |
| 618 | + // Loading of this section was deferred, load it now |
| 619 | + var $this = $(this); |
| 620 | + $this.addClass( 'current loading' ); |
| 621 | + setTimeout( function() { |
| 622 | + $section.trigger( 'loadSection' ); |
| 623 | + animate( $(this) ); |
| 624 | + $this.removeClass( 'loading' ); |
| 625 | + }, 1000 ); |
| 626 | + } else { |
| 627 | + animate( $(this) ); |
| 628 | + $(this).addClass( 'current' ); |
| 629 | + } |
| 630 | + } else { |
| 631 | + $sections |
| 632 | + .css( 'height', $section.outerHeight() ) |
| 633 | + .animate( { 'height': 'hide' }, $section.outerHeight() * 2, function() { |
| 634 | + $(this).css( { 'overflow': 'visible', 'height': 0 } ); |
| 635 | + context.fn.trigger( 'resize' ); |
| 636 | + } ); |
| 637 | + } |
| 638 | + // Click tracking |
| 639 | + if ( $.trackAction != undefined ) { |
| 640 | + $.trackAction( $section.attr('rel') + '.' + ( show ? 'show': 'hide' ) ); |
| 641 | + } |
| 642 | + // Save the currently visible section |
| 643 | + $.cookie( |
| 644 | + 'wikiEditor-' + $(this).data( 'context' ).instance + '-toolbar-section', |
| 645 | + show ? $section.attr( 'rel' ) : null, |
| 646 | + { expires: 30, path: '/' } |
| 647 | + ); |
| 648 | + e.preventDefault(); |
| 649 | + return false; |
| 650 | + } ) |
| 651 | + ); |
| 652 | + }, |
| 653 | + buildSection: function( context, id, section ) { |
| 654 | + var $section = $( '<div />' ).attr( { 'class': section.type + ' section section-' + id, 'rel': id } ); |
| 655 | + var selected = $.cookie( 'wikiEditor-' + context.instance + '-toolbar-section' ); |
| 656 | + var show = selected == id; |
| 657 | + |
| 658 | + if ( typeof section.deferLoad != 'undefined' && section.deferLoad && id !== 'main' && !show ) { |
| 659 | + // This class shows the spinner and serves as a marker for the click handler in buildTab() |
| 660 | + $section.addClass( 'loading' ).append( $( '<div />' ).addClass( 'spinner' ) ); |
| 661 | + $section.bind( 'loadSection', function() { |
| 662 | + $.wikiEditor.modules.toolbar.fn.reallyBuildSection( context, id, section, $section ); |
| 663 | + $section.removeClass( 'loading' ); |
| 664 | + } ); |
| 665 | + } else { |
| 666 | + $.wikiEditor.modules.toolbar.fn.reallyBuildSection( context, id, section, $section ); |
| 667 | + } |
| 668 | + |
| 669 | + // Show or hide section |
| 670 | + if ( id !== 'main' ) { |
| 671 | + $section.css( 'display', show ? 'block' : 'none' ); |
| 672 | + if ( show ) |
| 673 | + $section.addClass( 'section-visible' ); |
| 674 | + } |
| 675 | + return $section; |
| 676 | + }, |
| 677 | + reallyBuildSection: function( context, id, section, $section ) { |
| 678 | + context.$textarea.trigger( 'wikiEditor-toolbar-buildSection-' + $section.attr( 'rel' ), [section] ); |
| 679 | + switch ( section.type ) { |
| 680 | + case 'toolbar': |
| 681 | + if ( 'groups' in section ) { |
| 682 | + for ( group in section.groups ) { |
| 683 | + $section.append( |
| 684 | + $.wikiEditor.modules.toolbar.fn.buildGroup( context, group, section.groups[group] ) |
| 685 | + ); |
| 686 | + } |
| 687 | + } |
| 688 | + break; |
| 689 | + case 'booklet': |
| 690 | + var $pages = $( '<div />' ).addClass( 'pages' ); |
| 691 | + var $index = $( '<div />' ).addClass( 'index' ); |
| 692 | + if ( 'pages' in section ) { |
| 693 | + for ( page in section.pages ) { |
| 694 | + $pages.append( |
| 695 | + $.wikiEditor.modules.toolbar.fn.buildPage( context, page, section.pages[page] ) |
| 696 | + ); |
| 697 | + $index.append( |
| 698 | + $.wikiEditor.modules.toolbar.fn.buildBookmark( context, page, section.pages[page] ) |
| 699 | + ); |
| 700 | + } |
| 701 | + } |
| 702 | + $section.append( $index ).append( $pages ); |
| 703 | + $.wikiEditor.modules.toolbar.fn.updateBookletSelection( context, id, $pages, $index ); |
| 704 | + break; |
| 705 | + } |
| 706 | + }, |
| 707 | + updateBookletSelection : function( context, id, $pages, $index ) { |
| 708 | + var cookie = 'wikiEditor-' + context.instance + '-booklet-' + id + '-page'; |
| 709 | + var selected = $.cookie( cookie ); |
| 710 | + // Re-save cookie |
| 711 | + if ( selected != null ) { |
| 712 | + $.cookie( cookie, selected, { expires: 30, path: '/' } ); |
| 713 | + } |
| 714 | + var $selectedIndex = $index.find( '*[rel=' + selected + ']' ); |
| 715 | + if ( $selectedIndex.size() == 0 ) { |
| 716 | + selected = $index.children().eq( 0 ).attr( 'rel' ); |
| 717 | + $.cookie( cookie, selected, { expires: 30, path: '/' } ); |
| 718 | + } |
| 719 | + $pages.children().hide(); |
| 720 | + $pages.find( '*[rel=' + selected + ']' ).show(); |
| 721 | + $index.children().removeClass( 'current' ); |
| 722 | + $selectedIndex.addClass( 'current' ); |
| 723 | + }, |
| 724 | + build : function( context, config ) { |
| 725 | + var $tabs = $( '<div />' ).addClass( 'tabs' ).appendTo( context.modules.toolbar.$toolbar ); |
| 726 | + var $sections = $( '<div />' ).addClass( 'sections' ).appendTo( context.modules.toolbar.$toolbar ); |
| 727 | + context.modules.toolbar.$toolbar.append( $( '<div />' ).css( 'clear', 'both' ) ); |
| 728 | + var sectionQueue = []; |
| 729 | + for ( section in config ) { |
| 730 | + if ( section == 'main' ) { |
| 731 | + context.modules.toolbar.$toolbar.prepend( |
| 732 | + $.wikiEditor.modules.toolbar.fn.buildSection( context, section, config[section] ) |
| 733 | + ); |
| 734 | + } else { |
| 735 | + sectionQueue.push( { |
| 736 | + '$sections' : $sections, |
| 737 | + 'context' : context, |
| 738 | + 'id' : section, |
| 739 | + 'config' : config[section] |
| 740 | + } ); |
| 741 | + $tabs.append( $.wikiEditor.modules.toolbar.fn.buildTab( context, section, config[section] ) ); |
| 742 | + } |
| 743 | + } |
| 744 | + $.eachAsync( sectionQueue, { |
| 745 | + 'bulk' : 0, |
| 746 | + 'end' : function() { |
| 747 | + // HACK: Opera doesn't seem to want to redraw after these bits |
| 748 | + // are added to the DOM, so we can just FORCE it! |
| 749 | + var oldValue = $( 'body' ).css( 'position' ); |
| 750 | + $( 'body' ).css( 'position', 'static' ); |
| 751 | + $( 'body' ).css( 'position', oldValue ); |
| 752 | + }, |
| 753 | + 'loop' : function( i, s ) { |
| 754 | + s.$sections.append( $.wikiEditor.modules.toolbar.fn.buildSection( s.context, s.id, s.config ) ); |
| 755 | + var $section = s.$sections.find( '.section:visible' ); |
| 756 | + if ( $section.size() ) { |
| 757 | + $sections.animate( { 'height': $section.outerHeight() }, $section.outerHeight() * 2, function( ) { |
| 758 | + context.fn.trigger( 'resize' ); |
| 759 | + } ); |
| 760 | + } |
| 761 | + } |
| 762 | + } ); |
| 763 | + } |
| 764 | +} |
| 765 | + |
| 766 | +}; } )( jQuery ); |
Property changes on: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.toolbar.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 767 | + native |
Index: trunk/extensions/WikiEditor/modules/images/dialogs/close_x.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/dialogs/close_x.png |
___________________________________________________________________ |
Added: svn:mime-type |
2 | 768 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/dialogs/insert-link-exists.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/dialogs/insert-link-exists.png |
___________________________________________________________________ |
Added: svn:mime-type |
3 | 769 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/dialogs/insert-link-notexists.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/dialogs/insert-link-notexists.png |
___________________________________________________________________ |
Added: svn:mime-type |
4 | 770 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/dialogs/insert-link-external-rtl.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/dialogs/insert-link-external-rtl.png |
___________________________________________________________________ |
Added: svn:mime-type |
5 | 771 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/dialogs/loading.gif |
Cannot display: file marked as a binary type. |
svn:mime-type = image/gif |
Property changes on: trunk/extensions/WikiEditor/modules/images/dialogs/loading.gif |
___________________________________________________________________ |
Added: svn:mime-type |
6 | 772 | + image/gif |
Index: trunk/extensions/WikiEditor/modules/images/dialogs/insert-link-external.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/dialogs/insert-link-external.png |
___________________________________________________________________ |
Added: svn:mime-type |
7 | 773 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/dialogs/button_disabled.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/dialogs/button_disabled.png |
___________________________________________________________________ |
Added: svn:mime-type |
8 | 774 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/dialogs/button_down.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/dialogs/button_down.png |
___________________________________________________________________ |
Added: svn:mime-type |
9 | 775 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/dialogs/insert-link-invalid.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/dialogs/insert-link-invalid.png |
___________________________________________________________________ |
Added: svn:mime-type |
10 | 776 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/dialogs/button_off.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/dialogs/button_off.png |
___________________________________________________________________ |
Added: svn:mime-type |
11 | 777 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/dialogs/titlebar_fade.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/dialogs/titlebar_fade.png |
___________________________________________________________________ |
Added: svn:mime-type |
12 | 778 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/dialogs/button_over.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/dialogs/button_over.png |
___________________________________________________________________ |
Added: svn:mime-type |
13 | 779 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/dialogs/insert-link-error.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/dialogs/insert-link-error.png |
___________________________________________________________________ |
Added: svn:mime-type |
14 | 780 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/templateEditor/text-base.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/templateEditor/text-base.png |
___________________________________________________________________ |
Added: svn:mime-type |
15 | 781 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/templateEditor/expand.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/templateEditor/expand.png |
___________________________________________________________________ |
Added: svn:mime-type |
16 | 782 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/templateEditor/collapse.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/templateEditor/collapse.png |
___________________________________________________________________ |
Added: svn:mime-type |
17 | 783 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/templateEditor/dialog-collapsed.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/templateEditor/dialog-collapsed.png |
___________________________________________________________________ |
Added: svn:mime-type |
18 | 784 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/templateEditor/dialog-expanded.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/templateEditor/dialog-expanded.png |
___________________________________________________________________ |
Added: svn:mime-type |
19 | 785 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/templateEditor/wiki-text.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/templateEditor/wiki-text.png |
___________________________________________________________________ |
Added: svn:mime-type |
20 | 786 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/templateEditor/name-base.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/templateEditor/name-base.png |
___________________________________________________________________ |
Added: svn:mime-type |
21 | 787 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/loading.gif |
Cannot display: file marked as a binary type. |
svn:mime-type = image/gif |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/loading.gif |
___________________________________________________________________ |
Added: svn:mime-type |
22 | 788 | + image/gif |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-bold-ka.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-bold-ka.png |
___________________________________________________________________ |
Added: svn:mime-type |
23 | 789 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/insert-link.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/insert-link.png |
___________________________________________________________________ |
Added: svn:mime-type |
24 | 790 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/insert-reference.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/insert-reference.png |
___________________________________________________________________ |
Added: svn:mime-type |
25 | 791 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/insert-redirect.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/insert-redirect.png |
___________________________________________________________________ |
Added: svn:mime-type |
26 | 792 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/insert-signature.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/insert-signature.png |
___________________________________________________________________ |
Added: svn:mime-type |
27 | 793 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-subscript.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-subscript.png |
___________________________________________________________________ |
Added: svn:mime-type |
28 | 794 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/loading-small.gif |
Cannot display: file marked as a binary type. |
svn:mime-type = image/gif |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/loading-small.gif |
___________________________________________________________________ |
Added: svn:mime-type |
29 | 795 | + image/gif |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/arrow-right.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/arrow-right.png |
___________________________________________________________________ |
Added: svn:mime-type |
30 | 796 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-bold.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-bold.png |
___________________________________________________________________ |
Added: svn:mime-type |
31 | 797 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-indent.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-indent.png |
___________________________________________________________________ |
Added: svn:mime-type |
32 | 798 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-superscript.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-superscript.png |
___________________________________________________________________ |
Added: svn:mime-type |
33 | 799 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-italic-A.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-italic-A.png |
___________________________________________________________________ |
Added: svn:mime-type |
34 | 800 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-italic-C.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-italic-C.png |
___________________________________________________________________ |
Added: svn:mime-type |
35 | 801 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/example-image.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/example-image.png |
___________________________________________________________________ |
Added: svn:mime-type |
36 | 802 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-italic-D.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-italic-D.png |
___________________________________________________________________ |
Added: svn:mime-type |
37 | 803 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/button-sprite.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/button-sprite.png |
___________________________________________________________________ |
Added: svn:mime-type |
38 | 804 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-italic-I.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-italic-I.png |
___________________________________________________________________ |
Added: svn:mime-type |
39 | 805 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-italic-K.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-italic-K.png |
___________________________________________________________________ |
Added: svn:mime-type |
40 | 806 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-bold-A.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-bold-A.png |
___________________________________________________________________ |
Added: svn:mime-type |
41 | 807 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-italic-ka.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-italic-ka.png |
___________________________________________________________________ |
Added: svn:mime-type |
42 | 808 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-bold-B.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-bold-B.png |
___________________________________________________________________ |
Added: svn:mime-type |
43 | 809 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-bold-F.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-bold-F.png |
___________________________________________________________________ |
Added: svn:mime-type |
44 | 810 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-bold-G.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-bold-G.png |
___________________________________________________________________ |
Added: svn:mime-type |
45 | 811 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-small.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-small.png |
___________________________________________________________________ |
Added: svn:mime-type |
46 | 812 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/arrow-down.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/arrow-down.png |
___________________________________________________________________ |
Added: svn:mime-type |
47 | 813 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-bold-N.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-bold-N.png |
___________________________________________________________________ |
Added: svn:mime-type |
48 | 814 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/insert-gallery.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/insert-gallery.png |
___________________________________________________________________ |
Added: svn:mime-type |
49 | 815 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/insert-nowiki.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/insert-nowiki.png |
___________________________________________________________________ |
Added: svn:mime-type |
50 | 816 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/insert-newline.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/insert-newline.png |
___________________________________________________________________ |
Added: svn:mime-type |
51 | 817 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-bold-P.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-bold-P.png |
___________________________________________________________________ |
Added: svn:mime-type |
52 | 818 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/insert-link.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/insert-link.png |
___________________________________________________________________ |
Added: svn:mime-type |
53 | 819 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/insert-reference.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/insert-reference.png |
___________________________________________________________________ |
Added: svn:mime-type |
54 | 820 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/insert-signature.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/insert-signature.png |
___________________________________________________________________ |
Added: svn:mime-type |
55 | 821 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/insert-redirect.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/insert-redirect.png |
___________________________________________________________________ |
Added: svn:mime-type |
56 | 822 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-subscript.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-subscript.png |
___________________________________________________________________ |
Added: svn:mime-type |
57 | 823 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/arrow-right.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/arrow-right.png |
___________________________________________________________________ |
Added: svn:mime-type |
58 | 824 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-bold.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-bold.png |
___________________________________________________________________ |
Added: svn:mime-type |
59 | 825 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-superscript.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-superscript.png |
___________________________________________________________________ |
Added: svn:mime-type |
60 | 826 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-italic-A.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-italic-A.png |
___________________________________________________________________ |
Added: svn:mime-type |
61 | 827 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-italic-C.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-italic-C.png |
___________________________________________________________________ |
Added: svn:mime-type |
62 | 828 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-italic-I.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-italic-I.png |
___________________________________________________________________ |
Added: svn:mime-type |
63 | 829 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-italic-K.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-italic-K.png |
___________________________________________________________________ |
Added: svn:mime-type |
64 | 830 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-bold-A.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-bold-A.png |
___________________________________________________________________ |
Added: svn:mime-type |
65 | 831 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-bold-B.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-bold-B.png |
___________________________________________________________________ |
Added: svn:mime-type |
66 | 832 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-bold-F.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-bold-F.png |
___________________________________________________________________ |
Added: svn:mime-type |
67 | 833 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-bold-G.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-bold-G.png |
___________________________________________________________________ |
Added: svn:mime-type |
68 | 834 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-small.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-small.png |
___________________________________________________________________ |
Added: svn:mime-type |
69 | 835 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/arrow-down.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/arrow-down.png |
___________________________________________________________________ |
Added: svn:mime-type |
70 | 836 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-bold-N.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-bold-N.png |
___________________________________________________________________ |
Added: svn:mime-type |
71 | 837 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/insert-gallery.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/insert-gallery.png |
___________________________________________________________________ |
Added: svn:mime-type |
72 | 838 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/insert-nowiki.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/insert-nowiki.png |
___________________________________________________________________ |
Added: svn:mime-type |
73 | 839 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-bold-P.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-bold-P.png |
___________________________________________________________________ |
Added: svn:mime-type |
74 | 840 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/insert-newline.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/insert-newline.png |
___________________________________________________________________ |
Added: svn:mime-type |
75 | 841 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-bold-V.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-bold-V.png |
___________________________________________________________________ |
Added: svn:mime-type |
76 | 842 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/search-replace.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/search-replace.png |
___________________________________________________________________ |
Added: svn:mime-type |
77 | 843 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-olist.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-olist.png |
___________________________________________________________________ |
Added: svn:mime-type |
78 | 844 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/generate.sh |
— | — | @@ -0,0 +1,12 @@ |
| 2 | +#! /bin/bash |
| 3 | + |
| 4 | +# Compresses all PNGs in the current directory and puts the compressed |
| 5 | +# version in the parent directory |
| 6 | +# |
| 7 | +# Requires pngcrush |
| 8 | + |
| 9 | +for f in *.png |
| 10 | +do |
| 11 | + pngcrush $f ../$f |
| 12 | +done |
| 13 | + |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/generate.sh |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 14 | + native |
Added: svn:executable |
2 | 15 | + * |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/insert-file.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/insert-file.png |
___________________________________________________________________ |
Added: svn:mime-type |
3 | 16 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/arrow-left.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/arrow-left.png |
___________________________________________________________________ |
Added: svn:mime-type |
4 | 17 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-ulist.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-ulist.png |
___________________________________________________________________ |
Added: svn:mime-type |
5 | 18 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-big.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-big.png |
___________________________________________________________________ |
Added: svn:mime-type |
6 | 19 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/insert-table.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/insert-table.png |
___________________________________________________________________ |
Added: svn:mime-type |
7 | 20 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-italic.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/png24/format-italic.png |
___________________________________________________________________ |
Added: svn:mime-type |
8 | 21 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/insert-ilink.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/insert-ilink.png |
___________________________________________________________________ |
Added: svn:mime-type |
9 | 22 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-bold-V.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-bold-V.png |
___________________________________________________________________ |
Added: svn:mime-type |
10 | 23 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/base.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/base.png |
___________________________________________________________________ |
Added: svn:mime-type |
11 | 24 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/search-replace.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/search-replace.png |
___________________________________________________________________ |
Added: svn:mime-type |
12 | 25 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/magnify-clip.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/magnify-clip.png |
___________________________________________________________________ |
Added: svn:mime-type |
13 | 26 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-olist.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-olist.png |
___________________________________________________________________ |
Added: svn:mime-type |
14 | 27 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/insert-file.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/insert-file.png |
___________________________________________________________________ |
Added: svn:mime-type |
15 | 28 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/arrow-left.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/arrow-left.png |
___________________________________________________________________ |
Added: svn:mime-type |
16 | 29 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-ulist.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-ulist.png |
___________________________________________________________________ |
Added: svn:mime-type |
17 | 30 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-big.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-big.png |
___________________________________________________________________ |
Added: svn:mime-type |
18 | 31 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/insert-xlink.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/insert-xlink.png |
___________________________________________________________________ |
Added: svn:mime-type |
19 | 32 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/insert-table.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/insert-table.png |
___________________________________________________________________ |
Added: svn:mime-type |
20 | 33 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-bold-ru.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-bold-ru.png |
___________________________________________________________________ |
Added: svn:mime-type |
21 | 34 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toolbar/format-italic.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toolbar/format-italic.png |
___________________________________________________________________ |
Added: svn:mime-type |
22 | 35 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toc/grip.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toc/grip.png |
___________________________________________________________________ |
Added: svn:mime-type |
23 | 36 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toc/open.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toc/open.png |
___________________________________________________________________ |
Added: svn:mime-type |
24 | 37 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toc/close.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toc/close.png |
___________________________________________________________________ |
Added: svn:mime-type |
25 | 38 | + image/png |
Index: trunk/extensions/WikiEditor/modules/images/toc/grab.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/WikiEditor/modules/images/toc/grab.png |
___________________________________________________________________ |
Added: svn:mime-type |
26 | 39 | + image/png |
Index: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.publish.js |
— | — | @@ -0,0 +1,146 @@ |
| 2 | +/* Publish module for wikiEditor */ |
| 3 | +( function( $ ) { $.wikiEditor.modules.publish = { |
| 4 | + |
| 5 | +/** |
| 6 | + * Compatability map |
| 7 | + */ |
| 8 | +'browsers': { |
| 9 | + // Left-to-right languages |
| 10 | + 'ltr': { |
| 11 | + 'msie': [['>=', 7]], |
| 12 | + 'firefox': [['>=', 3]], |
| 13 | + 'opera': [['>=', 9.6]], |
| 14 | + 'safari': [['>=', 4]] |
| 15 | + }, |
| 16 | + // Right-to-left languages |
| 17 | + 'rtl': { |
| 18 | + 'msie': [['>=', 8]], |
| 19 | + 'firefox': [['>=', 3]], |
| 20 | + 'opera': [['>=', 9.6]], |
| 21 | + 'safari': [['>=', 4]] |
| 22 | + } |
| 23 | +}, |
| 24 | +/** |
| 25 | + * Internally used functions |
| 26 | + */ |
| 27 | +fn: { |
| 28 | + /** |
| 29 | + * Creates a publish module within a wikiEditor |
| 30 | + * @param context Context object of editor to create module in |
| 31 | + * @param config Configuration object to create module from |
| 32 | + */ |
| 33 | + create: function( context, config ) { |
| 34 | + // Build the dialog behind the Publish button |
| 35 | + var dialogID = 'wikiEditor-' + context.instance + '-dialog'; |
| 36 | + $.wikiEditor.modules.dialogs.fn.create( |
| 37 | + context, |
| 38 | + { |
| 39 | + previewsave: { |
| 40 | + id: dialogID, |
| 41 | + titleMsg: 'wikieditor-publish-dialog-title', |
| 42 | + html: '\ |
| 43 | + <div class="wikiEditor-publish-dialog-copywarn"></div>\ |
| 44 | + <div class="wikiEditor-publish-dialog-editoptions">\ |
| 45 | + <form id="wikieditor-' + context.instance + '-publish-dialog-form">\ |
| 46 | + <div class="wikiEditor-publish-dialog-summary">\ |
| 47 | + <label for="wikiEditor-' + context.instance + '-dialog-summary"\ |
| 48 | + rel="wikieditor-publish-dialog-summary"></label>\ |
| 49 | + <br />\ |
| 50 | + <input type="text" id="wikiEditor-' + context.instance + '-dialog-summary"\ |
| 51 | + style="width: 100%;" />\ |
| 52 | + </div>\ |
| 53 | + <div class="wikiEditor-publish-dialog-options">\ |
| 54 | + <input type="checkbox"\ |
| 55 | + id="wikiEditor-' + context.instance + '-dialog-minor" />\ |
| 56 | + <label for="wikiEditor-' + context.instance + '-dialog-minor"\ |
| 57 | + rel="wikieditor-publish-dialog-minor"></label>\ |
| 58 | + <input type="checkbox"\ |
| 59 | + id="wikiEditor-' + context.instance + '-dialog-watch" />\ |
| 60 | + <label for="wikiEditor-' + context.instance + '-dialog-watch"\ |
| 61 | + rel="wikieditor-publish-dialog-watch"></label>\ |
| 62 | + </div>\ |
| 63 | + </form>\ |
| 64 | + </div>', |
| 65 | + init: function() { |
| 66 | + $(this).find( '[rel]' ).each( function() { |
| 67 | + $(this).text( mw.usability.getMsg( $(this).attr( 'rel' ) ) ); |
| 68 | + }); |
| 69 | + |
| 70 | + /* REALLY DIRTY HACK! */ |
| 71 | + // Reformat the copyright warning stuff |
| 72 | + var copyWarnHTML = $( '#editpage-copywarn p' ).html(); |
| 73 | + // TODO: internationalize by splitting on other characters that end statements |
| 74 | + var copyWarnStatements = copyWarnHTML.split( '. ' ); |
| 75 | + var newCopyWarnHTML = '<ul>'; |
| 76 | + for ( var i = 0; i < copyWarnStatements.length; i++ ) { |
| 77 | + if ( copyWarnStatements[i] != '' ) { |
| 78 | + var copyWarnStatement = $j.trim( copyWarnStatements[i] ).replace( /\.*$/, '' ); |
| 79 | + newCopyWarnHTML += '<li>' + copyWarnStatement + '.</li>'; |
| 80 | + } |
| 81 | + } |
| 82 | + newCopyWarnHTML += '</ul>'; |
| 83 | + // No list if there's only one element |
| 84 | + $(this).find( '.wikiEditor-publish-dialog-copywarn' ).html( |
| 85 | + copyWarnStatements.length > 1 ? newCopyWarnHTML : copyWarnHTML |
| 86 | + ); |
| 87 | + /* END OF REALLY DIRTY HACK */ |
| 88 | + |
| 89 | + if ( $( '#wpMinoredit' ).size() == 0 ) |
| 90 | + $( '#wikiEditor-' + context.instance + '-dialog-minor' ).hide(); |
| 91 | + else if ( $( '#wpMinoredit' ).is( ':checked' ) ) |
| 92 | + $( '#wikiEditor-' + context.instance + '-dialog-minor' ) |
| 93 | + .attr( 'checked', 'checked' ); |
| 94 | + if ( $( '#wpWatchthis' ).size() == 0 ) |
| 95 | + $( '#wikiEditor-' + context.instance + '-dialog-watch' ).hide(); |
| 96 | + else if ( $( '#wpWatchthis' ).is( ':checked' ) ) |
| 97 | + $( '#wikiEditor-' + context.instance + '-dialog-watch' ) |
| 98 | + .attr( 'checked', 'checked' ); |
| 99 | + |
| 100 | + $(this).find( 'form' ).submit( function( e ) { |
| 101 | + $(this).closest( '.ui-dialog' ).find( 'button:first' ).click(); |
| 102 | + e.preventDefault(); |
| 103 | + }); |
| 104 | + }, |
| 105 | + dialog: { |
| 106 | + buttons: { |
| 107 | + 'wikieditor-publish-dialog-publish': function() { |
| 108 | + var minorChecked = $( '#wikiEditor-' + context.instance + |
| 109 | + '-dialog-minor' ).is( ':checked' ) ? |
| 110 | + 'checked' : ''; |
| 111 | + var watchChecked = $( '#wikiEditor-' + context.instance + |
| 112 | + '-dialog-watch' ).is( ':checked' ) ? |
| 113 | + 'checked' : ''; |
| 114 | + $( '#wpMinoredit' ).attr( 'checked', minorChecked ); |
| 115 | + $( '#wpWatchthis' ).attr( 'checked', watchChecked ); |
| 116 | + $( '#wpSummary' ).val( $j( '#wikiEditor-' + context.instance + |
| 117 | + '-dialog-summary' ).val() ); |
| 118 | + $( '#editform' ).submit(); |
| 119 | + }, |
| 120 | + 'wikieditor-publish-dialog-goback': function() { |
| 121 | + $(this).dialog( 'close' ); |
| 122 | + } |
| 123 | + }, |
| 124 | + open: function() { |
| 125 | + $( '#wikiEditor-' + context.instance + '-dialog-summary' ).focus(); |
| 126 | + }, |
| 127 | + width: 500 |
| 128 | + }, |
| 129 | + resizeme: false |
| 130 | + } |
| 131 | + } |
| 132 | + ); |
| 133 | + context.fn.addButton( { |
| 134 | + 'captionMsg': 'wikieditor-publish-button-publish', |
| 135 | + 'action': function() { |
| 136 | + $( '#' + dialogID ).dialog( 'open' ); |
| 137 | + return false; |
| 138 | + } |
| 139 | + } ); |
| 140 | + context.fn.addButton( { |
| 141 | + 'captionMsg': 'wikieditor-publish-button-cancel', |
| 142 | + 'action': function() { } |
| 143 | + } ); |
| 144 | + } |
| 145 | +} |
| 146 | + |
| 147 | +}; } )( jQuery ); |
Property changes on: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.publish.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 148 | + native |
Index: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.highlight.js |
— | — | @@ -0,0 +1,357 @@ |
| 2 | +/* Highlight module for wikiEditor */ |
| 3 | + |
| 4 | +( function( $ ) { $.wikiEditor.modules.highlight = { |
| 5 | + |
| 6 | +/** |
| 7 | + * Core Requirements |
| 8 | + */ |
| 9 | +'req': [ 'iframe' ], |
| 10 | +/** |
| 11 | + * Configuration |
| 12 | + */ |
| 13 | +'cfg': { |
| 14 | + 'styleVersion': 3 |
| 15 | +}, |
| 16 | +/** |
| 17 | + * Internally used event handlers |
| 18 | + */ |
| 19 | +'evt': { |
| 20 | + 'delayedChange': function( context, event ) { |
| 21 | + if ( event.data.scope == 'realchange' ) { |
| 22 | + $.wikiEditor.modules.highlight.fn.scan( context ); |
| 23 | + $.wikiEditor.modules.highlight.fn.mark( context, event.data.scope ); |
| 24 | + } |
| 25 | + }, |
| 26 | + 'ready': function( context, event ) { |
| 27 | + $.wikiEditor.modules.highlight.fn.scan( context ); |
| 28 | + $.wikiEditor.modules.highlight.fn.mark( context, 'ready' ); |
| 29 | + } |
| 30 | +}, |
| 31 | +/** |
| 32 | + * Internally used functions |
| 33 | + */ |
| 34 | +'fn': { |
| 35 | + /** |
| 36 | + * Creates a highlight module within a wikiEditor |
| 37 | + * |
| 38 | + * @param config Configuration object to create module from |
| 39 | + */ |
| 40 | + 'create': function( context, config ) { |
| 41 | + context.modules.highlight.markersStr = ''; |
| 42 | + }, |
| 43 | + /** |
| 44 | + * Scans text division for tokens |
| 45 | + * |
| 46 | + * @param division |
| 47 | + */ |
| 48 | + 'scan': function( context, division ) { |
| 49 | + // Remove all existing tokens |
| 50 | + var tokenArray = context.modules.highlight.tokenArray = []; |
| 51 | + // Scan text for new tokens |
| 52 | + var text = context.fn.getContents(); |
| 53 | + // Perform a scan for each module which provides any expressions to scan for |
| 54 | + // FIXME: This traverses the entire string once for every regex. Investigate |
| 55 | + // whether |-concatenating regexes then traversing once is faster. |
| 56 | + for ( var module in context.modules ) { |
| 57 | + if ( module in $.wikiEditor.modules && 'exp' in $.wikiEditor.modules[module] ) { |
| 58 | + for ( var exp in $.wikiEditor.modules[module].exp ) { |
| 59 | + // Prepare configuration |
| 60 | + var regex = $.wikiEditor.modules[module].exp[exp].regex; |
| 61 | + var label = $.wikiEditor.modules[module].exp[exp].label; |
| 62 | + var markAfter = $.wikiEditor.modules[module].exp[exp].markAfter || false; |
| 63 | + // Search for tokens |
| 64 | + var offset = 0, left, right, match; |
| 65 | + while ( ( match = text.substr( offset ).match( regex ) ) != null ) { |
| 66 | + right = ( left = offset + match.index ) + match[0].length; |
| 67 | + tokenArray[tokenArray.length] = { |
| 68 | + 'offset': markAfter ? right : left, |
| 69 | + 'label': label, |
| 70 | + 'tokenStart': left, |
| 71 | + 'match': match |
| 72 | + }; |
| 73 | + // Move to the right of this match |
| 74 | + offset = right; |
| 75 | + } |
| 76 | + } |
| 77 | + } |
| 78 | + } |
| 79 | + // Sort by start |
| 80 | + tokenArray.sort( function( a, b ) { return a.tokenStart - b.tokenStart; } ); |
| 81 | + // Let the world know, a scan just happened! |
| 82 | + context.fn.trigger( 'scan' ); |
| 83 | + }, |
| 84 | + /** |
| 85 | + * Marks up text with HTML |
| 86 | + * |
| 87 | + * @param division |
| 88 | + * @param tokens |
| 89 | + */ |
| 90 | + // FIXME: What do division and tokens do? |
| 91 | + // TODO: Document the scan() and mark() APIs somewhere |
| 92 | + 'mark': function( context, division, tokens ) { |
| 93 | + // Reset markers |
| 94 | + var markers = []; |
| 95 | + |
| 96 | + // Recycle markers that will be skipped in this run |
| 97 | + if ( context.modules.highlight.markers && division != '' ) { |
| 98 | + for ( var i = 0; i < context.modules.highlight.markers.length; i++ ) { |
| 99 | + if ( context.modules.highlight.markers[i].skipDivision == division ) { |
| 100 | + markers.push( context.modules.highlight.markers[i] ); |
| 101 | + } |
| 102 | + } |
| 103 | + } |
| 104 | + context.modules.highlight.markers = markers; |
| 105 | + |
| 106 | + // Get all markers |
| 107 | + context.fn.trigger( 'mark' ); |
| 108 | + markers.sort( function( a, b ) { return a.start - b.start || a.end - b.end; } ); |
| 109 | + |
| 110 | + // Serialize the markers array to a string and compare it with the one stored in the previous run - if they're |
| 111 | + // equal, there's no markers to change |
| 112 | + var markersStr = ''; |
| 113 | + for ( var i = 0; i < markers.length; i++ ) { |
| 114 | + markersStr += markers[i].start + ',' + markers[i].end + ',' + markers[i].type + ','; |
| 115 | + } |
| 116 | + if ( context.modules.highlight.markersStr == markersStr ) { |
| 117 | + // No change, bail out |
| 118 | + return; |
| 119 | + } |
| 120 | + context.modules.highlight.markersStr = markersStr; |
| 121 | + |
| 122 | + // Traverse the iframe DOM, inserting markers where they're needed - store visited markers here so we know which |
| 123 | + // markers should be removed |
| 124 | + var visited = [], v = 0; |
| 125 | + for ( var i = 0; i < markers.length; i++ ) { |
| 126 | + if ( typeof markers[i].skipDivision !== 'undefined' && ( division == markers[i].skipDivision ) ) { |
| 127 | + continue; |
| 128 | + } |
| 129 | + |
| 130 | + // We want to isolate each marker, so we may need to split textNodes if a marker starts or ends halfway one. |
| 131 | + var start = markers[i].start; |
| 132 | + var s = context.fn.getOffset( start ); |
| 133 | + if ( !s ) { |
| 134 | + // This shouldn't happen |
| 135 | + continue; |
| 136 | + } |
| 137 | + var startNode = s.node; |
| 138 | + |
| 139 | + // Don't wrap leading BRs, produces undesirable results |
| 140 | + // FIXME: It's also possible that the offset is a bit high because getOffset() has incremented .length to |
| 141 | + // fake the newline caused by startNode being in a P. In this case, prevent the textnode splitting below |
| 142 | + // from making startNode an empty textnode, IE barfs on that |
| 143 | + while ( startNode.nodeName == 'BR' || s.offset == startNode.nodeValue.length ) { |
| 144 | + start++; |
| 145 | + s = context.fn.getOffset( start ); |
| 146 | + startNode = s.node; |
| 147 | + } |
| 148 | + |
| 149 | + // The next marker starts somewhere in this textNode or at this BR |
| 150 | + if ( s.offset > 0 && s.node.nodeName == '#text' ) { |
| 151 | + // Split off the prefix - this leaves the prefix in the current node and puts the rest in a new node |
| 152 | + // which is our start node |
| 153 | + var newStartNode = startNode.splitText( s.offset < s.node.nodeValue.length ? |
| 154 | + s.offset : s.node.nodeValue.length - 1 |
| 155 | + ); |
| 156 | + var oldStartNode = startNode; |
| 157 | + startNode = newStartNode; |
| 158 | + // Update offset objects. We don't need purgeOffsets(), simply manipulating the existing offset objects |
| 159 | + // will suffice |
| 160 | + // FIXME: This manipulates context.offsets directly, which is ugly, but the performance improvement vs. |
| 161 | + // purgeOffsets() is worth it - this code doesn't set lastTextNode to newStartNode for offset objects |
| 162 | + // with lastTextNode == oldStartNode, but that doesn't really matter |
| 163 | + var subtracted = s.offset; |
| 164 | + var oldLength = s.length; |
| 165 | + |
| 166 | + var j, o; |
| 167 | + // Update offset objects referring to oldStartNode |
| 168 | + for ( j = start - subtracted; j < start; j++ ) { |
| 169 | + if ( j in context.offsets ) { |
| 170 | + o = context.offsets[j]; |
| 171 | + o.node = oldStartNode; |
| 172 | + o.length = subtracted; |
| 173 | + } |
| 174 | + } |
| 175 | + // Update offset objects referring to newStartNode |
| 176 | + for ( j = start; j < start - subtracted + oldLength; j++ ) { |
| 177 | + if ( j in context.offsets ) { |
| 178 | + o = context.offsets[j]; |
| 179 | + o.node = newStartNode; |
| 180 | + o.offset -= subtracted; |
| 181 | + o.length -= subtracted; |
| 182 | + o.lastTextNode = oldStartNode; |
| 183 | + } |
| 184 | + } |
| 185 | + } |
| 186 | + var end = markers[i].end; |
| 187 | + // To avoid ending up at the first char of the next node, we grab the offset for end - 1 and add one to the |
| 188 | + // offset |
| 189 | + var e = context.fn.getOffset( end - 1 ); |
| 190 | + if ( !e ) { |
| 191 | + // This shouldn't happen |
| 192 | + continue; |
| 193 | + } |
| 194 | + var endNode = e.node; |
| 195 | + if ( e.offset + 1 < e.length - 1 && endNode.nodeName == '#text' ) { |
| 196 | + // Split off the suffix. This puts the suffix in a new node and leaves the rest in endNode |
| 197 | + var oldEndNode = endNode; |
| 198 | + var newEndNode = endNode.splitText( e.offset + 1 ); |
| 199 | + // Update offset objects |
| 200 | + var subtracted = e.offset + 1; |
| 201 | + var oldLength = e.length; |
| 202 | + var j, o; |
| 203 | + // Update offset objects referring to oldEndNode |
| 204 | + for ( j = end - subtracted; j < end; j++ ) { |
| 205 | + if ( j in context.offsets ) { |
| 206 | + o = context.offsets[j]; |
| 207 | + o.node = oldEndNode; |
| 208 | + o.length = subtracted; |
| 209 | + } |
| 210 | + } |
| 211 | + // We have to insert this one, as it might not exist: we didn't call getOffset( end ) |
| 212 | + context.offsets[end] = { |
| 213 | + 'node': newEndNode, |
| 214 | + 'offset': 0, |
| 215 | + 'length': oldLength - subtracted, |
| 216 | + 'lastTextNode': oldEndNode |
| 217 | + }; |
| 218 | + // Update offset objects referring to newEndNode |
| 219 | + for ( j = end + 1; j < end - subtracted + oldLength; j++ ) { |
| 220 | + if ( j in context.offsets ) { |
| 221 | + o = context.offsets[j]; |
| 222 | + o.node = newEndNode; |
| 223 | + o.offset -= subtracted; |
| 224 | + o.length -= subtracted; |
| 225 | + o.lastTextNode = oldEndNode; |
| 226 | + } |
| 227 | + } |
| 228 | + } |
| 229 | + // Don't wrap trailing BRs, doing that causes weird issues |
| 230 | + if ( endNode.nodeName == 'BR' ) { |
| 231 | + endNode = e.lastTextNode; |
| 232 | + } |
| 233 | + // If startNode and endNode have different parents, we need to pull endNode and all textnodes in between |
| 234 | + // into startNode's parent and replace </p><p> with <br> |
| 235 | + if ( startNode.parentNode != endNode.parentNode ) { |
| 236 | + var startP = $( startNode ).closest( 'p' ).get( 0 ); |
| 237 | + var t = new context.fn.rawTraverser( startNode, startP, context.$content.get( 0 ), false ); |
| 238 | + var afterStart = startNode.nextSibling; |
| 239 | + var lastP = startP; |
| 240 | + var nextT = t.next(); |
| 241 | + while ( nextT && t.node != endNode ) { |
| 242 | + t = nextT; |
| 243 | + nextT = t.next(); |
| 244 | + // If t.node has a different parent, merge t.node.parentNode with startNode.parentNode |
| 245 | + if ( t.node.parentNode != startNode.parentNode ) { |
| 246 | + var oldParent = t.node.parentNode; |
| 247 | + if ( afterStart ) { |
| 248 | + if ( lastP != t.inP ) { |
| 249 | + // We're entering a new <p>, insert a <br> |
| 250 | + startNode.parentNode.insertBefore( |
| 251 | + startNode.ownerDocument.createElement( 'br' ), |
| 252 | + afterStart |
| 253 | + ); |
| 254 | + } |
| 255 | + // A <p> with just a <br> in it is an empty line, so let's not bother with unwrapping it |
| 256 | + if ( !( oldParent.childNodes.length == 1 && oldParent.firstChild.nodeName == 'BR' ) ) { |
| 257 | + // Move all children of oldParent into startNode's parent |
| 258 | + while ( oldParent.firstChild ) { |
| 259 | + startNode.parentNode.insertBefore( oldParent.firstChild, afterStart ); |
| 260 | + } |
| 261 | + } |
| 262 | + } else { |
| 263 | + if ( lastP != t.inP ) { |
| 264 | + // We're entering a new <p>, insert a <br> |
| 265 | + startNode.parentNode.appendChild( |
| 266 | + startNode.ownerDocument.createElement( 'br' ) |
| 267 | + ); |
| 268 | + } |
| 269 | + // A <p> with just a <br> in it is an empty line, so let's not bother with unwrapping it |
| 270 | + if ( !( oldParent.childNodes.length == 1 && oldParent.firstChild.nodeName == 'BR' ) ) { |
| 271 | + // Move all children of oldParent into startNode's parent |
| 272 | + while ( oldParent.firstChild ) { |
| 273 | + startNode.parentNode.appendChild( oldParent.firstChild ); |
| 274 | + } |
| 275 | + } |
| 276 | + } |
| 277 | + // Remove oldParent, which is now empty |
| 278 | + oldParent.parentNode.removeChild( oldParent ); |
| 279 | + } |
| 280 | + lastP = t.inP; |
| 281 | + } |
| 282 | + // Moving nodes around like this invalidates offset objects |
| 283 | + // TODO: Update offset objects ourselves for performance. Requires rewriting this code block to be |
| 284 | + // offset-based rather than traverser-based |
| 285 | + } |
| 286 | + // Now wrap everything between startNode and endNode (may be equal). |
| 287 | + var ca1 = startNode, ca2 = endNode; |
| 288 | + if ( ca1 && ca2 && ca1.parentNode ) { |
| 289 | + var anchor = markers[i].getAnchor( ca1, ca2 ); |
| 290 | + if ( !anchor ) { |
| 291 | + var commonAncestor = ca1.parentNode; |
| 292 | + if ( markers[i].anchor == 'wrap') { |
| 293 | + // We have to store things like .parentNode and .nextSibling because appendChild() changes these |
| 294 | + var newNode = ca1.ownerDocument.createElement( 'span' ); |
| 295 | + var nextNode = ca2.nextSibling; |
| 296 | + // Append all nodes between ca1 and ca2 (inclusive) to newNode |
| 297 | + var n = ca1; |
| 298 | + while ( n != nextNode ) { |
| 299 | + var ns = n.nextSibling; |
| 300 | + newNode.appendChild( n ); |
| 301 | + n = ns; |
| 302 | + } |
| 303 | + // Insert newNode in the right place |
| 304 | + if ( nextNode ) { |
| 305 | + commonAncestor.insertBefore( newNode, nextNode ); |
| 306 | + } else { |
| 307 | + commonAncestor.appendChild( newNode ); |
| 308 | + } |
| 309 | + anchor = newNode; |
| 310 | + } else if ( markers[i].anchor == 'tag' ) { |
| 311 | + anchor = commonAncestor; |
| 312 | + } |
| 313 | + $( anchor ).data( 'marker', markers[i] ).addClass( 'wikiEditor-highlight' ); |
| 314 | + // Allow the module adding this marker to manipulate it |
| 315 | + markers[i].afterWrap( anchor, markers[i] ); |
| 316 | + |
| 317 | + } else { |
| 318 | + // Update the marker object |
| 319 | + $( anchor ).data( 'marker', markers[i] ); |
| 320 | + if ( typeof markers[i].onSkip == 'function' ) { |
| 321 | + markers[i].onSkip( anchor ); |
| 322 | + } |
| 323 | + } |
| 324 | + visited[v++] = anchor; |
| 325 | + } |
| 326 | + } |
| 327 | + // Remove markers that were previously inserted but weren't passed to this function - visited[] contains the |
| 328 | + // visited elements in order and find() and each() preserve order |
| 329 | + var j = 0; |
| 330 | + context.$content.find( '.wikiEditor-highlight' ).each( function() { |
| 331 | + if ( visited[j] == this ) { |
| 332 | + // This marker is legit, leave it in |
| 333 | + j++; |
| 334 | + return true; |
| 335 | + } |
| 336 | + // Remove this marker |
| 337 | + var marker = $(this).data( 'marker' ); |
| 338 | + if ( marker && typeof marker.skipDivision != 'undefined' && ( division == marker.skipDivision ) ) { |
| 339 | + // Don't remove these either |
| 340 | + return true; |
| 341 | + } |
| 342 | + if ( marker && typeof marker.beforeUnwrap == 'function' ) |
| 343 | + marker.beforeUnwrap( this ); |
| 344 | + if ( ( marker && marker.anchor == 'tag' ) || $(this).is( 'p' ) ) { |
| 345 | + // Remove all classes |
| 346 | + $(this).removeAttr( 'class' ); |
| 347 | + } else { |
| 348 | + // Assume anchor == 'wrap' |
| 349 | + $(this).replaceWith( this.childNodes ); |
| 350 | + } |
| 351 | + context.fn.purgeOffsets(); |
| 352 | + }); |
| 353 | + |
| 354 | + } |
| 355 | +} |
| 356 | + |
| 357 | +}; })( jQuery ); |
| 358 | + |
Property changes on: trunk/extensions/WikiEditor/modules/jquery.wikiEditor.highlight.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 359 | + native |
Index: trunk/extensions/WikiEditor/modules/Templates.js |
— | — | @@ -0,0 +1,16 @@ |
| 2 | +/* JavaScript for WikiEditor Templates module */ |
| 3 | + |
| 4 | +$j(document).ready( function() { |
| 5 | + // Check preferences for templates |
| 6 | + if ( !wgWikiEditorEnabledModules.templates ) { |
| 7 | + return true; |
| 8 | + } |
| 9 | + // Disable for template namespace |
| 10 | + if ( wgNamespaceNumber == 10 ) { |
| 11 | + return true; |
| 12 | + } |
| 13 | + // Add the templates module |
| 14 | + if ( $j.fn.wikiEditor ) { |
| 15 | + $j( 'textarea#wpTextbox1' ).wikiEditor( 'addModule', 'templates' ); |
| 16 | + } |
| 17 | +}); |
Property changes on: trunk/extensions/WikiEditor/modules/Templates.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 18 | + native |
Index: trunk/extensions/WikiEditor/modules/PreviewDialog.js |
— | — | @@ -0,0 +1,12 @@ |
| 2 | +/* JavaScript for WikiEditor PreviewDialog module */ |
| 3 | + |
| 4 | +$j(document).ready( function() { |
| 5 | + // Check preferences for preview |
| 6 | + if ( !wgWikiEditorEnabledModules.previewDialog ) { |
| 7 | + return true; |
| 8 | + } |
| 9 | + // Add the preview module |
| 10 | + if ( $j.fn.wikiEditor ) { |
| 11 | + $j( 'textarea#wpTextbox1' ).wikiEditor( 'addModule', 'previewDialog' ); |
| 12 | + } |
| 13 | +}); |
Property changes on: trunk/extensions/WikiEditor/modules/PreviewDialog.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 14 | + native |
Index: trunk/extensions/WikiEditor/modules/Toolbar.js |
— | — | @@ -0,0 +1,2124 @@ |
| 2 | +/* JavaScript for WikiEditor Toolbar module */ |
| 3 | + |
| 4 | +$j(document).ready( function() { |
| 5 | + // Check preferences for toolbar |
| 6 | + if ( !wgWikiEditorEnabledModules.toolbar ) { |
| 7 | + return true; |
| 8 | + } |
| 9 | + // Only show content generation dialogs if enabled |
| 10 | + if ( wgWikiEditorPreferences.toolbar.dialogs && $j.wikiEditor.isSupported( $j.wikiEditor.modules.dialogs ) ) { |
| 11 | + $j( '#wpTextbox1' ).addClass( 'toolbar-dialogs' ); |
| 12 | + } |
| 13 | + if ( $j.fn.wikiEditor && $j.wikiEditor.isSupported( $j.wikiEditor.modules.toolbar ) ) { |
| 14 | + // Remove the old toolbar |
| 15 | + $j( '#toolbar' ).remove(); |
| 16 | + // Add toolbar module |
| 17 | + $j( '#wpTextbox1' ).wikiEditor( 'addModule', { |
| 18 | +'toolbar': { |
| 19 | + // Main section |
| 20 | + 'main': { |
| 21 | + type: 'toolbar', |
| 22 | + groups: { |
| 23 | + 'format': { |
| 24 | + tools: { |
| 25 | + 'bold': { |
| 26 | + labelMsg: 'wikieditor-toolbar-tool-bold', |
| 27 | + type: 'button', |
| 28 | + offset: { |
| 29 | + 'default': [2, -574], |
| 30 | + 'en': [2, -142], |
| 31 | + 'cs': [2, -142], |
| 32 | + 'de': [2, -214], |
| 33 | + 'fr': [2, -286], |
| 34 | + 'es': [2, -358], |
| 35 | + 'he': [2, -142], |
| 36 | + 'hu': [2, -214], |
| 37 | + 'it': [2, -286], |
| 38 | + 'nl': [2, -502], |
| 39 | + 'pt': [2, -358], |
| 40 | + 'pt-br': [2, -358], |
| 41 | + 'pl': [2, -142], |
| 42 | + 'ml': [2, -142] |
| 43 | + }, |
| 44 | + icon: { |
| 45 | + 'default': 'format-bold.png', |
| 46 | + 'en': 'format-bold-B.png', |
| 47 | + 'cs': 'format-bold-B.png', |
| 48 | + 'de': 'format-bold-F.png', |
| 49 | + 'fr': 'format-bold-G.png', |
| 50 | + 'es': 'format-bold-N.png', |
| 51 | + 'he': 'format-bold-B.png', |
| 52 | + 'hu': 'format-bold-F.png', |
| 53 | + 'it': 'format-bold-G.png', |
| 54 | + 'ka': 'format-bold-ka.png', |
| 55 | + 'nl': 'format-bold-V.png', |
| 56 | + 'pt': 'format-bold-N.png', |
| 57 | + 'pt-br': 'format-bold-N.png', |
| 58 | + 'pl': 'format-bold-B.png', |
| 59 | + 'ru': 'format-bold-ru.png', |
| 60 | + 'ml': 'format-bold-B.png' |
| 61 | + }, |
| 62 | + action: { |
| 63 | + type: 'encapsulate', |
| 64 | + options: { |
| 65 | + pre: "'''", |
| 66 | + periMsg: 'wikieditor-toolbar-tool-bold-example', |
| 67 | + post: "'''" |
| 68 | + } |
| 69 | + } |
| 70 | + }, |
| 71 | + 'italic': { |
| 72 | + section: 'main', |
| 73 | + group: 'format', |
| 74 | + id: 'italic', |
| 75 | + labelMsg: 'wikieditor-toolbar-tool-italic', |
| 76 | + type: 'button', |
| 77 | + offset: { |
| 78 | + 'default': [2, -718], |
| 79 | + 'en': [2, -862], |
| 80 | + 'cs': [2, -862], |
| 81 | + 'de': [2, -934], |
| 82 | + 'fr': [2, -862], |
| 83 | + 'es': [2, -790], |
| 84 | + 'he': [2, -862], |
| 85 | + 'it': [2, -790], |
| 86 | + 'nl': [2, -790], |
| 87 | + 'pt': [2, -862], |
| 88 | + 'pt-br': [2, -862], |
| 89 | + 'pl': [2, -862], |
| 90 | + 'ru': [2, -934], |
| 91 | + 'ml': [2, -862] |
| 92 | + }, |
| 93 | + icon: { |
| 94 | + 'default': 'format-italic.png', |
| 95 | + 'en': 'format-italic-I.png', |
| 96 | + 'cs': 'format-italic-I.png', |
| 97 | + 'de': 'format-italic-K.png', |
| 98 | + 'fr': 'format-italic-I.png', |
| 99 | + 'es': 'format-italic-C.png', |
| 100 | + 'he': 'format-italic-I.png', |
| 101 | + 'hu': 'format-italic-D.png', |
| 102 | + 'it': 'format-italic-C.png', |
| 103 | + 'ka': 'format-italic-ka.png', |
| 104 | + 'nl': 'format-italic-C.png', |
| 105 | + 'pt': 'format-italic-I.png', |
| 106 | + 'pt-br': 'format-italic-I.png', |
| 107 | + 'pl': 'format-italic-I.png', |
| 108 | + 'ru': 'format-italic-K.png', |
| 109 | + 'ml': 'format-italic-I.png' |
| 110 | + }, |
| 111 | + action: { |
| 112 | + type: 'encapsulate', |
| 113 | + options: { |
| 114 | + pre: "''", |
| 115 | + periMsg: 'wikieditor-toolbar-tool-italic-example', |
| 116 | + post: "''" |
| 117 | + } |
| 118 | + } |
| 119 | + } |
| 120 | + } |
| 121 | + }, |
| 122 | + 'insert': { |
| 123 | + tools: { |
| 124 | + 'xlink': { |
| 125 | + labelMsg: 'wikieditor-toolbar-tool-xlink', |
| 126 | + type: 'button', |
| 127 | + icon: 'insert-xlink.png', |
| 128 | + offset: [-70, 2], |
| 129 | + filters: [ '#wpTextbox1:not(.toolbar-dialogs)' ], |
| 130 | + action: { |
| 131 | + type: 'encapsulate', |
| 132 | + options: { |
| 133 | + pre: "[", |
| 134 | + periMsg: 'wikieditor-toolbar-tool-xlink-example', |
| 135 | + post: "]" |
| 136 | + } |
| 137 | + } |
| 138 | + }, |
| 139 | + 'ilink': { |
| 140 | + labelMsg: 'wikieditor-toolbar-tool-ilink', |
| 141 | + type: 'button', |
| 142 | + icon: 'insert-ilink.png', |
| 143 | + offset: [2, -1582], |
| 144 | + filters: [ '#wpTextbox1:not(.toolbar-dialogs)' ], |
| 145 | + action: { |
| 146 | + type: 'encapsulate', |
| 147 | + options: { |
| 148 | + pre: "[[", |
| 149 | + periMsg: 'wikieditor-toolbar-tool-ilink-example', |
| 150 | + post: "]]" |
| 151 | + } |
| 152 | + } |
| 153 | + }, |
| 154 | + 'linkCGD': { |
| 155 | + labelMsg: 'wikieditor-toolbar-tool-link', |
| 156 | + type: 'button', |
| 157 | + icon: 'insert-link.png', |
| 158 | + offset: [2, -1654], |
| 159 | + filters: [ '#wpTextbox1.toolbar-dialogs' ], |
| 160 | + action: { |
| 161 | + type: 'dialog', |
| 162 | + module: 'insert-link' |
| 163 | + } |
| 164 | + }, |
| 165 | + 'file': { |
| 166 | + labelMsg: 'wikieditor-toolbar-tool-file', |
| 167 | + type: 'button', |
| 168 | + icon: 'insert-file.png', |
| 169 | + offset: [2, -1438], |
| 170 | + action: { |
| 171 | + type: 'encapsulate', |
| 172 | + options: { |
| 173 | + // FIXME: Why the hell was this done this way? |
| 174 | + preMsg: [ 'wikieditor-toolbar-tool-file-pre', '[[' ], |
| 175 | + periMsg: 'wikieditor-toolbar-tool-file-example', |
| 176 | + post: "]]" |
| 177 | + } |
| 178 | + } |
| 179 | + }, |
| 180 | + 'referenceCGD': { |
| 181 | + labelMsg: 'wikieditor-toolbar-tool-reference', |
| 182 | + type: 'button', |
| 183 | + icon: 'insert-reference.png', |
| 184 | + offset: [2, -1798], |
| 185 | + filters: [ 'body.ns-subject', '#wpTextbox1.toolbar-dialogs' ], |
| 186 | + action: { |
| 187 | + type: 'dialog', |
| 188 | + module: 'insert-reference' |
| 189 | + } |
| 190 | + }, |
| 191 | + 'reference': { |
| 192 | + labelMsg: 'wikieditor-toolbar-tool-reference', |
| 193 | + filters: [ 'body.ns-subject', '#wpTextbox1:not(.toolbar-dialogs)' ], |
| 194 | + type: 'button', |
| 195 | + offset: [2, -1798], |
| 196 | + icon: 'insert-reference.png', |
| 197 | + action: { |
| 198 | + type: 'encapsulate', |
| 199 | + options: { |
| 200 | + pre: "<ref>", |
| 201 | + periMsg: 'wikieditor-toolbar-tool-reference-example', |
| 202 | + post: "</ref>" |
| 203 | + } |
| 204 | + } |
| 205 | + }, |
| 206 | + 'signature': { |
| 207 | + labelMsg: 'wikieditor-toolbar-tool-signature', |
| 208 | + filters: [ 'body:not(.ns-0)' ], |
| 209 | + type: 'button', |
| 210 | + offset: [2, -1872], |
| 211 | + icon: 'insert-signature.png', |
| 212 | + action: { |
| 213 | + type: 'encapsulate', |
| 214 | + options: { |
| 215 | + post: "--~~~~" |
| 216 | + } |
| 217 | + } |
| 218 | + } |
| 219 | + } |
| 220 | + } |
| 221 | + } |
| 222 | + }, |
| 223 | + // Format section |
| 224 | + 'advanced': { |
| 225 | + labelMsg: 'wikieditor-toolbar-section-advanced', |
| 226 | + type: 'toolbar', |
| 227 | + groups: { |
| 228 | + 'heading': { |
| 229 | + tools: { |
| 230 | + 'heading': { |
| 231 | + labelMsg: 'wikieditor-toolbar-tool-heading', |
| 232 | + type: 'select', |
| 233 | + list: { |
| 234 | + 'heading-2' : { |
| 235 | + labelMsg: 'wikieditor-toolbar-tool-heading-2', |
| 236 | + action: { |
| 237 | + type: 'encapsulate', |
| 238 | + options: { |
| 239 | + pre: '== ', |
| 240 | + periMsg: 'wikieditor-toolbar-tool-heading-example', |
| 241 | + post: ' ==', |
| 242 | + regex: /^(\s*)(={1,6})(.*?)\2(\s*)$/, |
| 243 | + regexReplace: "\$1==\$3==\$4", |
| 244 | + ownline: true |
| 245 | + } |
| 246 | + } |
| 247 | + }, |
| 248 | + 'heading-3' : { |
| 249 | + labelMsg: 'wikieditor-toolbar-tool-heading-3', |
| 250 | + action: { |
| 251 | + type: 'encapsulate', |
| 252 | + options: { |
| 253 | + pre: '=== ', |
| 254 | + periMsg: 'wikieditor-toolbar-tool-heading-example', |
| 255 | + post: ' ===', |
| 256 | + regex: /^(\s*)(={1,6})(.*?)\2(\s*)$/, |
| 257 | + regexReplace: "\$1===\$3===\$4", |
| 258 | + ownline: true |
| 259 | + } |
| 260 | + } |
| 261 | + }, |
| 262 | + 'heading-4' : { |
| 263 | + labelMsg: 'wikieditor-toolbar-tool-heading-4', |
| 264 | + action: { |
| 265 | + type: 'encapsulate', |
| 266 | + options: { |
| 267 | + pre: '==== ', |
| 268 | + periMsg: 'wikieditor-toolbar-tool-heading-example', |
| 269 | + post: ' ====', |
| 270 | + regex: /^(\s*)(={1,6})(.*?)\2(\s*)$/, |
| 271 | + regexReplace: "\$1====\$3====\$4", |
| 272 | + ownline: true |
| 273 | + } |
| 274 | + } |
| 275 | + }, |
| 276 | + 'heading-5' : { |
| 277 | + labelMsg: 'wikieditor-toolbar-tool-heading-5', |
| 278 | + action: { |
| 279 | + type: 'encapsulate', |
| 280 | + options: { |
| 281 | + pre: '===== ', |
| 282 | + periMsg: 'wikieditor-toolbar-tool-heading-example', |
| 283 | + post: ' =====', |
| 284 | + regex: /^(\s*)(={1,6})(.*?)\2(\s*)$/, |
| 285 | + regexReplace: "\$1=====\$3=====\$4", |
| 286 | + ownline: true |
| 287 | + } |
| 288 | + } |
| 289 | + } |
| 290 | + } |
| 291 | + } |
| 292 | + } |
| 293 | + }, |
| 294 | + 'format': { |
| 295 | + labelMsg: 'wikieditor-toolbar-group-format', |
| 296 | + tools: { |
| 297 | + 'ulist': { |
| 298 | + labelMsg: 'wikieditor-toolbar-tool-ulist', |
| 299 | + type: 'button', |
| 300 | + icon: 'format-ulist.png', |
| 301 | + offset: [2, -1366], |
| 302 | + action: { |
| 303 | + type: 'encapsulate', |
| 304 | + options: { |
| 305 | + pre: "* ", |
| 306 | + periMsg: 'wikieditor-toolbar-tool-ulist-example', |
| 307 | + post: "", |
| 308 | + ownline: true |
| 309 | + } |
| 310 | + } |
| 311 | + }, |
| 312 | + 'olist': { |
| 313 | + labelMsg: 'wikieditor-toolbar-tool-olist', |
| 314 | + type: 'button', |
| 315 | + icon: 'format-olist.png', |
| 316 | + offset: [2, -1078], |
| 317 | + action: { |
| 318 | + type: 'encapsulate', |
| 319 | + options: { |
| 320 | + pre: "# ", |
| 321 | + periMsg: 'wikieditor-toolbar-tool-olist-example', |
| 322 | + post: "", |
| 323 | + ownline: true |
| 324 | + } |
| 325 | + } |
| 326 | + }, |
| 327 | + 'indent': { |
| 328 | + labelMsg: 'wikieditor-toolbar-tool-indent', |
| 329 | + type: 'button', |
| 330 | + icon: 'format-indent.png', |
| 331 | + offset: [2, -646], |
| 332 | + action: { |
| 333 | + type: 'encapsulate', |
| 334 | + options: { |
| 335 | + pre: ":", |
| 336 | + periMsg: 'wikieditor-toolbar-tool-indent-example', |
| 337 | + post: "", |
| 338 | + ownline: true, |
| 339 | + splitlines: true |
| 340 | + } |
| 341 | + } |
| 342 | + }, |
| 343 | + 'nowiki': { |
| 344 | + labelMsg: 'wikieditor-toolbar-tool-nowiki', |
| 345 | + type: 'button', |
| 346 | + icon: 'insert-nowiki.png', |
| 347 | + offset: [-70, -70], |
| 348 | + action: { |
| 349 | + type: 'encapsulate', |
| 350 | + options: { |
| 351 | + pre: "<nowiki>", |
| 352 | + periMsg: 'wikieditor-toolbar-tool-nowiki-example', |
| 353 | + post: "</nowiki>" |
| 354 | + } |
| 355 | + } |
| 356 | + }, |
| 357 | + 'newline': { |
| 358 | + labelMsg: 'wikieditor-toolbar-tool-newline', |
| 359 | + type: 'button', |
| 360 | + icon: 'insert-newline.png', |
| 361 | + offset: [2, -1726], |
| 362 | + action: { |
| 363 | + type: 'encapsulate', |
| 364 | + options: { |
| 365 | + pre: "<br />\n" |
| 366 | + } |
| 367 | + } |
| 368 | + } |
| 369 | + } |
| 370 | + }, |
| 371 | + 'size': { |
| 372 | + tools: { |
| 373 | + 'big': { |
| 374 | + labelMsg: 'wikieditor-toolbar-tool-big', |
| 375 | + type: 'button', |
| 376 | + icon: 'format-big.png', |
| 377 | + offset: [2, 2], |
| 378 | + action: { |
| 379 | + type: 'encapsulate', |
| 380 | + options: { |
| 381 | + pre: "<big>", |
| 382 | + periMsg: 'wikieditor-toolbar-tool-big-example', |
| 383 | + post: "</big>" |
| 384 | + } |
| 385 | + } |
| 386 | + }, |
| 387 | + 'small': { |
| 388 | + labelMsg: 'wikieditor-toolbar-tool-small', |
| 389 | + type: 'button', |
| 390 | + icon: 'format-small.png', |
| 391 | + offset: [2, -1150], |
| 392 | + action: { |
| 393 | + type: 'encapsulate', |
| 394 | + options: { |
| 395 | + pre: "<small>", |
| 396 | + periMsg: 'wikieditor-toolbar-tool-small-example', |
| 397 | + post: "</small>" |
| 398 | + } |
| 399 | + } |
| 400 | + }, |
| 401 | + 'superscript': { |
| 402 | + labelMsg: 'wikieditor-toolbar-tool-superscript', |
| 403 | + type: 'button', |
| 404 | + icon: 'format-superscript.png', |
| 405 | + offset: [2, -1294], |
| 406 | + action: { |
| 407 | + type: 'encapsulate', |
| 408 | + options: { |
| 409 | + pre: "<sup>", |
| 410 | + periMsg: 'wikieditor-toolbar-tool-superscript-example', |
| 411 | + post: "</sup>" |
| 412 | + } |
| 413 | + } |
| 414 | + }, |
| 415 | + 'subscript': { |
| 416 | + labelMsg: 'wikieditor-toolbar-tool-subscript', |
| 417 | + type: 'button', |
| 418 | + icon: 'format-subscript.png', |
| 419 | + offset: [2, -1222], |
| 420 | + action: { |
| 421 | + type: 'encapsulate', |
| 422 | + options: { |
| 423 | + pre: "<sub>", |
| 424 | + periMsg: 'wikieditor-toolbar-tool-subscript-example', |
| 425 | + post: "</sub>" |
| 426 | + } |
| 427 | + } |
| 428 | + } |
| 429 | + } |
| 430 | + }, |
| 431 | + 'insert': { |
| 432 | + labelMsg: 'wikieditor-toolbar-group-insert', |
| 433 | + tools: { |
| 434 | + 'gallery': { |
| 435 | + labelMsg: 'wikieditor-toolbar-tool-gallery', |
| 436 | + type: 'button', |
| 437 | + icon: 'insert-gallery.png', |
| 438 | + offset: [2, -1510], |
| 439 | + action: { |
| 440 | + type: 'encapsulate', |
| 441 | + options: { |
| 442 | + pre: "<gallery>\n", |
| 443 | + periMsg: 'wikieditor-toolbar-tool-gallery-example', |
| 444 | + post: "\n</gallery>", |
| 445 | + ownline: true |
| 446 | + } |
| 447 | + } |
| 448 | + }, |
| 449 | + 'tableCGD': { |
| 450 | + labelMsg: 'wikieditor-toolbar-tool-table', |
| 451 | + type: 'button', |
| 452 | + icon: 'insert-table.png', |
| 453 | + offset: [2, -1942], |
| 454 | + filters: [ '#wpTextbox1.toolbar-dialogs' ], |
| 455 | + action: { |
| 456 | + type: 'dialog', |
| 457 | + module: 'insert-table' |
| 458 | + } |
| 459 | + }, |
| 460 | + 'table': { |
| 461 | + labelMsg: 'wikieditor-toolbar-tool-table', |
| 462 | + type: 'button', |
| 463 | + icon: 'insert-table.png', |
| 464 | + offset: [2, -1942], |
| 465 | + filters: [ '#wpTextbox1:not(.toolbar-dialogs)' ], |
| 466 | + action: { |
| 467 | + type: 'encapsulate', |
| 468 | + options: { |
| 469 | + pre: "{| class=\"wikitable\" border=\"1\"\n|", |
| 470 | + periMsg: 'wikieditor-toolbar-tool-table-example-old', |
| 471 | + post: "\n|}", |
| 472 | + ownline: true |
| 473 | + } |
| 474 | + } |
| 475 | + }, |
| 476 | + 'redirect': { |
| 477 | + labelMsg: 'wikieditor-toolbar-tool-redirect', |
| 478 | + type: 'button', |
| 479 | + icon: 'insert-redirect.png', |
| 480 | + offset: [-70, -142], |
| 481 | + action: { |
| 482 | + type: 'encapsulate', |
| 483 | + options: { |
| 484 | + pre: "#REDIRECT [[", |
| 485 | + periMsg: 'wikieditor-toolbar-tool-redirect-example', |
| 486 | + post: "]]", |
| 487 | + ownline: true |
| 488 | + } |
| 489 | + } |
| 490 | + } |
| 491 | + } |
| 492 | + }, |
| 493 | + 'search': { |
| 494 | + tools: { |
| 495 | + 'replace': { |
| 496 | + labelMsg: 'wikieditor-toolbar-tool-replace', |
| 497 | + type: 'button', |
| 498 | + icon: 'search-replace.png', |
| 499 | + offset: [-70, -214], |
| 500 | + filters: [ '#wpTextbox1.toolbar-dialogs' ], |
| 501 | + action: { |
| 502 | + type: 'dialog', |
| 503 | + module: 'search-and-replace' |
| 504 | + } |
| 505 | + } |
| 506 | + } |
| 507 | + } |
| 508 | + } |
| 509 | + }, |
| 510 | + 'characters': { |
| 511 | + labelMsg: 'wikieditor-toolbar-section-characters', |
| 512 | + type: 'booklet', |
| 513 | + deferLoad: true, |
| 514 | + pages: { |
| 515 | + 'latin': { |
| 516 | + 'labelMsg': 'wikieditor-toolbar-characters-page-latin', |
| 517 | + 'layout': 'characters', |
| 518 | + 'characters': [ |
| 519 | + "\u00c1", "\u00e1", "\u00c0", "\u00e0", "\u00c2", "\u00e2", "\u00c4", "\u00e4", "\u00c3", "\u00e3", |
| 520 | + "\u01cd", "\u01ce", "\u0100", "\u0101", "\u0102", "\u0103", "\u0104", "\u0105", "\u00c5", "\u00e5", |
| 521 | + "\u0106", "\u0107", "\u0108", "\u0109", "\u00c7", "\u00e7", "\u010c", "\u010d", "\u010a", "\u010b", |
| 522 | + "\u0110", "\u0111", "\u010e", "\u010f", "\u00c9", "\u00e9", "\u00c8", "\u00e8", "\u00ca", "\u00ea", |
| 523 | + "\u00cb", "\u00eb", "\u011a", "\u011b", "\u0112", "\u0113", "\u0114", "\u0115", "\u0116", "\u0117", |
| 524 | + "\u0118", "\u0119", "\u011c", "\u011d", "\u0122", "\u0123", "\u011e", "\u011f", "\u0120", "\u0121", |
| 525 | + "\u0124", "\u0125", "\u0126", "\u0127", "\u00cd", "\u00ed", "\u00cc", "\u00ec", "\u00ce", "\u00ee", |
| 526 | + "\u00cf", "\u00ef", "\u0128", "\u0129", "\u01cf", "\u01d0", "\u012a", "\u012b", "\u012c", "\u012d", |
| 527 | + "\u0130", "\u0131", "\u012e", "\u012f", "\u0134", "\u0135", "\u0136", "\u0137", "\u0139", "\u013a", |
| 528 | + "\u013b", "\u013c", "\u013d", "\u013e", "\u0141", "\u0142", "\u013f", "\u0140", "\u0143", "\u0144", |
| 529 | + "\u00d1", "\u00f1", "\u0145", "\u0146", "\u0147", "\u0148", "\u00d3", "\u00f3", "\u00d2", "\u00f2", |
| 530 | + "\u00d4", "\u00f4", "\u00d6", "\u00f6", "\u00d5", "\u00f5", "\u01d1", "\u01d2", "\u014c", "\u014d", |
| 531 | + "\u014e", "\u014f", "\u01ea", "\u01eb", "\u0150", "\u0151", "\u0154", "\u0155", "\u0156", "\u0157", |
| 532 | + "\u0158", "\u0159", "\u015a", "\u015b", "\u015c", "\u015d", "\u015e", "\u015f", "\u0160", "\u0161", |
| 533 | + "\u0162", "\u0163", "\u0164", "\u0165", "\u00da", "\u00fa", "\u00d9", "\u00f9", "\u00db", "\u00fb", |
| 534 | + "\u00dc", "\u00fc", "\u0168", "\u0169", "\u016e", "\u016f", "\u01d3", "\u01d4", "\u016a", "\u016b", |
| 535 | + "\u01d6", "\u01d8", "\u01da", "\u01dc", "\u016c", "\u016d", "\u0172", "\u0173", "\u0170", "\u0171", |
| 536 | + "\u0174", "\u0175", "\u00dd", "\u00fd", "\u0176", "\u0177", "\u0178", "\u00ff", "\u0232", "\u0233", |
| 537 | + "\u0179", "\u017a", "\u017d", "\u017e", "\u017b", "\u017c", "\u00c6", "\u00e6", "\u01e2", "\u01e3", |
| 538 | + "\u00d8", "\u00f8", "\u0152", "\u0153", "\u00df", "\u00f0", "\u00de", "\u00fe", "\u018f", "\u0259" |
| 539 | + ] |
| 540 | + }, |
| 541 | + 'latinextended': { |
| 542 | + 'labelMsg': 'wikieditor-toolbar-characters-page-latinextended', |
| 543 | + 'layout': 'characters', |
| 544 | + 'characters': [ |
| 545 | + "\u1e00", "\u1e01", "\u1e9a", "\u1ea0", "\u1ea1", "\u1ea2", "\u1ea3", "\u1ea4", "\u1ea5", "\u1ea6", |
| 546 | + "\u1ea7", "\u1ea8", "\u1ea9", "\u1eaa", "\u1eab", "\u1eac", "\u1ead", "\u1eae", "\u1eaf", "\u1eb0", |
| 547 | + "\u1eb1", "\u1eb2", "\u1eb3", "\u1eb4", "\u1eb5", "\u1eb6", "\u1eb7", "\u1e02", "\u1e03", "\u1e04", |
| 548 | + "\u1e05", "\u1e06", "\u1e07", "\u1e08", "\u1e09", "\u1e0a", "\u1e0b", "\u1e0c", "\u1e0d", "\u1e0e", |
| 549 | + "\u1e0f", "\u1e10", "\u1e11", "\u1e12", "\u1e13", "\u1e14", "\u1e15", "\u1e16", "\u1e17", "\u1e18", |
| 550 | + "\u1e19", "\u1e1a", "\u1e1b", "\u1e1c", "\u1e1d", "\u1eb8", "\u1eb9", "\u1eba", "\u1ebb", "\u1ebc", |
| 551 | + "\u1ebd", "\u1ebe", "\u1ebf", "\u1ec0", "\u1ec1", "\u1ec2", "\u1ec3", "\u1ec4", "\u1ec5", "\u1ec6", |
| 552 | + "\u1ec7", "\u1e1e", "\u1e1f", "\u1e20", "\u1e21", "\u1e22", "\u1e23", "\u1e24", "\u1e25", "\u1e26", |
| 553 | + "\u1e27", "\u1e28", "\u1e29", "\u1e2a", "\u1e2b", "\u1e96", "\u1e2c", "\u1e2d", "\u1e2e", "\u1e2f", |
| 554 | + "\u1ec8", "\u1ec9", "\u1eca", "\u1ecb", "\u1e30", "\u1e31", "\u1e32", "\u1e33", "\u1e34", "\u1e35", |
| 555 | + "\u1e36", "\u1e37", "\u1e38", "\u1e39", "\u1e3a", "\u1e3b", "\u1e3c", "\u1e3d", "\u1efa", "\u1efb", |
| 556 | + "\u1e3e", "\u1e3f", "\u1e40", "\u1e41", "\u1e42", "\u1e43", "\u1e44", "\u1e45", "\u1e46", "\u1e47", |
| 557 | + "\u1e48", "\u1e49", "\u1e4a", "\u1e4b", "\u1e4c", "\u1e4d", "\u1e4e", "\u1e4f", "\u1e50", "\u1e51", |
| 558 | + "\u1e52", "\u1e53", "\u1ecc", "\u1ecd", "\u1ece", "\u1ecf", "\u1ed0", "\u1ed1", "\u1ed2", "\u1ed3", |
| 559 | + "\u1ed4", "\u1ed5", "\u1ed6", "\u1ed7", "\u1ed8", "\u1ed9", "\u1eda", "\u1edb", "\u1edc", "\u1edd", |
| 560 | + "\u1ede", "\u1edf", "\u1ee0", "\u1ee1", "\u1ee2", "\u1ee3", "\u1e54", "\u1e55", "\u1e56", "\u1e57", |
| 561 | + "\u1e58", "\u1e59", "\u1e5a", "\u1e5b", "\u1e5c", "\u1e5d", "\u1e5e", "\u1e5f", "\u1e60", "\u1e61", |
| 562 | + "\u1e9b", "\u1e62", "\u1e63", "\u1e64", "\u1e65", "\u1e66", "\u1e67", "\u1e68", "\u1e69", "\u1e9c", |
| 563 | + "\u1e9d", "\u1e6a", "\u1e6b", "\u1e6c", "\u1e6d", "\u1e6e", "\u1e6f", "\u1e70", "\u1e71", "\u1e97", |
| 564 | + "\u1e72", "\u1e73", "\u1e74", "\u1e75", "\u1e76", "\u1e77", "\u1e78", "\u1e79", "\u1e7a", "\u1e7b", |
| 565 | + "\u1ee4", "\u1ee5", "\u1ee6", "\u1ee7", "\u1ee8", "\u1ee9", "\u1eea", "\u1eeb", "\u1eec", "\u1eed", |
| 566 | + "\u1eee", "\u1eef", "\u1ef0", "\u1ef1", "\u1e7c", "\u1e7d", "\u1e7e", "\u1e7f", "\u1efc", "\u1efd", |
| 567 | + "\u1e80", "\u1e81", "\u1e82", "\u1e83", "\u1e84", "\u1e85", "\u1e86", "\u1e87", "\u1e88", "\u1e89", |
| 568 | + "\u1e98", "\u1e8a", "\u1e8b", "\u1e8c", "\u1e8d", "\u1e8e", "\u1e8f", "\u1e99", "\u1ef2", "\u1ef3", |
| 569 | + "\u1ef4", "\u1ef5", "\u1ef6", "\u1ef7", "\u1ef8", "\u1ef9", "\u1efe", "\u1eff", "\u1e90", "\u1e91", |
| 570 | + "\u1e92", "\u1e93", "\u1e94", "\u1e95", "\u1e9e", "\u1e9f" |
| 571 | + ] |
| 572 | + }, |
| 573 | + 'ipa': { |
| 574 | + labelMsg: 'wikieditor-toolbar-characters-page-ipa', |
| 575 | + layout: 'characters', |
| 576 | + characters: [ |
| 577 | + "p", "t\u032a", "t", "\u0288", "c", "k", "q", "\u02a1", "\u0294", "b","d\u032a", "d", "\u0256", |
| 578 | + "\u025f", "\u0261", "\u0262", "\u0253", "\u0257", "\u0284", "\u0260", "\u029b", "t\u0361s", |
| 579 | + "t\u0361\u0283", "t\u0361\u0255", "d\u0361z", "d\u0361\u0292", "d\u0361\u0291", "\u0278", "f", |
| 580 | + "\u03b8", "s", "\u0283", "\u0285", "\u0286", "\u0282", "\u0255", "\u00e7", "\u0267", "x", "\u03c7", |
| 581 | + "\u0127", "\u029c", "h", "\u03b2", "v", "\u028d", "\u00f0", "z", "\u0292", "\u0293", "\u0290", |
| 582 | + "\u0291", "\u029d", "\u0263", "\u0281", "\u0295", "\u0296", "\u02a2", "\u0266", "\u026c", "\u026e", |
| 583 | + "m", "m\u0329", "\u0271", "\u0271\u0329", "\u0271\u030d", "n\u032a", "n\u032a\u030d", "n", |
| 584 | + "n\u0329", "\u0273", "\u0273\u0329", "\u0272", "\u0272\u0329", "\u014b", "\u014b\u030d", |
| 585 | + "\u014b\u0329", "\u0274", "\u0274\u0329", "\u0299", "\u0299\u0329", "r", "r\u0329", "\u0280", |
| 586 | + "\u0280\u0329", "\u027e", "\u027d", "\u027f", "\u027a", "l\u032a", "l\u032a\u0329", "l", "l\u0329", |
| 587 | + "\u026b", "\u026b\u0329", "\u026d", "\u026d\u0329", "\u028e", "\u028e\u0329", "\u029f", |
| 588 | + "\u029f\u0329", "w", "\u0265", "\u028b", "\u0279", "\u027b", "j", "\u0270", "\u0298", "\u01c2", |
| 589 | + "\u01c0", "!", "\u01c1", "\u02b0", "\u02b1", "\u02b7", "\u02b8", "\u02b2", "\u02b3", "\u207f", |
| 590 | + "\u02e1", "\u02b4", "\u02b5", "\u02e2", "\u02e3", "\u02e0", "\u02b6", "\u02e4", "\u02c1", "\u02c0", |
| 591 | + "\u02bc", "i", "i\u032f", "\u0129", "y", "y\u032f", "\u1ef9", "\u026a", "\u026a\u032f", |
| 592 | + "\u026a\u0303", "\u028f", "\u028f\u032f", "\u028f\u0303", "\u0268", "\u0268\u032f", "\u0268\u0303", |
| 593 | + "\u0289", "\u0289\u032f", "\u0289\u0303", "\u026f", "\u026f\u032f", "\u026f\u0303", "u", "u\u032f", |
| 594 | + "\u0169", "\u028a", "\u028a\u032f", "\u028a\u0303", "e", "e\u032f", "\u1ebd", "\u00f8", |
| 595 | + "\u00f8\u032f", "\u00f8\u0303", "\u0258", "\u0258\u032f", "\u0258\u0303", "\u0275", "\u0275\u032f", |
| 596 | + "\u0275\u0303", "\u0264", "\u0264\u032f", "\u0264\u0303", "o", "o\u032f", "\u00f5", "\u025b", |
| 597 | + "\u025b\u032f", "\u025b\u0303", "\u0153", "\u0153\u032f", "\u0153\u0303", "\u025c", "\u025c\u032f", |
| 598 | + "\u025c\u0303", "\u0259", "\u0259\u032f", "\u0259\u0303", "\u025e", "\u025e\u032f", "\u025e\u0303", |
| 599 | + "\u028c", "\u028c\u032f", "\u028c\u0303", "\u0254", "\u0254\u032f", "\u0254\u0303", "\u00e6", |
| 600 | + "\u00e6\u032f", "\u00e6\u0303", "\u0276", "\u0276\u032f", "\u0276\u0303", "a", "a\u032f", "\u00e3", |
| 601 | + "\u0250", "\u0250\u032f", "\u0250\u0303", "\u0251", "\u0251\u032f", "\u0251\u0303", "\u0252", |
| 602 | + "\u0252\u032f", "\u0252\u0303", "\u02c8", "\u02cc", "\u02d0", "\u02d1", "\u02d8", ".", "\u203f", |
| 603 | + "|", "\u2016" |
| 604 | + ] |
| 605 | + }, |
| 606 | + 'symbols': { |
| 607 | + 'labelMsg': 'wikieditor-toolbar-characters-page-symbols', |
| 608 | + 'layout': 'characters', |
| 609 | + 'characters': [ |
| 610 | + "~", "|", "\u00a1", "\u00bf", "\u2020", "\u2021", "\u2194", "\u2191", "\u2193", "\u2022", "\u00b6", |
| 611 | + "#", "\u00bd", "\u2153", "\u2154", "\u00bc", "\u00be", "\u215b", "\u215c", "\u215d", "\u215e", |
| 612 | + "\u221e", "\u2018", "\u2019", |
| 613 | + { |
| 614 | + 'label': "\u201c\u201d", |
| 615 | + 'action': { |
| 616 | + 'type': 'encapsulate', 'options': { 'pre': "\u201c", 'post': "\u201d" } |
| 617 | + } |
| 618 | + }, |
| 619 | + { |
| 620 | + 'label': "\u201e\u201c", |
| 621 | + 'action': { |
| 622 | + 'type': 'encapsulate', 'options': { 'pre': "\u201e", 'post': "\u201c" } |
| 623 | + } |
| 624 | + }, |
| 625 | + { |
| 626 | + 'label': "\u00ab\u00bb", |
| 627 | + 'action': { |
| 628 | + 'type': 'encapsulate', 'options': { 'pre': "\u00ab", 'post': "\u00bb" } |
| 629 | + } |
| 630 | + }, |
| 631 | + "\u00a4", "\u20b3", "\u0e3f", "\u20b5", "\u00a2", "\u20a1", "\u20a2", "$", "\u20ab", "\u20af", |
| 632 | + "\u20ac", "\u20a0", "\u20a3", "\u0192", "\u20b4", "\u20ad", "\u20a4", "\u2133", "\u20a5", "\u20a6", |
| 633 | + "\u2116", "\u20a7", "\u20b0", "\u00a3", "\u17db", "\u20a8", "\u20aa", "\u09f3", "\u20ae", "\u20a9", |
| 634 | + "\u00a5", "\u2660", "\u2663", "\u2665", "\u2666", "m\u00b2", "m\u00b3", "\u2013", "\u2014", |
| 635 | + "\u2026", "\u2018", "\u2019", "\u201c", "\u201d", "\u00b0", "\u2032", "\u2033", "\u2248", "\u2260", |
| 636 | + "\u2264", "\u2265", "\u00b1", "\u2212", "\u00d7", "\u00f7", "\u2190", "\u2192", "\u00b7", "\u00a7" |
| 637 | + ] |
| 638 | + }, |
| 639 | + 'greek': { |
| 640 | + 'labelMsg': 'wikieditor-toolbar-characters-page-greek', |
| 641 | + 'layout': 'characters', |
| 642 | + 'language': 'hl', |
| 643 | + 'characters': [ |
| 644 | + "\u0391", "\u0386", "\u03b1", "\u03ac", "\u0392", "\u03b2", "\u0393", "\u03b3", "\u0394", "\u03b4", |
| 645 | + "\u0395", "\u0388", "\u03b5", "\u03ad", "\u0396", "\u03b6", "\u0397", "\u0389", "\u03b7", "\u03ae", |
| 646 | + "\u0398", "\u03b8", "\u0399", "\u038a", "\u03b9", "\u03af", "\u039a", "\u03ba", "\u039b", "\u03bb", |
| 647 | + "\u039c", "\u03bc", "\u039d", "\u03bd", "\u039e", "\u03be", "\u039f", "\u038c", "\u03bf", "\u03cc", |
| 648 | + "\u03a0", "\u03c0", "\u03a1", "\u03c1", "\u03a3", "\u03c3", "\u03c2", "\u03a4", "\u03c4", "\u03a5", |
| 649 | + "\u038e", "\u03c5", "\u03cd", "\u03a6", "\u03c6", "\u03a7", "\u03c7", "\u03a8", "\u03c8", "\u03a9", |
| 650 | + "\u038f", "\u03c9", "\u03ce" |
| 651 | + ] |
| 652 | + }, |
| 653 | + 'cyrillic': { |
| 654 | + 'labelMsg': 'wikieditor-toolbar-characters-page-cyrillic', |
| 655 | + 'layout': 'characters', |
| 656 | + 'characters': [ |
| 657 | + "\u0410", "\u0430", "\u04d8", "\u04d9", "\u0411", "\u0431", "\u0412", "\u0432", "\u0413", "\u0433", |
| 658 | + "\u0490", "\u0491", "\u0403", "\u0453", "\u0492", "\u0493", "\u0414", "\u0434", "\u0402", "\u0452", |
| 659 | + "\u0415", "\u0435", "\u0404", "\u0454", "\u0401", "\u0451", "\u0416", "\u0436", "\u0417", "\u0437", |
| 660 | + "\u0405", "\u0455", "\u0418", "\u0438", "\u0406", "\u0456", "\u0407", "\u0457", "\u04c0", "\u0419", |
| 661 | + "\u0439", "\u04e2", "\u04e3", "\u0408", "\u0458", "\u041a", "\u043a", "\u040c", "\u045c", "\u049a", |
| 662 | + "\u049b", "\u041b", "\u043b", "\u0409", "\u0459", "\u041c", "\u043c", "\u041d", "\u043d", "\u040a", |
| 663 | + "\u045a", "\u04a2", "\u04a3", "\u041e", "\u043e", "\u04e8", "\u04e9", "\u041f", "\u043f", "\u0420", |
| 664 | + "\u0440", "\u0421", "\u0441", "\u0422", "\u0442", "\u040b", "\u045b", "\u0423", "\u0443", "\u040e", |
| 665 | + "\u045e", "\u04ee", "\u04ef", "\u04b0", "\u04b1", "\u04ae", "\u04af", "\u0424", "\u0444", "\u0425", |
| 666 | + "\u0445", "\u04b2", "\u04b3", "\u04ba", "\u04bb", "\u0426", "\u0446", "\u0427", "\u0447", "\u04b6", |
| 667 | + "\u04b7", "\u040f", "\u045f", "\u0428", "\u0448", "\u0429", "\u0449", "\u042a", "\u044a", "\u042b", |
| 668 | + "\u044b", "\u042c", "\u044c", "\u042d", "\u044d", "\u042e", "\u044e", "\u042f", "\u044f" |
| 669 | + ] |
| 670 | + }, |
| 671 | + 'arabic': { |
| 672 | + 'labelMsg': 'wikieditor-toolbar-characters-page-arabic', |
| 673 | + 'layout': 'characters', |
| 674 | + 'language': 'ar', |
| 675 | + 'direction': 'rtl', |
| 676 | + 'characters': [ |
| 677 | + "\u061b", "\u061f", "\u0621", "\u0622", "\u0623", "\u0624", "\u0625", "\u0626", "\u0627", "\u0628", |
| 678 | + "\u0629", "\u062a", "\u062b", "\u062c", "\u062d", "\u062e", "\u062f", "\u0630", "\u0631", "\u0632", |
| 679 | + "\u0633", "\u0634", "\u0635", "\u0636", "\u0637", "\u0638", "\u0639", "\u063a", "\u0641", "\u0642", |
| 680 | + "\u0643", "\u0644", "\u0645", "\u0646", "\u0647", "\u0648", "\u0649", "\u064a", "\u060c", "\u067e", |
| 681 | + "\u0686", "\u0698", "\u06af", "\u06ad" |
| 682 | + ] |
| 683 | + }, |
| 684 | + 'hebrew': { |
| 685 | + 'labelMsg': 'wikieditor-toolbar-characters-page-hebrew', |
| 686 | + 'layout': 'characters', |
| 687 | + 'direction': 'rtl', |
| 688 | + 'characters': [ |
| 689 | + "\u05d0", "\u05d1", "\u05d2", "\u05d3", "\u05d4", "\u05d5", "\u05d6", "\u05d7", "\u05d8", "\u05d9", |
| 690 | + "\u05db", "\u05da", "\u05dc", "\u05de", "\u05dd", "\u05e0", "\u05df", "\u05e1", "\u05e2", "\u05e4", |
| 691 | + "\u05e3", "\u05e6", "\u05e5", "\u05e7", "\u05e8", "\u05e9", "\u05ea", "\u05f3", "\u05f4", "\u05f0", |
| 692 | + "\u05f1", "\u05f2", "\u05d0", "\u05d3", "\u05d4", "\u05d5", "\u05d6", "\u05d7", "\u05d8", "\u05d9", |
| 693 | + "\u05da", "\u05db", "\u05dc", "\u05dd", "\u05de", "\u05df", "\u05e0", "\u05e1", "\u05e2", "\u05e3", |
| 694 | + "\u05e4", "\u05be", "\u05f3", "\u05f4", |
| 695 | + [ "\u05b0\u25cc", "\u05b0" ], [ "\u05b1\u25cc", "\u05b1" ], [ "\u05b2\u25cc", "\u05b2" ], |
| 696 | + [ "\u05b3\u25cc", "\u05b3" ], [ "\u05b4\u25cc", "\u05b4" ], [ "\u05b5\u25cc", "\u05b5" ], |
| 697 | + [ "\u05b6\u25cc", "\u05b6" ], [ "\u05b7\u25cc", "\u05b7" ], [ "\u05b8\u25cc", "\u05b8" ], |
| 698 | + [ "\u05b9\u25cc", "\u05b9" ], [ "\u05bb\u25cc", "\u05bb" ], [ "\u05bc\u25cc", "\u05bc" ], |
| 699 | + [ "\u05c1\u25cc", "\u05c1" ], [ "\u05c2\u25cc", "\u05c2" ], [ "\u05c7\u25cc", "\u05c7" ], |
| 700 | + [ "\u0591\u25cc", "\u0591" ], [ "\u0592\u25cc", "\u0592" ], [ "\u0593\u25cc", "\u0593" ], |
| 701 | + [ "\u0594\u25cc", "\u0594" ], [ "\u0595\u25cc", "\u0595" ], [ "\u0596\u25cc", "\u0596" ], |
| 702 | + [ "\u0597\u25cc", "\u0597" ], [ "\u0598\u25cc", "\u0598" ], [ "\u0599\u25cc", "\u0599" ], |
| 703 | + [ "\u059a\u25cc", "\u059a" ], [ "\u059b\u25cc", "\u059b" ], [ "\u059c\u25cc", "\u059c" ], |
| 704 | + [ "\u059d\u25cc", "\u059d" ], [ "\u059e\u25cc", "\u059e" ], [ "\u059f\u25cc", "\u059f" ], |
| 705 | + [ "\u05a0\u25cc", "\u05a0" ], [ "\u05a1\u25cc", "\u05a1" ], [ "\u05a2\u25cc", "\u05a2" ], |
| 706 | + [ "\u05a3\u25cc", "\u05a3" ], [ "\u05a4\u25cc", "\u05a4" ], [ "\u05a5\u25cc", "\u05a5" ], |
| 707 | + [ "\u05a6\u25cc", "\u05a6" ], [ "\u05a7\u25cc", "\u05a7" ], [ "\u05a8\u25cc", "\u05a8" ], |
| 708 | + [ "\u05a9\u25cc", "\u05a9" ], [ "\u05aa\u25cc", "\u05aa" ], [ "\u05ab\u25cc", "\u05ab" ], |
| 709 | + [ "\u05ac\u25cc", "\u05ac" ], [ "\u05ad\u25cc", "\u05ad" ], [ "\u05ae\u25cc", "\u05ae" ], |
| 710 | + [ "\u05af\u25cc", "\u05af" ], [ "\u05bf\u25cc", "\u05bf" ], [ "\u05c0\u25cc", "\u05c0" ], |
| 711 | + [ "\u05c3\u25cc", "\u05c3" ] |
| 712 | + ] |
| 713 | + }, |
| 714 | + 'bangla': { |
| 715 | + 'labelMsg': 'wikieditor-toolbar-characters-page-bangla', |
| 716 | + 'language': 'bn', |
| 717 | + 'layout': 'characters', |
| 718 | + 'characters': [ |
| 719 | + "\u0985", "\u0986", "\u0987", "\u0988", "\u0989", "\u098a", "\u098b", "\u098f", "\u0990", "\u0993", |
| 720 | + "\u0994", "\u09be", "\u09bf", "\u09c0", "\u09c1", "\u09c2", "\u09c3", "\u09c7", "\u09c8", "\u09cb", |
| 721 | + "\u09cc", "\u0995", "\u0996", "\u0997", "\u0998", "\u0999", "\u099a", "\u099b", "\u099c", "\u099d", |
| 722 | + "\u099e", "\u099f", "\u09a0", "\u09a1", "\u09a2", "\u09a3", "\u09a4", "\u09a5", "\u09a6", "\u09a7", |
| 723 | + "\u09a8", "\u09aa", "\u09ab", "\u09ac", "\u09ad", "\u09ae", "\u09af", "\u09b0", "\u09b2", "\u09b6", |
| 724 | + "\u09b7", "\u09b8", "\u09b9", "\u09a1\u09bc", "\u09a2\u09bc", "\u09af\u09bc", "\u09ce", "\u0982", |
| 725 | + "\u0983", "\u0981", "\u09cd", "\u09e7", "\u09e8", "\u09e9", "\u09ea", "\u09eb", "\u09ec", "\u09ed", |
| 726 | + "\u09ee", "\u09ef", "\u09e6" |
| 727 | + ] |
| 728 | + }, |
| 729 | + 'telugu': { |
| 730 | + 'labelMsg': 'wikieditor-toolbar-characters-page-telugu', |
| 731 | + 'language': 'te', |
| 732 | + 'layout': 'characters', |
| 733 | + 'characters': [ |
| 734 | + "\u0c01", "\u0c02", "\u0c03", "\u0c05", "\u0c06", "\u0c07", "\u0c08", "\u0c09", "\u0c0a", "\u0c0b", |
| 735 | + "\u0c60", "\u0c0c", "\u0c61", "\u0c0e", "\u0c0f", "\u0c10", "\u0c12", "\u0c13", "\u0c14", "\u0c15", |
| 736 | + "\u0c16", "\u0c17", "\u0c18", "\u0c19", "\u0c1a", "\u0c1b", "\u0c1c", "\u0c1d", "\u0c1e", "\u0c1f", |
| 737 | + "\u0c20", "\u0c21", "\u0c22", "\u0c23", "\u0c24", "\u0c25", "\u0c26", "\u0c27", "\u0c28", "\u0c2a", |
| 738 | + "\u0c2b", "\u0c2c", "\u0c2d", "\u0c2e", "\u0c2f", "\u0c30", "\u0c31", "\u0c32", "\u0c33", "\u0c35", |
| 739 | + "\u0c36", "\u0c37", "\u0c38", "\u0c39", "\u0c3e", "\u0c3f", "\u0c40", "\u0c41", "\u0c42", "\u0c43", |
| 740 | + "\u0c44", "\u0c46", "\u0c47", "\u0c48", "\u0c4a", "\u0c4b", "\u0c4c", "\u0c4d", "\u0c62", "\u0c63", |
| 741 | + "\u0c58", "\u0c59", "\u0c66", "\u0c67", "\u0c68", "\u0c69", "\u0c6a", "\u0c6b", "\u0c6c", "\u0c6d", |
| 742 | + "\u0c6e", "\u0c6f", "\u0c3d", "\u0c78", "\u0c79", "\u0c7a", "\u0c7b", "\u0c7c", "\u0c7d", "\u0c7e", |
| 743 | + "\u0c7f" |
| 744 | + ] |
| 745 | + }, |
| 746 | + 'sinhala': { |
| 747 | + 'labelMsg': 'wikieditor-toolbar-characters-page-sinhala', |
| 748 | + 'language': 'si', |
| 749 | + 'layout': 'characters', |
| 750 | + 'characters': [ |
| 751 | + "\u0d85", "\u0d86", "\u0d87", "\u0d88", "\u0d89", "\u0d8a", "\u0d8b", "\u0d8c", "\u0d8d", "\u0d8e", |
| 752 | + "\u0d8f", "\u0d90", "\u0d91", "\u0d92", "\u0d93", "\u0d94", "\u0d95", "\u0d96", "\u0d9a", "\u0d9b", |
| 753 | + "\u0d9c", "\u0d9d", "\u0d9e", "\u0d9f", "\u0da0", "\u0da1", "\u0da2", "\u0da3", "\u0da4", "\u0da5", |
| 754 | + "\u0da6", "\u0da7", "\u0da8", "\u0da9", "\u0daa", "\u0dab", "\u0dac", "\u0dad", "\u0dae", "\u0daf", |
| 755 | + "\u0db0", "\u0db1", "\u0db3", "\u0db4", "\u0db5", "\u0db6", "\u0db7", "\u0db8", "\u0db9", "\u0dba", |
| 756 | + "\u0dbb", "\u0dbd", "\u0dc0", "\u0dc1", "\u0dc2", "\u0dc3", "\u0dc4", "\u0dc5", "\u0dc6", |
| 757 | + [ "\u25cc\u0dcf", "\u0dcf" ], [ "\u25cc\u0dd0", "\u0dd0" ], [ "\u25cc\u0dd1", "\u0dd1" ], |
| 758 | + [ "\u25cc\u0dd2", "\u0dd2" ], [ "\u25cc\u0dd3", "\u0dd3" ], [ "\u25cc\u0dd4", "\u0dd4" ], |
| 759 | + [ "\u25cc\u0dd6", "\u0dd6" ], [ "\u25cc\u0dd8", "\u0dd8" ], [ "\u25cc\u0df2", "\u0df2" ], |
| 760 | + [ "\u25cc\u0ddf", "\u0ddf" ], [ "\u25cc\u0df3", "\u0df3" ], [ "\u25cc\u0dd9", "\u0dd9" ], |
| 761 | + [ "\u25cc\u0dda", "\u0dda" ], [ "\u25cc\u0ddc", "\u0ddc" ], [ "\u25cc\u0ddd", "\u0ddd" ], |
| 762 | + [ "\u25cc\u0dde", "\u0dde" ], [ "\u25cc\u0dca", "\u0dca" ] |
| 763 | + ] |
| 764 | + }, |
| 765 | + 'gujarati': { |
| 766 | + 'labelMsg': 'wikieditor-toolbar-characters-page-gujarati', |
| 767 | + 'language': 'gu', |
| 768 | + 'layout': 'characters', |
| 769 | + 'characters': [ |
| 770 | + "\u0ad0", "\u0a85", "\u0a86", "\u0a87", "\u0a88", "\u0a89", "\u0a8a", "\u0a8b", "\u0ae0", "\u0a8c", |
| 771 | + "\u0ae1", "\u0a8d", "\u0a8f", "\u0a90", "\u0a91", "\u0a93", "\u0a94", "\u0a95", "\u0a96", "\u0a97", |
| 772 | + "\u0a98", "\u0a99", "\u0a9a", "\u0a9b", "\u0a9c", "\u0a9d", "\u0a9e", "\u0a9f", "\u0aa0", "\u0aa1", |
| 773 | + "\u0aa2", "\u0aa3", "\u0aa4", "\u0aa5", "\u0aa6", "\u0aa7", "\u0aa8", "\u0aaa", "\u0aab", "\u0aac", |
| 774 | + "\u0aad", "\u0aae", "\u0aaf", "\u0ab0", "\u0ab2", "\u0ab5", "\u0ab6", "\u0ab7", "\u0ab8", "\u0ab9", |
| 775 | + "\u0ab3", "\u0abd", [ "\u25cc\u0abe", "\u0abe" ], [ "\u25cc\u0abf", "\u0abf" ], |
| 776 | + [ "\u25cc\u0ac0", "\u0ac0" ], [ "\u25cc\u0ac1", "\u0ac1" ], [ "\u25cc\u0ac2", "\u0ac2" ], |
| 777 | + [ "\u25cc\u0ac3", "\u0ac3" ], [ "\u25cc\u0ac4", "\u0ac4" ], [ "\u25cc\u0ae2", "\u0ae2" ], |
| 778 | + [ "\u25cc\u0ae3", "\u0ae3" ], [ "\u25cc\u0ac5", "\u0ac5" ], [ "\u25cc\u0ac7", "\u0ac7" ], |
| 779 | + [ "\u25cc\u0ac8", "\u0ac8" ], [ "\u25cc\u0ac9", "\u0ac9" ], [ "\u25cc\u0acb", "\u0acb" ], |
| 780 | + [ "\u25cc\u0acc", "\u0acc" ], [ "\u25cc\u0acd", "\u0acd" ] |
| 781 | + ] |
| 782 | + }, |
| 783 | + 'thai': { |
| 784 | + 'labelMsg': 'wikieditor-toolbar-characters-page-thai', |
| 785 | + 'language': 'th', |
| 786 | + 'layout': 'characters', |
| 787 | + 'characters': [ |
| 788 | + "\u0e01", "\u0e02", "\u0e03", "\u0e04", "\u0e05", "\u0e06", "\u0e07", "\u0e08", "\u0e09", "\u0e0a", |
| 789 | + "\u0e0b", "\u0e0c", "\u0e0d", "\u0e0e", "\u0e0f", "\u0e10", "\u0e11", "\u0e12", "\u0e13", "\u0e14", |
| 790 | + "\u0e15", "\u0e16", "\u0e17", "\u0e18", "\u0e19", "\u0e1a", "\u0e1b", "\u0e1c", "\u0e1d", "\u0e1e", |
| 791 | + "\u0e1f", "\u0e20", "\u0e21", "\u0e22", "\u0e23", "\u0e24", "\u0e25", "\u0e26", "\u0e27", "\u0e28", |
| 792 | + "\u0e29", "\u0e2a", "\u0e2b", "\u0e2c", "\u0e2d", "\u0e2e", "\u0e30", "\u0e31", "\u0e32", "\u0e45", |
| 793 | + "\u0e33", "\u0e34", "\u0e35", "\u0e36", "\u0e37", "\u0e38", "\u0e39", "\u0e40", "\u0e41", "\u0e42", |
| 794 | + "\u0e43", "\u0e44", "\u0e47", "\u0e48", "\u0e49", "\u0e4a", "\u0e4b", "\u0e4c", "\u0e4d", "\u0e3a", |
| 795 | + "\u0e4e", "\u0e50", "\u0e51", "\u0e52", "\u0e53", "\u0e54", "\u0e55", "\u0e56", "\u0e57", "\u0e58", |
| 796 | + "\u0e59", "\u0e3f", "\u0e46", "\u0e2f", "\u0e5a", "\u0e4f", "\u0e5b" |
| 797 | + ] |
| 798 | + }, |
| 799 | + 'lao': { |
| 800 | + 'labelMsg': 'wikieditor-toolbar-characters-page-lao', |
| 801 | + 'language': 'lo', |
| 802 | + 'layout': 'characters', |
| 803 | + 'characters': [ |
| 804 | + "\u0e81", "\u0e82", "\u0e84", "\u0e87", "\u0e88", "\u0eaa", "\u0e8a", "\u0e8d", "\u0e94", "\u0e95", |
| 805 | + "\u0e96", "\u0e97", "\u0e99", "\u0e9a", "\u0e9b", "\u0e9c", "\u0e9d", "\u0e9e", "\u0e9f", "\u0ea1", |
| 806 | + "\u0ea2", "\u0ea5", "\u0ea7", "\u0eab", "\u0ead", "\u0eae", "\u0ea3", "\u0edc", "\u0edd", "\u0ebc", |
| 807 | + "\u0ebd", "\u0eb0", "\u0eb1", "\u0eb2", "\u0eb3", "\u0eb4", "\u0eb5", "\u0eb6", "\u0eb7", "\u0eb8", |
| 808 | + "\u0eb9", "\u0ebb", "\u0ec0", "\u0ec1", "\u0ec2", "\u0ec3", "\u0ec4", "\u0ec8", "\u0ec9", "\u0eca", |
| 809 | + "\u0ecb", "\u0ecc", "\u0ecd", "\u0ed0", "\u0ed1", "\u0ed2", "\u0ed3", "\u0ed4", "\u0ed5", "\u0ed6", |
| 810 | + "\u0ed7", "\u0ed8", "\u0ed9", "\u20ad", "\u0ec6", "\u0eaf" |
| 811 | + ] |
| 812 | + }, |
| 813 | + 'khmer': { |
| 814 | + 'labelMsg': 'wikieditor-toolbar-characters-page-khmer', |
| 815 | + 'language': 'km', |
| 816 | + 'layout': 'characters', |
| 817 | + 'characters': [ |
| 818 | + "\u1780", "\u1781", "\u1782", "\u1783", "\u1784", "\u1785", "\u1786", "\u1787", "\u1788", "\u1789", |
| 819 | + "\u178a", "\u178b", "\u178c", "\u178d", "\u178e", "\u178f", "\u1790", "\u1791", "\u1792", "\u1793", |
| 820 | + "\u1794", "\u1795", "\u1796", "\u1797", "\u1798", "\u1799", "\u179a", "\u179b", "\u179c", "\u179f", |
| 821 | + "\u17a0", "\u17a1", "\u17a2", "\u17a3", "\u17a4", "\u17a5", "\u17a6", "\u17a7", "\u17a8", "\u17a9", |
| 822 | + "\u17aa", "\u17ab", "\u17ac", "\u17ad", "\u17ae", "\u17af", "\u17b0", "\u17b1", "\u17b2", "\u17b3", |
| 823 | + "\u17d2", "\u17b4", "\u17b5", "\u17b6", "\u17b7", "\u17b8", "\u17b9", "\u17ba", "\u17bb", "\u17bc", |
| 824 | + "\u17bd", "\u17be", "\u17bf", "\u17c0", "\u17c1", "\u17c2", "\u17c3", "\u17c4", "\u17c5", "\u17c6", |
| 825 | + "\u17c7", "\u17c8", "\u17c9", "\u17ca", "\u17cb", "\u17cc", "\u17cd", "\u17ce", "\u17cf", "\u17d0", |
| 826 | + "\u17d1", "\u17d3", "\u17dd", "\u17dc", "\u17e0", "\u17e1", "\u17e2", "\u17e3", "\u17e4", "\u17e5", |
| 827 | + "\u17e6", "\u17e7", "\u17e8", "\u17e9", "\u17db", "\u17d4", "\u17d5", "\u17d6", "\u17d7", "\u17d8", |
| 828 | + "\u17d9", "\u17da", "\u17f0", "\u17f1", "\u17f2", "\u17f3", "\u17f4", "\u17f5", "\u17f6", "\u17f7", |
| 829 | + "\u17f8", "\u17f9", "\u19e0", "\u19e1", "\u19e2", "\u19e3", "\u19e4", "\u19e5", "\u19e6", "\u19e7", |
| 830 | + "\u19e8", "\u19e9", "\u19ea", "\u19eb", "\u19ec", "\u19ed", "\u19ee", "\u19ef", "\u19f0", "\u19f1", |
| 831 | + "\u19f2", "\u19f3", "\u19f4", "\u19f5", "\u19f6", "\u19f7", "\u19f8", "\u19f9", "\u19fa", "\u19fb", |
| 832 | + "\u19fc", "\u19fd", "\u19fe", "\u19ff" |
| 833 | + ] |
| 834 | + } |
| 835 | + } |
| 836 | + }, |
| 837 | + 'help': { |
| 838 | + labelMsg: 'wikieditor-toolbar-section-help', |
| 839 | + type: 'booklet', |
| 840 | + deferLoad: true, |
| 841 | + pages: { |
| 842 | + 'format': { |
| 843 | + labelMsg: 'wikieditor-toolbar-help-page-format', |
| 844 | + layout: 'table', |
| 845 | + headings: [ |
| 846 | + { textMsg: 'wikieditor-toolbar-help-heading-description' }, |
| 847 | + { textMsg: 'wikieditor-toolbar-help-heading-syntax' }, |
| 848 | + { textMsg: 'wikieditor-toolbar-help-heading-result' } |
| 849 | + ], |
| 850 | + rows: [ |
| 851 | + { |
| 852 | + 'description': { htmlMsg: 'wikieditor-toolbar-help-content-italic-description' }, |
| 853 | + 'syntax': { htmlMsg: 'wikieditor-toolbar-help-content-italic-syntax' }, |
| 854 | + 'result': { htmlMsg: 'wikieditor-toolbar-help-content-italic-result' } |
| 855 | + }, |
| 856 | + { |
| 857 | + 'description': { htmlMsg: 'wikieditor-toolbar-help-content-bold-description' }, |
| 858 | + 'syntax': { htmlMsg: 'wikieditor-toolbar-help-content-bold-syntax' }, |
| 859 | + 'result': { htmlMsg: 'wikieditor-toolbar-help-content-bold-result' } |
| 860 | + }, |
| 861 | + { |
| 862 | + 'description': { htmlMsg: 'wikieditor-toolbar-help-content-bolditalic-description' }, |
| 863 | + 'syntax': { htmlMsg: 'wikieditor-toolbar-help-content-bolditalic-syntax' }, |
| 864 | + 'result': { htmlMsg: 'wikieditor-toolbar-help-content-bolditalic-result' } |
| 865 | + } |
| 866 | + ] |
| 867 | + }, |
| 868 | + 'link': { |
| 869 | + labelMsg: 'wikieditor-toolbar-help-page-link', |
| 870 | + layout: 'table', |
| 871 | + headings: [ |
| 872 | + { textMsg: 'wikieditor-toolbar-help-heading-description' }, |
| 873 | + { textMsg: 'wikieditor-toolbar-help-heading-syntax' }, |
| 874 | + { textMsg: 'wikieditor-toolbar-help-heading-result' } |
| 875 | + ], |
| 876 | + rows: [ |
| 877 | + { |
| 878 | + 'description': { htmlMsg: 'wikieditor-toolbar-help-content-ilink-description' }, |
| 879 | + 'syntax': { htmlMsg: 'wikieditor-toolbar-help-content-ilink-syntax' }, |
| 880 | + 'result': { htmlMsg: 'wikieditor-toolbar-help-content-ilink-result' } |
| 881 | + }, |
| 882 | + { |
| 883 | + 'description': { htmlMsg: 'wikieditor-toolbar-help-content-xlink-description' }, |
| 884 | + 'syntax': { htmlMsg: 'wikieditor-toolbar-help-content-xlink-syntax' }, |
| 885 | + 'result': { htmlMsg: 'wikieditor-toolbar-help-content-xlink-result' } |
| 886 | + } |
| 887 | + ] |
| 888 | + }, |
| 889 | + 'heading': { |
| 890 | + labelMsg: 'wikieditor-toolbar-help-page-heading', |
| 891 | + layout: 'table', |
| 892 | + headings: [ |
| 893 | + { textMsg: 'wikieditor-toolbar-help-heading-description' }, |
| 894 | + { textMsg: 'wikieditor-toolbar-help-heading-syntax' }, |
| 895 | + { textMsg: 'wikieditor-toolbar-help-heading-result' } |
| 896 | + ], |
| 897 | + rows: [ |
| 898 | + { |
| 899 | + 'description': { htmlMsg: 'wikieditor-toolbar-help-content-heading2-description' }, |
| 900 | + 'syntax': { htmlMsg: 'wikieditor-toolbar-help-content-heading2-syntax' }, |
| 901 | + 'result': { htmlMsg: 'wikieditor-toolbar-help-content-heading2-result' } |
| 902 | + }, |
| 903 | + { |
| 904 | + 'description': { htmlMsg: 'wikieditor-toolbar-help-content-heading3-description' }, |
| 905 | + 'syntax': { htmlMsg: 'wikieditor-toolbar-help-content-heading3-syntax' }, |
| 906 | + 'result': { htmlMsg: 'wikieditor-toolbar-help-content-heading3-result' } |
| 907 | + }, |
| 908 | + { |
| 909 | + 'description': { htmlMsg: 'wikieditor-toolbar-help-content-heading4-description' }, |
| 910 | + 'syntax': { htmlMsg: 'wikieditor-toolbar-help-content-heading4-syntax' }, |
| 911 | + 'result': { htmlMsg: 'wikieditor-toolbar-help-content-heading4-result' } |
| 912 | + }, |
| 913 | + { |
| 914 | + 'description': { htmlMsg: 'wikieditor-toolbar-help-content-heading5-description' }, |
| 915 | + 'syntax': { htmlMsg: 'wikieditor-toolbar-help-content-heading5-syntax' }, |
| 916 | + 'result': { htmlMsg: 'wikieditor-toolbar-help-content-heading5-result' } |
| 917 | + } |
| 918 | + ] |
| 919 | + }, |
| 920 | + 'list': { |
| 921 | + labelMsg: 'wikieditor-toolbar-help-page-list', |
| 922 | + layout: 'table', |
| 923 | + headings: [ |
| 924 | + { textMsg: 'wikieditor-toolbar-help-heading-description' }, |
| 925 | + { textMsg: 'wikieditor-toolbar-help-heading-syntax' }, |
| 926 | + { textMsg: 'wikieditor-toolbar-help-heading-result' } |
| 927 | + ], |
| 928 | + rows: [ |
| 929 | + { |
| 930 | + 'description': { htmlMsg: 'wikieditor-toolbar-help-content-ulist-description' }, |
| 931 | + 'syntax': { htmlMsg: 'wikieditor-toolbar-help-content-ulist-syntax' }, |
| 932 | + 'result': { htmlMsg: 'wikieditor-toolbar-help-content-ulist-result' } |
| 933 | + }, |
| 934 | + { |
| 935 | + 'description': { htmlMsg: 'wikieditor-toolbar-help-content-olist-description' }, |
| 936 | + 'syntax': { htmlMsg: 'wikieditor-toolbar-help-content-olist-syntax' }, |
| 937 | + 'result': { htmlMsg: 'wikieditor-toolbar-help-content-olist-result' } |
| 938 | + } |
| 939 | + ] |
| 940 | + }, |
| 941 | + 'file': { |
| 942 | + labelMsg: 'wikieditor-toolbar-help-page-file', |
| 943 | + layout: 'table', |
| 944 | + headings: [ |
| 945 | + { textMsg: 'wikieditor-toolbar-help-heading-description' }, |
| 946 | + { textMsg: 'wikieditor-toolbar-help-heading-syntax' }, |
| 947 | + { textMsg: 'wikieditor-toolbar-help-heading-result' } |
| 948 | + ], |
| 949 | + rows: [ |
| 950 | + { |
| 951 | + 'description': { htmlMsg: 'wikieditor-toolbar-help-content-file-description' }, |
| 952 | + 'syntax': { htmlMsg: 'wikieditor-toolbar-help-content-file-syntax' }, |
| 953 | + 'result': { htmlMsg: [ 'wikieditor-toolbar-help-content-file-result', stylepath ] } |
| 954 | + } |
| 955 | + ] |
| 956 | + }, |
| 957 | + 'reference': { |
| 958 | + labelMsg: 'wikieditor-toolbar-help-page-reference', |
| 959 | + layout: 'table', |
| 960 | + headings: [ |
| 961 | + { textMsg: 'wikieditor-toolbar-help-heading-description' }, |
| 962 | + { textMsg: 'wikieditor-toolbar-help-heading-syntax' }, |
| 963 | + { textMsg: 'wikieditor-toolbar-help-heading-result' } |
| 964 | + ], |
| 965 | + rows: [ |
| 966 | + { |
| 967 | + 'description': { htmlMsg: 'wikieditor-toolbar-help-content-reference-description' }, |
| 968 | + 'syntax': { htmlMsg: 'wikieditor-toolbar-help-content-reference-syntax' }, |
| 969 | + 'result': { htmlMsg: 'wikieditor-toolbar-help-content-reference-result' } |
| 970 | + }, |
| 971 | + { |
| 972 | + 'description': { htmlMsg: 'wikieditor-toolbar-help-content-rereference-description' }, |
| 973 | + 'syntax': { htmlMsg: 'wikieditor-toolbar-help-content-rereference-syntax' }, |
| 974 | + 'result': { htmlMsg: 'wikieditor-toolbar-help-content-rereference-result' } |
| 975 | + }, |
| 976 | + { |
| 977 | + 'description': { htmlMsg: 'wikieditor-toolbar-help-content-showreferences-description' }, |
| 978 | + 'syntax': { htmlMsg: 'wikieditor-toolbar-help-content-showreferences-syntax' }, |
| 979 | + 'result': { htmlMsg: 'wikieditor-toolbar-help-content-showreferences-result' } |
| 980 | + } |
| 981 | + ] |
| 982 | + }, |
| 983 | + 'discussion': { |
| 984 | + labelMsg: 'wikieditor-toolbar-help-page-discussion', |
| 985 | + layout: 'table', |
| 986 | + headings: [ |
| 987 | + { textMsg: 'wikieditor-toolbar-help-heading-description' }, |
| 988 | + { textMsg: 'wikieditor-toolbar-help-heading-syntax' }, |
| 989 | + { textMsg: 'wikieditor-toolbar-help-heading-result' } |
| 990 | + ], |
| 991 | + rows: [ |
| 992 | + { |
| 993 | + 'description': { htmlMsg: 'wikieditor-toolbar-help-content-signaturetimestamp-description' }, |
| 994 | + 'syntax': { htmlMsg: 'wikieditor-toolbar-help-content-signaturetimestamp-syntax' }, |
| 995 | + 'result': { htmlMsg: 'wikieditor-toolbar-help-content-signaturetimestamp-result' } |
| 996 | + }, |
| 997 | + { |
| 998 | + 'description': { htmlMsg: 'wikieditor-toolbar-help-content-signature-description' }, |
| 999 | + 'syntax': { htmlMsg: 'wikieditor-toolbar-help-content-signature-syntax' }, |
| 1000 | + 'result': { htmlMsg: 'wikieditor-toolbar-help-content-signature-result' } |
| 1001 | + }, |
| 1002 | + { |
| 1003 | + 'description': { htmlMsg: 'wikieditor-toolbar-help-content-indent-description' }, |
| 1004 | + 'syntax': { htmlMsg: 'wikieditor-toolbar-help-content-indent-syntax' }, |
| 1005 | + 'result': { htmlMsg: 'wikieditor-toolbar-help-content-indent-result' } |
| 1006 | + } |
| 1007 | + ] |
| 1008 | + } |
| 1009 | + } |
| 1010 | + } |
| 1011 | +}, |
| 1012 | +'dialogs': { |
| 1013 | + 'insert-link': { |
| 1014 | + // For now, apply the old browser and iframe requirements to the link and table dialogs as well |
| 1015 | + // This'll be removed once these dialogs are confirmed stable without the iframe and/or in more browsers |
| 1016 | + /* |
| 1017 | + 'browsers': { |
| 1018 | + // Left-to-right languages |
| 1019 | + 'ltr': { |
| 1020 | + 'msie': [['>=', 7]], |
| 1021 | + 'firefox': [['>=', 3]], |
| 1022 | + 'opera': [['>=', 10]], |
| 1023 | + 'safari': [['>=', 4]], |
| 1024 | + 'chrome': [['>=', 4]] |
| 1025 | + }, |
| 1026 | + // Right-to-left languages |
| 1027 | + 'rtl': { |
| 1028 | + 'msie': [['>=', 8]], |
| 1029 | + 'firefox': [['>=', 3]], |
| 1030 | + 'opera': [['>=', 10]], |
| 1031 | + 'safari': [['>=', 4]], |
| 1032 | + 'chrome': [['>=', 4]] |
| 1033 | + } |
| 1034 | + }, |
| 1035 | + 'req': [ 'iframe' ], |
| 1036 | + */ |
| 1037 | + filters: [ '#wpTextbox1.toolbar-dialogs' ], |
| 1038 | + titleMsg: 'wikieditor-toolbar-tool-link-title', |
| 1039 | + id: 'wikieditor-toolbar-link-dialog', |
| 1040 | + html: '\ |
| 1041 | + <fieldset>\ |
| 1042 | + <div class="wikieditor-toolbar-field-wrapper">\ |
| 1043 | + <label for="wikieditor-toolbar-link-int-target" rel="wikieditor-toolbar-tool-link-int-target" id="wikieditor-toolbar-tool-link-int-target-label"></label>\ |
| 1044 | + <div id="wikieditor-toolbar-link-int-target-status"></div>\ |
| 1045 | + <input type="text" id="wikieditor-toolbar-link-int-target" />\ |
| 1046 | + </div>\ |
| 1047 | + <div class="wikieditor-toolbar-field-wrapper">\ |
| 1048 | + <label for="wikieditor-toolbar-link-int-text" rel="wikieditor-toolbar-tool-link-int-text"></label>\ |
| 1049 | + <input type="text" id="wikieditor-toolbar-link-int-text" />\ |
| 1050 | + </div>\ |
| 1051 | + <div class="wikieditor-toolbar-field-wrapper">\ |
| 1052 | + <div class="wikieditor-toolbar-floated-field-wrapper">\ |
| 1053 | + <input type="radio" id="wikieditor-toolbar-link-type-int" name="wikieditor-toolbar-link-type" selected />\ |
| 1054 | + <label for="wikieditor-toolbar-link-type-int" rel="wikieditor-toolbar-tool-link-int"></label>\ |
| 1055 | + </div>\ |
| 1056 | + <div class="wikieditor-toolbar-floated-field-wrapper">\ |
| 1057 | + <input type="radio" id="wikieditor-toolbar-link-type-ext" name="wikieditor-toolbar-link-type" />\ |
| 1058 | + <label for="wikieditor-toolbar-link-type-ext" rel="wikieditor-toolbar-tool-link-ext"></label>\ |
| 1059 | + </div>\ |
| 1060 | + </div>\ |
| 1061 | + </fieldset>', |
| 1062 | + init: function() { |
| 1063 | + function isExternalLink( s ) { |
| 1064 | + // The following things are considered to be external links: |
| 1065 | + // * Starts a URL protocol |
| 1066 | + // * Starts with www. |
| 1067 | + // All of these are potentially valid titles, and the latter two |
| 1068 | + // categories match about 6300 titles in enwiki's ns0. Out of 6.9M |
| 1069 | + // titles, that's 0.09% |
| 1070 | + if ( typeof arguments.callee.regex == 'undefined' ) { |
| 1071 | + // Cache the regex |
| 1072 | + arguments.callee.regex = |
| 1073 | + new RegExp( "^(" + wgUrlProtocols + "|www\\.)", 'i'); |
| 1074 | + } |
| 1075 | + return s.match( arguments.callee.regex ); |
| 1076 | + } |
| 1077 | + // Updates the status indicator above the target link |
| 1078 | + function updateWidget( status ) { |
| 1079 | + $j( '#wikieditor-toolbar-link-int-target-status' ).children().hide(); |
| 1080 | + $j( '#wikieditor-toolbar-link-int-target' ).parent() |
| 1081 | + .removeClass( 'status-invalid status-external status-notexists status-exists status-loading' ); |
| 1082 | + if ( status ) { |
| 1083 | + $j( '#wikieditor-toolbar-link-int-target-status-' + status ).show(); |
| 1084 | + $j( '#wikieditor-toolbar-link-int-target' ).parent().addClass( 'status-' + status ); |
| 1085 | + } |
| 1086 | + if ( status == 'invalid' ) { |
| 1087 | + $j( '.ui-dialog:visible .ui-dialog-buttonpane button:first' ) |
| 1088 | + .attr( 'disabled', true ) |
| 1089 | + .addClass( 'disabled' ); |
| 1090 | + } else { |
| 1091 | + $j( '.ui-dialog:visible .ui-dialog-buttonpane button:first' ) |
| 1092 | + .removeAttr('disabled') |
| 1093 | + .removeClass('disabled'); |
| 1094 | + } |
| 1095 | + } |
| 1096 | + // Updates the UI to show if the page title being inputed by the user exists or not |
| 1097 | + // accepts parameter internal for bypassing external link detection |
| 1098 | + function updateExistence( internal ) { |
| 1099 | + // ensure the internal parameter is a boolean |
| 1100 | + if ( internal != true ) internal = false; |
| 1101 | + // Abort previous request |
| 1102 | + var request = $j( '#wikieditor-toolbar-link-int-target-status' ).data( 'request' ); |
| 1103 | + if ( request ) { |
| 1104 | + request.abort(); |
| 1105 | + } |
| 1106 | + var target = $j( '#wikieditor-toolbar-link-int-target' ).val(); |
| 1107 | + var cache = $j( '#wikieditor-toolbar-link-int-target-status' ).data( 'existencecache' ); |
| 1108 | + if ( cache[target] ) { |
| 1109 | + updateWidget( cache[target] ); |
| 1110 | + return; |
| 1111 | + } |
| 1112 | + if ( target.replace( /^\s+$/,'' ) == '' ) { |
| 1113 | + // Hide the widget when the textbox is empty |
| 1114 | + updateWidget( false ); |
| 1115 | + return; |
| 1116 | + } |
| 1117 | + // If the forced internal paremter was not true, check if the target is an external link |
| 1118 | + if ( !internal && isExternalLink( target ) ) { |
| 1119 | + updateWidget( 'external' ); |
| 1120 | + return; |
| 1121 | + } |
| 1122 | + if ( target.indexOf( '|' ) != -1 ) { |
| 1123 | + // Title contains | , which means it's invalid |
| 1124 | + // but confuses the API. Show invalid and bypass API |
| 1125 | + updateWidget( 'invalid' ); |
| 1126 | + return; |
| 1127 | + } |
| 1128 | + // Show loading spinner while waiting for the API to respond |
| 1129 | + updateWidget( 'loading' ); |
| 1130 | + // Call the API to check page status, saving the request object so it can be aborted if necessary |
| 1131 | + $j( '#wikieditor-toolbar-link-int-target-status' ).data( |
| 1132 | + 'request', |
| 1133 | + $j.ajax( { |
| 1134 | + url: wgScriptPath + '/api.php', |
| 1135 | + dataType: 'json', |
| 1136 | + data: { |
| 1137 | + 'action': 'query', |
| 1138 | + 'indexpageids': '', |
| 1139 | + 'titles': target, |
| 1140 | + 'converttitles': '', |
| 1141 | + 'format': 'json' |
| 1142 | + }, |
| 1143 | + success: function( data ) { |
| 1144 | + var status; |
| 1145 | + if ( !data || typeof data.query == 'undefined' ) { |
| 1146 | + // This happens in some weird cases |
| 1147 | + status = false; |
| 1148 | + } else { |
| 1149 | + var page = data.query.pages[data.query.pageids[0]]; |
| 1150 | + status = 'exists'; |
| 1151 | + if ( typeof page.missing != 'undefined' ) |
| 1152 | + status = 'notexists'; |
| 1153 | + else if ( typeof page.invalid != 'undefined' ) |
| 1154 | + status = 'invalid'; |
| 1155 | + } |
| 1156 | + // Cache the status of the link target if the force internal parameter was not passed |
| 1157 | + if ( !internal ) cache[target] = status; |
| 1158 | + updateWidget( status ); |
| 1159 | + } |
| 1160 | + } ) |
| 1161 | + ); |
| 1162 | + } |
| 1163 | + $j( '#wikieditor-toolbar-link-type-int, #wikieditor-toolbar-link-type-ext' ).click( function() { |
| 1164 | + if( $j( '#wikieditor-toolbar-link-type-ext' ).is( ':checked' ) ) { |
| 1165 | + // Abort previous request |
| 1166 | + var request = $j( '#wikieditor-toolbar-link-int-target-status' ).data( 'request' ); |
| 1167 | + if ( request ) { |
| 1168 | + request.abort(); |
| 1169 | + } |
| 1170 | + updateWidget( 'external' ); |
| 1171 | + } |
| 1172 | + if( $j( '#wikieditor-toolbar-link-type-int' ).is( ':checked' ) ) |
| 1173 | + updateExistence( true ); |
| 1174 | + }); |
| 1175 | + // Set labels of tabs based on rel values |
| 1176 | + var u = mw.usability; |
| 1177 | + $j(this).find( '[rel]' ).each( function() { |
| 1178 | + $j(this).text( u.getMsg( $j(this).attr( 'rel' ) ) ); |
| 1179 | + }); |
| 1180 | + // Set tabindexes on form fields |
| 1181 | + $j.wikiEditor.modules.dialogs.fn.setTabindexes( $j(this).find( 'input' ).not( '[tabindex]' ) ); |
| 1182 | + // Setup the tooltips in the textboxes |
| 1183 | + $j( '#wikieditor-toolbar-link-int-target' ) |
| 1184 | + .data( 'tooltip', u.getMsg( 'wikieditor-toolbar-tool-link-int-target-tooltip' ) ); |
| 1185 | + $j( '#wikieditor-toolbar-link-int-text' ) |
| 1186 | + .data( 'tooltip', u.getMsg( 'wikieditor-toolbar-tool-link-int-text-tooltip' ) ); |
| 1187 | + $j( '#wikieditor-toolbar-link-int-target, #wikieditor-toolbar-link-int-text' ) |
| 1188 | + .each( function() { |
| 1189 | + var tooltip = u.getMsg( $j( this ).attr( 'id' ) + '-tooltip' ); |
| 1190 | + if ( $j( this ).val() == '' ) |
| 1191 | + $j( this ) |
| 1192 | + .addClass( 'wikieditor-toolbar-dialog-hint' ) |
| 1193 | + .val( $j( this ).data( 'tooltip' ) ) |
| 1194 | + .data( 'tooltip-mode', true ); |
| 1195 | + } ) |
| 1196 | + .focus( function() { |
| 1197 | + if( $j( this ).val() == $j( this ).data( 'tooltip' ) ) { |
| 1198 | + $j( this ) |
| 1199 | + .val( '' ) |
| 1200 | + .removeClass( 'wikieditor-toolbar-dialog-hint' ) |
| 1201 | + .data( 'tooltip-mode', false ); |
| 1202 | + } |
| 1203 | + }) |
| 1204 | + .bind( 'change', function() { |
| 1205 | + if ( $j( this ).val() != $j( this ).data( 'tooltip' ) ) { |
| 1206 | + $j( this ) |
| 1207 | + .removeClass( 'wikieditor-toolbar-dialog-hint' ) |
| 1208 | + .data( 'tooltip-mode', false ); |
| 1209 | + } |
| 1210 | + }) |
| 1211 | + .bind( 'blur', function() { |
| 1212 | + if ( $j( this ).val() == '' ) { |
| 1213 | + $j( this ) |
| 1214 | + .addClass( 'wikieditor-toolbar-dialog-hint' ) |
| 1215 | + .val( $j( this ).data( 'tooltip' ) ) |
| 1216 | + .data( 'tooltip-mode', true ); |
| 1217 | + } |
| 1218 | + }); |
| 1219 | + |
| 1220 | + // Automatically copy the value of the internal link page title field to the link text field unless the user |
| 1221 | + // has changed the link text field - this is a convenience thing since most link texts are going to be the |
| 1222 | + // the same as the page title |
| 1223 | + // Also change the internal/external radio button accordingly |
| 1224 | + $j( '#wikieditor-toolbar-link-int-target' ).bind( 'change keydown paste cut', function() { |
| 1225 | + // $j(this).val() is the old value, before the keypress |
| 1226 | + // Defer this until $j(this).val() has been updated |
| 1227 | + setTimeout( function() { |
| 1228 | + if ( isExternalLink( $j( '#wikieditor-toolbar-link-int-target' ).val() ) ) { |
| 1229 | + $j( '#wikieditor-toolbar-link-type-ext' ).attr( 'checked', 'checked' ); |
| 1230 | + updateWidget( 'external' ); |
| 1231 | + } else { |
| 1232 | + $j( '#wikieditor-toolbar-link-type-int' ).attr( 'checked', 'checked' ); |
| 1233 | + updateExistence(); |
| 1234 | + } |
| 1235 | + if ( $j( '#wikieditor-toolbar-link-int-text' ).data( 'untouched' ) ) |
| 1236 | + if ( $j( '#wikieditor-toolbar-link-int-target' ).val() == |
| 1237 | + $j( '#wikieditor-toolbar-link-int-target' ).data( 'tooltip' ) ) { |
| 1238 | + $j( '#wikieditor-toolbar-link-int-text' ) |
| 1239 | + .addClass( 'wikieditor-toolbar-dialog-hint' ) |
| 1240 | + .val( $j( '#wikieditor-toolbar-link-int-text' ).data( 'tooltip' ) ) |
| 1241 | + .change(); |
| 1242 | + } else { |
| 1243 | + $j( '#wikieditor-toolbar-link-int-text' ) |
| 1244 | + .val( $j( '#wikieditor-toolbar-link-int-target' ).val() ) |
| 1245 | + .change(); |
| 1246 | + } |
| 1247 | + }, 0 ); |
| 1248 | + }); |
| 1249 | + $j( '#wikieditor-toolbar-link-int-text' ).bind( 'change keydown paste cut', function() { |
| 1250 | + var oldVal = $j(this).val(); |
| 1251 | + var that = this; |
| 1252 | + setTimeout( function() { |
| 1253 | + if ( $j(that).val() != oldVal ) |
| 1254 | + $j(that).data( 'untouched', false ); |
| 1255 | + }, 0 ); |
| 1256 | + }); |
| 1257 | + // Add images to the page existence widget, which will be shown mutually exclusively to communicate if the |
| 1258 | + // page exists, does not exist or the title is invalid (like if it contains a | character) |
| 1259 | + var existsMsg = u.getMsg( 'wikieditor-toolbar-tool-link-int-target-status-exists' ); |
| 1260 | + var notexistsMsg = u.getMsg( 'wikieditor-toolbar-tool-link-int-target-status-notexists' ); |
| 1261 | + var invalidMsg = u.getMsg( 'wikieditor-toolbar-tool-link-int-target-status-invalid' ); |
| 1262 | + var externalMsg = u.getMsg( 'wikieditor-toolbar-tool-link-int-target-status-external' ); |
| 1263 | + var loadingMsg = u.getMsg( 'wikieditor-toolbar-tool-link-int-target-status-loading' ); |
| 1264 | + $j( '#wikieditor-toolbar-link-int-target-status' ) |
| 1265 | + .append( $j( '<div />' ) |
| 1266 | + .attr( 'id', 'wikieditor-toolbar-link-int-target-status-exists' ) |
| 1267 | + .append( existsMsg ) |
| 1268 | + ) |
| 1269 | + .append( $j( '<div />' ) |
| 1270 | + .attr( 'id', 'wikieditor-toolbar-link-int-target-status-notexists' ) |
| 1271 | + .append( notexistsMsg ) |
| 1272 | + ) |
| 1273 | + .append( $j( '<div />' ) |
| 1274 | + .attr( 'id', 'wikieditor-toolbar-link-int-target-status-invalid' ) |
| 1275 | + .append( invalidMsg ) |
| 1276 | + ) |
| 1277 | + .append( $j( '<div />' ) |
| 1278 | + .attr( 'id', 'wikieditor-toolbar-link-int-target-status-external' ) |
| 1279 | + .append( externalMsg ) |
| 1280 | + ) |
| 1281 | + .append( $j( '<div />' ) |
| 1282 | + .attr( 'id', 'wikieditor-toolbar-link-int-target-status-loading' ) |
| 1283 | + .append( $j( '<img />' ).attr( { |
| 1284 | + 'src': $j.wikiEditor.imgPath + 'dialogs/' + 'loading.gif', |
| 1285 | + 'alt': loadingMsg, |
| 1286 | + 'title': loadingMsg |
| 1287 | + } ) ) |
| 1288 | + ) |
| 1289 | + .data( 'existencecache', {} ) |
| 1290 | + .children().hide(); |
| 1291 | + |
| 1292 | + $j( '#wikieditor-toolbar-link-int-target' ) |
| 1293 | + .bind( 'keyup paste cut', function() { |
| 1294 | + // Cancel the running timer if applicable |
| 1295 | + if ( typeof $j(this).data( 'timerID' ) != 'undefined' ) { |
| 1296 | + clearTimeout( $j(this).data( 'timerID' ) ); |
| 1297 | + } |
| 1298 | + // Delay fetch for a while |
| 1299 | + // FIXME: Make 120 configurable elsewhere |
| 1300 | + var timerID = setTimeout( updateExistence, 120 ); |
| 1301 | + $j(this).data( 'timerID', timerID ); |
| 1302 | + } ) |
| 1303 | + .change( function() { |
| 1304 | + // Cancel the running timer if applicable |
| 1305 | + if ( typeof $j(this).data( 'timerID' ) != 'undefined' ) { |
| 1306 | + clearTimeout( $j(this).data( 'timerID' ) ); |
| 1307 | + } |
| 1308 | + // Fetch right now |
| 1309 | + updateExistence(); |
| 1310 | + } ); |
| 1311 | + |
| 1312 | + // Title suggestions |
| 1313 | + $j( '#wikieditor-toolbar-link-int-target' ).data( 'suggcache', {} ).suggestions( { |
| 1314 | + fetch: function( query ) { |
| 1315 | + var that = this; |
| 1316 | + var title = $j(this).val(); |
| 1317 | + |
| 1318 | + if ( isExternalLink( title ) || title.indexOf( '|' ) != -1 || title == '') { |
| 1319 | + $j(this).suggestions( 'suggestions', [] ); |
| 1320 | + return; |
| 1321 | + } |
| 1322 | + |
| 1323 | + var cache = $j(this).data( 'suggcache' ); |
| 1324 | + if ( typeof cache[title] != 'undefined' ) { |
| 1325 | + $j(this).suggestions( 'suggestions', cache[title] ); |
| 1326 | + return; |
| 1327 | + } |
| 1328 | + |
| 1329 | + var request = $j.ajax( { |
| 1330 | + url: wgScriptPath + '/api.php', |
| 1331 | + data: { |
| 1332 | + 'action': 'opensearch', |
| 1333 | + 'search': title, |
| 1334 | + 'namespace': 0, |
| 1335 | + 'suggest': '', |
| 1336 | + 'format': 'json' |
| 1337 | + }, |
| 1338 | + dataType: 'json', |
| 1339 | + success: function( data ) { |
| 1340 | + cache[title] = data[1]; |
| 1341 | + $j(that).suggestions( 'suggestions', data[1] ); |
| 1342 | + } |
| 1343 | + }); |
| 1344 | + $j(this).data( 'request', request ); |
| 1345 | + }, |
| 1346 | + cancel: function() { |
| 1347 | + var request = $j(this).data( 'request' ); |
| 1348 | + if ( request ) |
| 1349 | + request.abort(); |
| 1350 | + } |
| 1351 | + }); |
| 1352 | + }, |
| 1353 | + dialog: { |
| 1354 | + width: 500, |
| 1355 | + dialogClass: 'wikiEditor-toolbar-dialog', |
| 1356 | + buttons: { |
| 1357 | + 'wikieditor-toolbar-tool-link-insert': function() { |
| 1358 | + function escapeInternalText( s ) { |
| 1359 | + // FIXME: Should this escape [[ too? Seems to work without that |
| 1360 | + return s.replace( /(]{2,})/g, '<nowiki>$1</nowiki>' ); |
| 1361 | + } |
| 1362 | + function escapeExternalTarget( s ) { |
| 1363 | + return s.replace( / /g, '%20' ) |
| 1364 | + .replace( /\[/g, '%5B' ) |
| 1365 | + .replace( /]/g, '%5D' ); |
| 1366 | + } |
| 1367 | + function escapeExternalText( s ) { |
| 1368 | + // FIXME: Should this escape [ too? Seems to work without that |
| 1369 | + return s.replace( /(]+)/g, '<nowiki>$1</nowiki>' ); |
| 1370 | + } |
| 1371 | + var insertText = ''; |
| 1372 | + var whitespace = $j( '#wikieditor-toolbar-link-dialog' ).data( 'whitespace' ); |
| 1373 | + var target = $j( '#wikieditor-toolbar-link-int-target' ).val(); |
| 1374 | + var text = $j( '#wikieditor-toolbar-link-int-text' ).val(); |
| 1375 | + // check if the tooltips were passed as target or text |
| 1376 | + if ( $j( '#wikieditor-toolbar-link-int-target' ).data( 'tooltip-mode' ) ) |
| 1377 | + target = ""; |
| 1378 | + if ( $j( '#wikieditor-toolbar-link-int-text' ).data( 'tooltip-mode' ) ) |
| 1379 | + text = ""; |
| 1380 | + var u = mw.usability; |
| 1381 | + if ( target == '' ) { |
| 1382 | + alert( u.getMsg( 'wikieditor-toolbar-tool-link-empty' ) ); |
| 1383 | + return; |
| 1384 | + } |
| 1385 | + if ( $j.trim( text ) == '' ) { |
| 1386 | + // [[Foo| ]] creates an invisible link |
| 1387 | + // Instead, generate [[Foo|]] |
| 1388 | + text = ''; |
| 1389 | + } |
| 1390 | + if ( $j( '#wikieditor-toolbar-link-type-int' ).is( ':checked' ) ) { |
| 1391 | + // FIXME: Exactly how fragile is this? |
| 1392 | + if ( $j( '#wikieditor-toolbar-link-int-target-status-invalid' ).is( ':visible' ) ) { |
| 1393 | + // Refuse to add links to invalid titles |
| 1394 | + alert( u.getMsg( 'wikieditor-toolbar-tool-link-int-invalid' ) ); |
| 1395 | + return; |
| 1396 | + } |
| 1397 | + |
| 1398 | + if ( target == text || !text.length ) |
| 1399 | + insertText = '[[' + target + ']]'; |
| 1400 | + else |
| 1401 | + insertText = '[[' + target + '|' + escapeInternalText( text ) + ']]'; |
| 1402 | + } else { |
| 1403 | + // Prepend http:// if there is no protocol |
| 1404 | + if ( !target.match( /^[a-z]+:\/\/./ ) ) |
| 1405 | + target = 'http://' + target; |
| 1406 | + |
| 1407 | + // Detect if this is really an internal link in disguise |
| 1408 | + var match = target.match( $j(this).data( 'articlePathRegex' ) ); |
| 1409 | + if ( match && !$j(this).data( 'ignoreLooksInternal' ) ) { |
| 1410 | + var buttons = { }; |
| 1411 | + var that = this; |
| 1412 | + buttons[ u.getMsg( 'wikieditor-toolbar-tool-link-lookslikeinternal-int' ) ] = function() { |
| 1413 | + $j( '#wikieditor-toolbar-link-int-target' ).val( match[1] ).change(); |
| 1414 | + $j(this).dialog( 'close' ); |
| 1415 | + }; |
| 1416 | + buttons[ u.getMsg( 'wikieditor-toolbar-tool-link-lookslikeinternal-ext' ) ] = function() { |
| 1417 | + $j(that).data( 'ignoreLooksInternal', true ); |
| 1418 | + $j(that).closest( '.ui-dialog' ).find( 'button:first' ).click(); |
| 1419 | + $j(that).data( 'ignoreLooksInternal', false ); |
| 1420 | + $j(this).dialog( 'close' ); |
| 1421 | + }; |
| 1422 | + $j.wikiEditor.modules.dialogs.quickDialog( |
| 1423 | + u.getMsg( 'wikieditor-toolbar-tool-link-lookslikeinternal', match[1] ), |
| 1424 | + { buttons: buttons } |
| 1425 | + ); |
| 1426 | + return; |
| 1427 | + } |
| 1428 | + |
| 1429 | + var escTarget = escapeExternalTarget( target ); |
| 1430 | + var escText = escapeExternalText( text ); |
| 1431 | + |
| 1432 | + if ( escTarget == escText ) |
| 1433 | + insertText = escTarget; |
| 1434 | + else if ( text == '' ) |
| 1435 | + insertText = '[' + escTarget + ']'; |
| 1436 | + else |
| 1437 | + insertText = '[' + escTarget + ' ' + escText + ']'; |
| 1438 | + } |
| 1439 | + // Preserve whitespace in selection when replacing |
| 1440 | + if ( whitespace ) insertText = whitespace[0] + insertText + whitespace[1]; |
| 1441 | + $j(this).dialog( 'close' ); |
| 1442 | + $j.wikiEditor.modules.toolbar.fn.doAction( $j(this).data( 'context' ), { |
| 1443 | + type: 'replace', |
| 1444 | + options: { |
| 1445 | + pre: insertText |
| 1446 | + } |
| 1447 | + }, $j(this) ); |
| 1448 | + |
| 1449 | + // Blank form |
| 1450 | + $j( '#wikieditor-toolbar-link-int-target, #wikieditor-toolbar-link-int-text' ).val( '' ); |
| 1451 | + $j( '#wikieditor-toolbar-link-type-int, #wikieditor-toolbar-link-type-ext' ).attr( 'checked', '' ); |
| 1452 | + }, |
| 1453 | + 'wikieditor-toolbar-tool-link-cancel': function() { |
| 1454 | + // Clear any saved selection state |
| 1455 | + var context = $j(this).data( 'context' ); |
| 1456 | + context.fn.restoreStuffForIE(); |
| 1457 | + $j(this).dialog( 'close' ); |
| 1458 | + } |
| 1459 | + }, |
| 1460 | + open: function() { |
| 1461 | + // Cache the articlepath regex |
| 1462 | + $j(this).data( 'articlePathRegex', new RegExp( |
| 1463 | + '^' + RegExp.escape( wgServer + wgArticlePath ) |
| 1464 | + .replace( /\\\$1/g, '(.*)' ) + '$' |
| 1465 | + ) ); |
| 1466 | + // Pre-fill the text fields based on the current selection |
| 1467 | + var context = $j(this).data( 'context' ); |
| 1468 | + // Restore and immediately save selection state, needed for inserting stuff later |
| 1469 | + context.fn.restoreStuffForIE(); |
| 1470 | + context.fn.saveStuffForIE(); |
| 1471 | + var selection = context.$textarea.textSelection( 'getSelection' ); |
| 1472 | + $j( '#wikieditor-toolbar-link-int-target' ).focus(); |
| 1473 | + // Trigger the change event, so the link status indicator is up to date |
| 1474 | + $j( '#wikieditor-toolbar-link-int-target' ).change(); |
| 1475 | + $j( '#wikieditor-toolbar-link-dialog' ).data( 'whitespace', [ '', '' ] ); |
| 1476 | + if ( selection != '' ) { |
| 1477 | + var target, text, type; |
| 1478 | + var matches; |
| 1479 | + if ( ( matches = selection.match( /^(\s*)\[\[([^\]\|]+)(\|([^\]\|]*))?\]\](\s*)$/ ) ) ) { |
| 1480 | + // [[foo|bar]] or [[foo]] |
| 1481 | + target = matches[2]; |
| 1482 | + text = ( matches[4] ? matches[4] : matches[2] ); |
| 1483 | + type = 'int'; |
| 1484 | + // Preserve whitespace when replacing |
| 1485 | + $j( '#wikieditor-toolbar-link-dialog' ).data( 'whitespace', [ matches[1], matches[5] ] ); |
| 1486 | + } else if ( ( matches = selection.match( /^(\s*)\[([^\] ]+)( ([^\]]+))?\](\s*)$/ ) ) ) { |
| 1487 | + // [http://www.example.com foo] or [http://www.example.com] |
| 1488 | + target = matches[2]; |
| 1489 | + text = ( matches[4] ? matches[4] : '' ); |
| 1490 | + type = 'ext'; |
| 1491 | + // Preserve whitespace when replacing |
| 1492 | + $j( '#wikieditor-toolbar-link-dialog' ).data( 'whitespace', [ matches[1], matches[5] ] ); |
| 1493 | + } else { |
| 1494 | + // Trim any leading and trailing whitespace from the selection, |
| 1495 | + // but preserve it when replacing |
| 1496 | + target = text = $j.trim( selection ); |
| 1497 | + if ( target.length < selection.length ) { |
| 1498 | + $j( '#wikieditor-toolbar-link-dialog' ).data( 'whitespace', [ |
| 1499 | + selection.substr( 0, selection.indexOf( target.charAt( 0 ) ) ), |
| 1500 | + selection.substr( |
| 1501 | + selection.lastIndexOf( target.charAt( target.length - 1 ) ) + 1 |
| 1502 | + ) ] |
| 1503 | + ); |
| 1504 | + } |
| 1505 | + } |
| 1506 | + |
| 1507 | + // Change the value by calling val() doesn't trigger the change event, so let's do that ourselves |
| 1508 | + if ( typeof text != 'undefined' ) |
| 1509 | + $j( '#wikieditor-toolbar-link-int-text' ).val( text ).change(); |
| 1510 | + if ( typeof target != 'undefined' ) |
| 1511 | + $j( '#wikieditor-toolbar-link-int-target' ).val( target ).change(); |
| 1512 | + if ( typeof type != 'undefined' ) |
| 1513 | + $j( '#wikieditor-toolbar-link-' + type ).attr( 'checked', 'checked' ); |
| 1514 | + } |
| 1515 | + $j( '#wikieditor-toolbar-link-int-text' ).data( 'untouched', |
| 1516 | + $j( '#wikieditor-toolbar-link-int-text' ).val() == |
| 1517 | + $j( '#wikieditor-toolbar-link-int-target' ).val() || |
| 1518 | + $j( '#wikieditor-toolbar-link-int-text' ).hasClass( 'wikieditor-toolbar-dialog-hint' ) |
| 1519 | + ); |
| 1520 | + $j( '#wikieditor-toolbar-link-int-target' ).suggestions(); |
| 1521 | + |
| 1522 | + //don't overwrite user's text |
| 1523 | + if( selection != '' ){ |
| 1524 | + $j( '#wikieditor-toolbar-link-int-text' ).data( 'untouched', false ); |
| 1525 | + } |
| 1526 | + |
| 1527 | + $j( '#wikieditor-toolbar-link-int-text, #wikiedit-toolbar-link-int-target' ) |
| 1528 | + .each( function() { |
| 1529 | + if ( $j(this).val() == '' ) |
| 1530 | + $j(this).parent().find( 'label' ).show(); |
| 1531 | + }); |
| 1532 | + |
| 1533 | + if ( !( $j(this).data( 'dialogkeypressset' ) ) ) { |
| 1534 | + $j(this).data( 'dialogkeypressset', true ); |
| 1535 | + // Execute the action associated with the first button |
| 1536 | + // when the user presses Enter |
| 1537 | + $j(this).closest( '.ui-dialog' ).keypress( function( e ) { |
| 1538 | + if ( ( e.keyCode || e.which ) == 13 ) { |
| 1539 | + var button = $j(this).data( 'dialogaction' ) || $j(this).find( 'button:first' ); |
| 1540 | + button.click(); |
| 1541 | + e.preventDefault(); |
| 1542 | + } |
| 1543 | + }); |
| 1544 | + |
| 1545 | + // Make tabbing to a button and pressing |
| 1546 | + // Enter do what people expect |
| 1547 | + $j(this).closest( '.ui-dialog' ).find( 'button' ).focus( function() { |
| 1548 | + $j(this).closest( '.ui-dialog' ).data( 'dialogaction', this ); |
| 1549 | + }); |
| 1550 | + } |
| 1551 | + } |
| 1552 | + } |
| 1553 | + }, |
| 1554 | + 'insert-reference': { |
| 1555 | + filters: [ '#wpTextbox1.toolbar-dialogs' ], |
| 1556 | + titleMsg: 'wikieditor-toolbar-tool-reference-title', |
| 1557 | + id: 'wikieditor-toolbar-reference-dialog', |
| 1558 | + html: '\ |
| 1559 | + <div class="wikieditor-toolbar-dialog-wrapper">\ |
| 1560 | + <fieldset><div class="wikieditor-toolbar-table-form">\ |
| 1561 | + <div class="wikieditor-toolbar-field-wrapper">\ |
| 1562 | + <label for="wikieditor-toolbar-reference-text"\ |
| 1563 | + rel="wikieditor-toolbar-tool-reference-text"></label>\ |
| 1564 | + <input type="text" id="wikieditor-toolbar-reference-text" />\ |
| 1565 | + </div>\ |
| 1566 | + </div></fieldset>\ |
| 1567 | + </div>', |
| 1568 | + init: function() { |
| 1569 | + // Insert translated strings into labels |
| 1570 | + $j( this ).find( '[rel]' ).each( function() { |
| 1571 | + $j( this ).text( mw.usability.getMsg( $j( this ).attr( 'rel' ) ) ); |
| 1572 | + } ); |
| 1573 | + |
| 1574 | + }, |
| 1575 | + dialog: { |
| 1576 | + dialogClass: 'wikiEditor-toolbar-dialog', |
| 1577 | + width: 590, |
| 1578 | + buttons: { |
| 1579 | + 'wikieditor-toolbar-tool-reference-insert': function() { |
| 1580 | + var insertText = $j( '#wikieditor-toolbar-reference-text' ).val(); |
| 1581 | + var whitespace = $j( '#wikieditor-toolbar-reference-dialog' ).data( 'whitespace' ); |
| 1582 | + var attributes = $j( '#wikieditor-toolbar-reference-dialog' ).data( 'attributes' ); |
| 1583 | + // Close the dialog |
| 1584 | + $j( this ).dialog( 'close' ); |
| 1585 | + $j.wikiEditor.modules.toolbar.fn.doAction( |
| 1586 | + $j( this ).data( 'context' ), |
| 1587 | + { |
| 1588 | + type: 'replace', |
| 1589 | + options: { |
| 1590 | + pre: whitespace[0] + '<ref' + attributes + '>', |
| 1591 | + peri: insertText, |
| 1592 | + post: '</ref>' + whitespace[1] |
| 1593 | + } |
| 1594 | + }, |
| 1595 | + $j( this ) |
| 1596 | + ); |
| 1597 | + // Restore form state |
| 1598 | + $j( '#wikieditor-toolbar-reference-text' ).val( "" ); |
| 1599 | + }, |
| 1600 | + 'wikieditor-toolbar-tool-reference-cancel': function() { |
| 1601 | + // Clear any saved selection state |
| 1602 | + var context = $j( this ).data( 'context' ); |
| 1603 | + context.fn.restoreStuffForIE(); |
| 1604 | + $j( this ).dialog( 'close' ); |
| 1605 | + } |
| 1606 | + }, |
| 1607 | + open: function() { |
| 1608 | + // Pre-fill the text fields based on the current selection |
| 1609 | + var context = $j(this).data( 'context' ); |
| 1610 | + // Restore and immediately save selection state, needed for inserting stuff later |
| 1611 | + context.fn.restoreStuffForIE(); |
| 1612 | + context.fn.saveStuffForIE(); |
| 1613 | + var selection = context.$textarea.textSelection( 'getSelection' ); |
| 1614 | + // set focus |
| 1615 | + $j( '#wikieditor-toolbar-reference-text' ).focus(); |
| 1616 | + $j( '#wikieditor-toolbar-reference-dialog' ) |
| 1617 | + .data( 'whitespace', [ '', '' ] ) |
| 1618 | + .data( 'attributes', '' ); |
| 1619 | + if ( selection != '' ) { |
| 1620 | + var matches, text; |
| 1621 | + if ( ( matches = selection.match( /^(\s*)<ref([^\>]*)>([^\<]*)<\/ref\>(\s*)$/ ) ) ) { |
| 1622 | + text = matches[3]; |
| 1623 | + // Preserve whitespace when replacing |
| 1624 | + $j( '#wikieditor-toolbar-reference-dialog' ).data( 'whitespace', [ matches[1], matches[4] ] ); |
| 1625 | + $j( '#wikieditor-toolbar-reference-dialog' ).data( 'attributes', matches[2] ); |
| 1626 | + } else { |
| 1627 | + text = selection; |
| 1628 | + } |
| 1629 | + $j( '#wikieditor-toolbar-reference-text' ).val( text ); |
| 1630 | + } |
| 1631 | + if ( !( $j( this ).data( 'dialogkeypressset' ) ) ) { |
| 1632 | + $j( this ).data( 'dialogkeypressset', true ); |
| 1633 | + // Execute the action associated with the first button |
| 1634 | + // when the user presses Enter |
| 1635 | + $j( this ).closest( '.ui-dialog' ).keypress( function( e ) { |
| 1636 | + if ( ( e.keyCode || e.which ) == 13 ) { |
| 1637 | + var button = $j( this ).data( 'dialogaction' ) || $j( this ).find( 'button:first' ); |
| 1638 | + button.click(); |
| 1639 | + e.preventDefault(); |
| 1640 | + } |
| 1641 | + } ); |
| 1642 | + // Make tabbing to a button and pressing |
| 1643 | + // Enter do what people expect |
| 1644 | + $j( this ).closest( '.ui-dialog' ).find( 'button' ).focus( function() { |
| 1645 | + $j( this ).closest( '.ui-dialog' ).data( 'dialogaction', this ); |
| 1646 | + } ); |
| 1647 | + } |
| 1648 | + } |
| 1649 | + } |
| 1650 | + }, |
| 1651 | + 'insert-table': { |
| 1652 | + // For now, apply the old browser and iframe requirements to the link and table dialogs as well |
| 1653 | + // This'll be removed once these dialogs are confirmed stable without the iframe and/or in more browsers |
| 1654 | + /* |
| 1655 | + 'browsers': { |
| 1656 | + // Left-to-right languages |
| 1657 | + 'ltr': { |
| 1658 | + 'msie': [['>=', 7]], |
| 1659 | + 'firefox': [['>=', 3]], |
| 1660 | + 'opera': [['>=', 10]], |
| 1661 | + 'safari': [['>=', 4]], |
| 1662 | + 'chrome': [['>=', 4]] |
| 1663 | + }, |
| 1664 | + // Right-to-left languages |
| 1665 | + 'rtl': { |
| 1666 | + 'msie': [['>=', 8]], |
| 1667 | + 'firefox': [['>=', 3]], |
| 1668 | + 'opera': [['>=', 10]], |
| 1669 | + 'safari': [['>=', 4]], |
| 1670 | + 'chrome': [['>=', 4]] |
| 1671 | + } |
| 1672 | + }, |
| 1673 | + 'req': [ 'iframe' ], |
| 1674 | + */ |
| 1675 | + filters: [ '#wpTextbox1.toolbar-dialogs' ], |
| 1676 | + titleMsg: 'wikieditor-toolbar-tool-table-title', |
| 1677 | + id: 'wikieditor-toolbar-table-dialog', |
| 1678 | + // FIXME: Localize 'x'? |
| 1679 | + html: '\ |
| 1680 | + <div class="wikieditor-toolbar-dialog-wrapper">\ |
| 1681 | + <fieldset><div class="wikieditor-toolbar-table-form">\ |
| 1682 | + <div class="wikieditor-toolbar-field-wrapper">\ |
| 1683 | + <input type="checkbox" id="wikieditor-toolbar-table-dimensions-header" checked />\ |
| 1684 | + <label for="wikieditor-toolbar-table-dimensions-header"\ |
| 1685 | + rel="wikieditor-toolbar-tool-table-dimensions-header"></label>\ |
| 1686 | + </div>\ |
| 1687 | + <div class="wikieditor-toolbar-field-wrapper">\ |
| 1688 | + <input type="checkbox" id="wikieditor-toolbar-table-wikitable" checked />\ |
| 1689 | + <label for="wikieditor-toolbar-table-wikitable" rel="wikieditor-toolbar-tool-table-wikitable"></label>\ |
| 1690 | + </div>\ |
| 1691 | + <div class="wikieditor-toolbar-field-wrapper">\ |
| 1692 | + <input type="checkbox" id="wikieditor-toolbar-table-sortable" />\ |
| 1693 | + <label for="wikieditor-toolbar-table-sortable" rel="wikieditor-toolbar-tool-table-sortable"></label>\ |
| 1694 | + </div>\ |
| 1695 | + <div class="wikieditor-toolbar-table-dimension-fields">\ |
| 1696 | + <div class="wikieditor-toolbar-field-wrapper">\ |
| 1697 | + <label for="wikieditor-toolbar-table-dimensions-rows"\ |
| 1698 | + rel="wikieditor-toolbar-tool-table-dimensions-rows"></label><br />\ |
| 1699 | + <input type="text" id="wikieditor-toolbar-table-dimensions-rows" size="4" />\ |
| 1700 | + </div>\ |
| 1701 | + <div class="wikieditor-toolbar-field-wrapper">\ |
| 1702 | + <label for="wikieditor-toolbar-table-dimensions-columns"\ |
| 1703 | + rel="wikieditor-toolbar-tool-table-dimensions-columns"></label><br />\ |
| 1704 | + <input type="text" id="wikieditor-toolbar-table-dimensions-columns" size="4" />\ |
| 1705 | + </div>\ |
| 1706 | + </div>\ |
| 1707 | + </div></fieldset>\ |
| 1708 | + <div class="wikieditor-toolbar-table-preview-wrapper" >\ |
| 1709 | + <span rel="wikieditor-toolbar-tool-table-example"></span>\ |
| 1710 | + <div class="wikieditor-toolbar-table-preview-content">\ |
| 1711 | + <table id="wikieditor-toolbar-table-preview" class="wikieditor-toolbar-table-preview wikitable">\ |
| 1712 | + <tr class="wikieditor-toolbar-table-preview-header">\ |
| 1713 | + <th rel="wikieditor-toolbar-tool-table-example-header"></th>\ |
| 1714 | + <th rel="wikieditor-toolbar-tool-table-example-header"></th>\ |
| 1715 | + <th rel="wikieditor-toolbar-tool-table-example-header"></th>\ |
| 1716 | + </tr><tr class="wikieditor-toolbar-table-preview-hidden" style="display: none;">\ |
| 1717 | + <td rel="wikieditor-toolbar-tool-table-example-cell-text"></td>\ |
| 1718 | + <td rel="wikieditor-toolbar-tool-table-example-cell-text"></td>\ |
| 1719 | + <td rel="wikieditor-toolbar-tool-table-example-cell-text"></td>\ |
| 1720 | + </tr><tr>\ |
| 1721 | + <td rel="wikieditor-toolbar-tool-table-example-cell-text"></td>\ |
| 1722 | + <td rel="wikieditor-toolbar-tool-table-example-cell-text"></td>\ |
| 1723 | + <td rel="wikieditor-toolbar-tool-table-example-cell-text"></td>\ |
| 1724 | + </tr><tr>\ |
| 1725 | + <td rel="wikieditor-toolbar-tool-table-example-cell-text"></td>\ |
| 1726 | + <td rel="wikieditor-toolbar-tool-table-example-cell-text"></td>\ |
| 1727 | + <td rel="wikieditor-toolbar-tool-table-example-cell-text"></td>\ |
| 1728 | + </tr><tr>\ |
| 1729 | + <td rel="wikieditor-toolbar-tool-table-example-cell-text"></td>\ |
| 1730 | + <td rel="wikieditor-toolbar-tool-table-example-cell-text"></td>\ |
| 1731 | + <td rel="wikieditor-toolbar-tool-table-example-cell-text"></td>\ |
| 1732 | + </tr>\ |
| 1733 | + </table>\ |
| 1734 | + </div>\ |
| 1735 | + </div></div>', |
| 1736 | + init: function() { |
| 1737 | + $j(this).find( '[rel]' ).each( function() { |
| 1738 | + $j(this).text( mw.usability.getMsg( $j(this).attr( 'rel' ) ) ); |
| 1739 | + }); |
| 1740 | + // Set tabindexes on form fields |
| 1741 | + $j.wikiEditor.modules.dialogs.fn.setTabindexes( $j(this).find( 'input' ).not( '[tabindex]' ) ); |
| 1742 | + |
| 1743 | + $j( '#wikieditor-toolbar-table-dimensions-rows' ).val( 3 ); |
| 1744 | + $j( '#wikieditor-toolbar-table-dimensions-columns' ).val( 3 ); |
| 1745 | + $j( '#wikieditor-toolbar-table-wikitable' ).click( function() { |
| 1746 | + $j( '.wikieditor-toolbar-table-preview' ).toggleClass( 'wikitable' ); |
| 1747 | + }); |
| 1748 | + |
| 1749 | + // Hack for sortable preview: dynamically adding |
| 1750 | + // sortable class doesn't work, so we use a clone |
| 1751 | + // FIXME: Relies on sortable table internals |
| 1752 | + $j( '#wikieditor-toolbar-table-preview' ) |
| 1753 | + .clone() |
| 1754 | + .attr( 'id', 'wikieditor-toolbar-table-preview2' ) |
| 1755 | + .addClass( 'sortable' ) |
| 1756 | + .insertAfter( $j( '#wikieditor-toolbar-table-preview' ) ) |
| 1757 | + .hide(); |
| 1758 | + if ( typeof ts_makeSortable == 'function' ) |
| 1759 | + ts_makeSortable( $j( '#wikieditor-toolbar-table-preview2' ).get( 0 ) ); |
| 1760 | + $j( '#wikieditor-toolbar-table-sortable' ).click( function() { |
| 1761 | + // Swap the currently shown one clone with the other one |
| 1762 | + $j( '#wikieditor-toolbar-table-preview' ) |
| 1763 | + .hide() |
| 1764 | + .attr( 'id', 'wikieditor-toolbar-table-preview3' ); |
| 1765 | + $j( '#wikieditor-toolbar-table-preview2' ) |
| 1766 | + .attr( 'id', 'wikieditor-toolbar-table-preview' ) |
| 1767 | + .show(); |
| 1768 | + $j( '#wikieditor-toolbar-table-preview3' ).attr( 'id', 'wikieditor-toolbar-table-preview2' ); |
| 1769 | + }); |
| 1770 | + |
| 1771 | + $j( '#wikieditor-toolbar-table-dimensions-header' ).click( function() { |
| 1772 | + // Instead of show/hiding, switch the HTML around |
| 1773 | + // We do this because the sortable tables script styles the first row, |
| 1774 | + // visible or not |
| 1775 | + var headerHTML = $j( '.wikieditor-toolbar-table-preview-header' ).html(); |
| 1776 | + var hiddenHTML = $j( '.wikieditor-toolbar-table-preview-hidden' ).html(); |
| 1777 | + $j( '.wikieditor-toolbar-table-preview-header' ).html( hiddenHTML ); |
| 1778 | + $j( '.wikieditor-toolbar-table-preview-hidden' ).html( headerHTML ); |
| 1779 | + if ( typeof ts_makeSortable == 'function' ) |
| 1780 | + ts_makeSortable( |
| 1781 | + $j( '#wikieditor-toolbar-table-preview, #wikieditor-toolbar-table-preview2' ) |
| 1782 | + .filter( '.sortable' ) |
| 1783 | + .get( 0 ) |
| 1784 | + ); |
| 1785 | + }); |
| 1786 | + |
| 1787 | + }, |
| 1788 | + dialog: { |
| 1789 | + resizable: false, |
| 1790 | + dialogClass: 'wikiEditor-toolbar-dialog', |
| 1791 | + width: 590, |
| 1792 | + buttons: { |
| 1793 | + 'wikieditor-toolbar-tool-table-insert': function() { |
| 1794 | + var rowsVal = $j( '#wikieditor-toolbar-table-dimensions-rows' ).val(); |
| 1795 | + var colsVal = $j( '#wikieditor-toolbar-table-dimensions-columns' ).val(); |
| 1796 | + var rows = parseInt( rowsVal, 10 ); |
| 1797 | + var cols = parseInt( colsVal, 10 ); |
| 1798 | + var header = $j( '#wikieditor-toolbar-table-dimensions-header' ).is( ':checked' ) ? 1 : 0; |
| 1799 | + var u = mw.usability; |
| 1800 | + if ( isNaN( rows ) || isNaN( cols ) || rows != rowsVal || cols != colsVal ) { |
| 1801 | + alert( u.getMsg( 'wikieditor-toolbar-tool-table-invalidnumber' ) ); |
| 1802 | + return; |
| 1803 | + } |
| 1804 | + if ( rows + header == 0 || cols == 0 ) { |
| 1805 | + alert( u.getMsg( 'wikieditor-toolbar-tool-table-zero' ) ); |
| 1806 | + return; |
| 1807 | + } |
| 1808 | + if ( rows * cols > 1000 ) { |
| 1809 | + alert( u.getMsg( 'wikieditor-toolbar-tool-table-toomany', 1000 ) ); |
| 1810 | + return; |
| 1811 | + } |
| 1812 | + var headerText = u.getMsg( 'wikieditor-toolbar-tool-table-example-header' ); |
| 1813 | + var normalText = u.getMsg( 'wikieditor-toolbar-tool-table-example' ); |
| 1814 | + var table = ""; |
| 1815 | + for ( var r = 0; r < rows + header; r++ ) { |
| 1816 | + table += "|-\n"; |
| 1817 | + for ( var c = 0; c < cols; c++ ) { |
| 1818 | + var isHeader = ( header && r == 0 ); |
| 1819 | + var delim = isHeader ? '!' : '|'; |
| 1820 | + if ( c > 0 ) { |
| 1821 | + delim += delim; |
| 1822 | + } |
| 1823 | + table += delim + ' ' + ( isHeader ? headerText : normalText ) + ' '; |
| 1824 | + } |
| 1825 | + // Replace trailing space by newline |
| 1826 | + // table[table.length - 1] is read-only |
| 1827 | + table = table.substr( 0, table.length - 1 ) + "\n"; |
| 1828 | + } |
| 1829 | + var classes = []; |
| 1830 | + if ( $j( '#wikieditor-toolbar-table-wikitable' ).is( ':checked' ) ) |
| 1831 | + classes.push( 'wikitable' ); |
| 1832 | + if ( $j( '#wikieditor-toolbar-table-sortable' ).is( ':checked' ) ) |
| 1833 | + classes.push( 'sortable' ); |
| 1834 | + var classStr = classes.length > 0 ? ' class="' + classes.join( ' ' ) + '"' : ''; |
| 1835 | + $j(this).dialog( 'close' ); |
| 1836 | + $j.wikiEditor.modules.toolbar.fn.doAction( |
| 1837 | + $j(this).data( 'context' ), |
| 1838 | + { |
| 1839 | + type: 'replace', |
| 1840 | + options: { |
| 1841 | + pre: '{|' + classStr + "\n", |
| 1842 | + peri: table, |
| 1843 | + post: '|}', |
| 1844 | + ownline: true |
| 1845 | + } |
| 1846 | + }, |
| 1847 | + $j(this) |
| 1848 | + ); |
| 1849 | + |
| 1850 | + // Restore form state |
| 1851 | + $j( '#wikieditor-toolbar-table-dimensions-rows' ).val( 3 ); |
| 1852 | + $j( '#wikieditor-toolbar-table-dimensions-columns' ).val( 3 ); |
| 1853 | + // Simulate clicks instead of setting values, so the according |
| 1854 | + // actions are performed |
| 1855 | + if ( !$j( '#wikieditor-toolbar-table-dimensions-header' ).is( ':checked' ) ) |
| 1856 | + $j( '#wikieditor-toolbar-table-dimensions-header' ).click(); |
| 1857 | + if ( !$j( '#wikieditor-toolbar-table-wikitable' ).is( ':checked' ) ) |
| 1858 | + $j( '#wikieditor-toolbar-table-wikitable' ).click(); |
| 1859 | + if ( $j( '#wikieditor-toolbar-table-sortable' ).is( ':checked' ) ) |
| 1860 | + $j( '#wikieditor-toolbar-table-sortable' ).click(); |
| 1861 | + }, |
| 1862 | + 'wikieditor-toolbar-tool-table-cancel': function() { |
| 1863 | + $j(this).dialog( 'close' ); |
| 1864 | + } |
| 1865 | + }, |
| 1866 | + open: function() { |
| 1867 | + $j( '#wikieditor-toolbar-table-dimensions-rows' ).focus(); |
| 1868 | + if ( !( $j(this).data( 'dialogkeypressset' ) ) ) { |
| 1869 | + $j(this).data( 'dialogkeypressset', true ); |
| 1870 | + // Execute the action associated with the first button |
| 1871 | + // when the user presses Enter |
| 1872 | + $j(this).closest( '.ui-dialog' ).keypress( function( e ) { |
| 1873 | + if ( ( e.keyCode || e.which ) == 13 ) { |
| 1874 | + var button = $j(this).data( 'dialogaction' ) || $j(this).find( 'button:first' ); |
| 1875 | + button.click(); |
| 1876 | + e.preventDefault(); |
| 1877 | + } |
| 1878 | + }); |
| 1879 | + |
| 1880 | + // Make tabbing to a button and pressing |
| 1881 | + // Enter do what people expect |
| 1882 | + $j(this).closest( '.ui-dialog' ).find( 'button' ).focus( function() { |
| 1883 | + $j(this).closest( '.ui-dialog' ).data( 'dialogaction', this ); |
| 1884 | + }); |
| 1885 | + } |
| 1886 | + } |
| 1887 | + } |
| 1888 | + }, |
| 1889 | + 'search-and-replace': { |
| 1890 | + 'browsers': { |
| 1891 | + // Left-to-right languages |
| 1892 | + 'ltr': { |
| 1893 | + 'msie': false, |
| 1894 | + 'firefox': [['>=', 2]], |
| 1895 | + 'opera': false, |
| 1896 | + 'safari': [['>=', 3]], |
| 1897 | + 'chrome': [['>=', 3]] |
| 1898 | + }, |
| 1899 | + // Right-to-left languages |
| 1900 | + 'rtl': { |
| 1901 | + 'msie': false, |
| 1902 | + 'firefox': [['>=', 2]], |
| 1903 | + 'opera': false, |
| 1904 | + 'safari': [['>=', 3]], |
| 1905 | + 'chrome': [['>=', 3]] |
| 1906 | + } |
| 1907 | + }, |
| 1908 | + filters: [ '#wpTextbox1.toolbar-dialogs' ], |
| 1909 | + titleMsg: 'wikieditor-toolbar-tool-replace-title', |
| 1910 | + id: 'wikieditor-toolbar-replace-dialog', |
| 1911 | + html: '\ |
| 1912 | + <div id="wikieditor-toolbar-replace-message">\ |
| 1913 | + <div id="wikieditor-toolbar-replace-nomatch" rel="wikieditor-toolbar-tool-replace-nomatch"></div>\ |
| 1914 | + <div id="wikieditor-toolbar-replace-success"></div>\ |
| 1915 | + <div id="wikieditor-toolbar-replace-emptysearch" rel="wikieditor-toolbar-tool-replace-emptysearch"></div>\ |
| 1916 | + <div id="wikieditor-toolbar-replace-invalidregex"></div>\ |
| 1917 | + </div>\ |
| 1918 | + <fieldset>\ |
| 1919 | + <div class="wikieditor-toolbar-field-wrapper">\ |
| 1920 | + <label for="wikieditor-toolbar-replace-search" rel="wikieditor-toolbar-tool-replace-search"></label>\ |
| 1921 | + <input type="text" id="wikieditor-toolbar-replace-search" style="width: 100%;" />\ |
| 1922 | + </div>\ |
| 1923 | + <div class="wikieditor-toolbar-field-wrapper">\ |
| 1924 | + <label for="wikieditor-toolbar-replace-replace" rel="wikieditor-toolbar-tool-replace-replace"></label>\ |
| 1925 | + <input type="text" id="wikieditor-toolbar-replace-replace" style="width: 100%;" />\ |
| 1926 | + </div>\ |
| 1927 | + <div class="wikieditor-toolbar-field-wrapper">\ |
| 1928 | + <input type="checkbox" id="wikieditor-toolbar-replace-case" />\ |
| 1929 | + <label for="wikieditor-toolbar-replace-case" rel="wikieditor-toolbar-tool-replace-case"></label>\ |
| 1930 | + </div>\ |
| 1931 | + <div class="wikieditor-toolbar-field-wrapper">\ |
| 1932 | + <input type="checkbox" id="wikieditor-toolbar-replace-regex" />\ |
| 1933 | + <label for="wikieditor-toolbar-replace-regex" rel="wikieditor-toolbar-tool-replace-regex"></label>\ |
| 1934 | + </div>\ |
| 1935 | + </fieldset>', |
| 1936 | + init: function() { |
| 1937 | + var u = mw.usability; |
| 1938 | + $j(this).find( '[rel]' ).each( function() { |
| 1939 | + $j(this).text( u.getMsg( $j(this).attr( 'rel' ) ) ); |
| 1940 | + }); |
| 1941 | + // Set tabindexes on form fields |
| 1942 | + $j.wikiEditor.modules.dialogs.fn.setTabindexes( $j(this).find( 'input' ).not( '[tabindex]' ) ); |
| 1943 | + |
| 1944 | + // TODO: Find a cleaner way to share this function |
| 1945 | + $j(this).data( 'replaceCallback', function( mode ) { |
| 1946 | + $j( '#wikieditor-toolbar-replace-nomatch, #wikieditor-toolbar-replace-success, #wikieditor-toolbar-replace-emptysearch, #wikieditor-toolbar-replace-invalidregex' ).hide(); |
| 1947 | + var searchStr = $j( '#wikieditor-toolbar-replace-search' ).val(); |
| 1948 | + if ( searchStr == '' ) { |
| 1949 | + $j( '#wikieditor-toolbar-replace-emptysearch' ).show(); |
| 1950 | + return; |
| 1951 | + } |
| 1952 | + var replaceStr = $j( '#wikieditor-toolbar-replace-replace' ).val(); |
| 1953 | + var flags = 'm'; |
| 1954 | + var matchCase = $j( '#wikieditor-toolbar-replace-case' ).is( ':checked' ); |
| 1955 | + var isRegex = $j( '#wikieditor-toolbar-replace-regex' ).is( ':checked' ); |
| 1956 | + if ( !matchCase ) { |
| 1957 | + flags += 'i'; |
| 1958 | + } |
| 1959 | + if ( mode == 'replaceAll' ) { |
| 1960 | + flags += 'g'; |
| 1961 | + } |
| 1962 | + if ( !isRegex ) { |
| 1963 | + searchStr = RegExp.escape( searchStr ); |
| 1964 | + } |
| 1965 | + try { |
| 1966 | + var regex = new RegExp( searchStr, flags ); |
| 1967 | + } catch( e ) { |
| 1968 | + $j( '#wikieditor-toolbar-replace-invalidregex' ) |
| 1969 | + .text( u.getMsg( 'wikieditor-toolbar-tool-replace-invalidregex', |
| 1970 | + e.message ) ) |
| 1971 | + .show(); |
| 1972 | + return; |
| 1973 | + } |
| 1974 | + var $textarea = $j(this).data( 'context' ).$textarea; |
| 1975 | + var text = $textarea.textSelection( 'getContents' ); |
| 1976 | + var match = false; |
| 1977 | + var offset, s; |
| 1978 | + if ( mode != 'replaceAll' ) { |
| 1979 | + offset = $j(this).data( 'offset' ); |
| 1980 | + s = text.substr( offset ); |
| 1981 | + match = s.match( regex ); |
| 1982 | + } |
| 1983 | + if ( !match ) { |
| 1984 | + // Search hit BOTTOM, continuing at TOP |
| 1985 | + offset = 0; |
| 1986 | + s = text; |
| 1987 | + match = s.match( regex ); |
| 1988 | + } |
| 1989 | + |
| 1990 | + if ( !match ) { |
| 1991 | + $j( '#wikieditor-toolbar-replace-nomatch' ).show(); |
| 1992 | + } else if ( mode == 'replaceAll' ) { |
| 1993 | + // Instead of using repetitive .match() calls, we use one .match() call with /g |
| 1994 | + // and indexOf() followed by substr() to find the offsets. This is actually |
| 1995 | + // faster because our indexOf+substr loop is faster than a match loop, and the |
| 1996 | + // /g match is so ridiculously fast that it's negligible. |
| 1997 | + // FIXME: Repetitively calling encapsulateSelection() is probably the best strategy |
| 1998 | + // in Firefox/Webkit, but in IE replacing the entire content once is better. |
| 1999 | + var index; |
| 2000 | + for ( var i = 0; i < match.length; i++ ) { |
| 2001 | + index = s.indexOf( match[i] ); |
| 2002 | + if ( index == -1 ) { |
| 2003 | + // This shouldn't happen |
| 2004 | + break; |
| 2005 | + } |
| 2006 | + var matchedText = s.substr( index, match[i].length ); |
| 2007 | + s = s.substr( index + match[i].length ); |
| 2008 | + |
| 2009 | + var start = index + offset; |
| 2010 | + var end = start + match[i].length; |
| 2011 | + // Make regex placeholder substitution ($1) work |
| 2012 | + var replace = isRegex ? matchedText.replace( regex, replaceStr ) : replaceStr; |
| 2013 | + var newEnd = start + replace.length; |
| 2014 | + $textarea |
| 2015 | + .textSelection( 'setSelection', { 'start': start, 'end': end } ) |
| 2016 | + .textSelection( 'encapsulateSelection', { |
| 2017 | + 'peri': replace, |
| 2018 | + 'replace': true } ) |
| 2019 | + .textSelection( 'setSelection', { 'start': start, 'end': newEnd } ); |
| 2020 | + offset = newEnd; |
| 2021 | + } |
| 2022 | + $j( '#wikieditor-toolbar-replace-success' ) |
| 2023 | + .text( u.getMsg( 'wikieditor-toolbar-tool-replace-success', match.length ) ) |
| 2024 | + .show(); |
| 2025 | + $j(this).data( 'offset', 0 ); |
| 2026 | + } else { |
| 2027 | + // Make regex placeholder substitution ($1) work |
| 2028 | + var replace = isRegex ? match[0].replace( regex, replaceStr ): replaceStr; |
| 2029 | + var start = match.index + offset; |
| 2030 | + var end = start + match[0].length; |
| 2031 | + var newEnd = start + replace.length; |
| 2032 | + var context = $j( this ).data( 'context' ); |
| 2033 | + $textarea.textSelection( 'setSelection', { 'start': start, |
| 2034 | + 'end': end } ); |
| 2035 | + if ( mode == 'replace' ) { |
| 2036 | + $textarea |
| 2037 | + .textSelection( 'encapsulateSelection', { |
| 2038 | + 'peri': replace, |
| 2039 | + 'replace': true } ) |
| 2040 | + .textSelection( 'setSelection', { |
| 2041 | + 'start': start, |
| 2042 | + 'end': newEnd } ); |
| 2043 | + } |
| 2044 | + $textarea.textSelection( 'scrollToCaretPosition' ); |
| 2045 | + $textarea.textSelection( 'setSelection', { 'start': start, |
| 2046 | + 'end': mode == 'replace' ? newEnd : end } ); |
| 2047 | + $j( this ).data( 'offset', mode == 'replace' ? newEnd : end ); |
| 2048 | + var textbox = typeof context.$iframe != 'undefined' ? context.$iframe[0].contentWindow : $textarea[0]; |
| 2049 | + textbox.focus(); |
| 2050 | + } |
| 2051 | + }); |
| 2052 | + }, |
| 2053 | + dialog: { |
| 2054 | + width: 500, |
| 2055 | + dialogClass: 'wikiEditor-toolbar-dialog', |
| 2056 | + buttons: { |
| 2057 | + 'wikieditor-toolbar-tool-replace-button-findnext': function( e ) { |
| 2058 | + $j(this).closest( '.ui-dialog' ).data( 'dialogaction', e.target ); |
| 2059 | + $j(this).data( 'replaceCallback' ).call( this, 'find' ); |
| 2060 | + }, |
| 2061 | + 'wikieditor-toolbar-tool-replace-button-replacenext': function( e ) { |
| 2062 | + $j(this).closest( '.ui-dialog' ).data( 'dialogaction', e.target ); |
| 2063 | + $j(this).data( 'replaceCallback' ).call( this, 'replace' ); |
| 2064 | + }, |
| 2065 | + 'wikieditor-toolbar-tool-replace-button-replaceall': function( e ) { |
| 2066 | + $j(this).closest( '.ui-dialog' ).data( 'dialogaction', e.target ); |
| 2067 | + $j(this).data( 'replaceCallback' ).call( this, 'replaceAll' ); |
| 2068 | + }, |
| 2069 | + 'wikieditor-toolbar-tool-replace-close': function() { |
| 2070 | + $j(this).dialog( 'close' ); |
| 2071 | + } |
| 2072 | + }, |
| 2073 | + open: function() { |
| 2074 | + $j(this).data( 'offset', 0 ); |
| 2075 | + $j( '#wikieditor-toolbar-replace-search' ).focus(); |
| 2076 | + $j( '#wikieditor-toolbar-replace-nomatch, #wikieditor-toolbar-replace-success, #wikieditor-toolbar-replace-emptysearch, #wikieditor-toolbar-replace-invalidregex' ).hide(); |
| 2077 | + if ( !( $j(this).data( 'onetimeonlystuff' ) ) ) { |
| 2078 | + $j(this).data( 'onetimeonlystuff', true ); |
| 2079 | + // Execute the action associated with the first button |
| 2080 | + // when the user presses Enter |
| 2081 | + $j(this).closest( '.ui-dialog' ).keypress( function( e ) { |
| 2082 | + if ( ( e.keyCode || e.which ) == 13 ) { |
| 2083 | + var button = $j(this).data( 'dialogaction' ) || $j(this).find( 'button:first' ); |
| 2084 | + button.click(); |
| 2085 | + e.preventDefault(); |
| 2086 | + } |
| 2087 | + }); |
| 2088 | + // Make tabbing to a button and pressing |
| 2089 | + // Enter do what people expect |
| 2090 | + $j(this).closest( '.ui-dialog' ).find( 'button' ).focus( function() { |
| 2091 | + $j(this).closest( '.ui-dialog' ).data( 'dialogaction', this ); |
| 2092 | + }); |
| 2093 | + } |
| 2094 | + var dialog = $j(this).closest( '.ui-dialog' ); |
| 2095 | + var that = this; |
| 2096 | + var context = $j(this).data( 'context' ); |
| 2097 | + var textbox = typeof context.$iframe != 'undefined' ? |
| 2098 | + context.$iframe[0].contentWindow.document : context.$textarea; |
| 2099 | + |
| 2100 | + $j( textbox ) |
| 2101 | + .bind( 'keypress.srdialog', function( e ) { |
| 2102 | + if ( ( e.keyCode || e.which ) == 13 ) { |
| 2103 | + // Enter |
| 2104 | + var button = dialog.data( 'dialogaction' ) || dialog.find( 'button:first' ); |
| 2105 | + button.click(); |
| 2106 | + e.preventDefault(); |
| 2107 | + } else if ( ( e.keyCode || e.which ) == 27 ) { |
| 2108 | + // Escape |
| 2109 | + $j(that).dialog( 'close' ); |
| 2110 | + } |
| 2111 | + }); |
| 2112 | + }, |
| 2113 | + close: function() { |
| 2114 | + var context = $j(this).data( 'context' ); |
| 2115 | + var textbox = typeof context.$iframe != 'undefined' ? |
| 2116 | + context.$iframe[0].contentWindow.document : context.$textarea; |
| 2117 | + $j( textbox ).unbind( 'keypress.srdialog' ); |
| 2118 | + $j(this).closest( '.ui-dialog' ).data( 'dialogaction', false ); |
| 2119 | + } |
| 2120 | + } |
| 2121 | + } |
| 2122 | +} } ); |
| 2123 | + |
| 2124 | +} } ); |
| 2125 | + |
Property changes on: trunk/extensions/WikiEditor/modules/Toolbar.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 2126 | + native |