r111039 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r111038‎ | r111039 | r111040 >
Date:14:51, 9 February 2012
Author:reedy
Status:resolved (Comments)
Tags:miscextensions 
Comment:
Move ext.narayam.core modules to their own folder
Modified paths:
  • /trunk/extensions/Narayam/Narayam.php (modified) (history)
  • /trunk/extensions/Narayam/resources/ext.narayam.core (added) (history)
  • /trunk/extensions/Narayam/resources/ext.narayam.core-modern.css (deleted) (history)
  • /trunk/extensions/Narayam/resources/ext.narayam.core-monobook.css (deleted) (history)
  • /trunk/extensions/Narayam/resources/ext.narayam.core-vector.css (deleted) (history)
  • /trunk/extensions/Narayam/resources/ext.narayam.core.css (deleted) (history)
  • /trunk/extensions/Narayam/resources/ext.narayam.core.js (deleted) (history)
  • /trunk/extensions/Narayam/resources/ext.narayam.core/ext.narayam.core-modern.css (added) (history)
  • /trunk/extensions/Narayam/resources/ext.narayam.core/ext.narayam.core-monobook.css (added) (history)
  • /trunk/extensions/Narayam/resources/ext.narayam.core/ext.narayam.core-vector.css (added) (history)
  • /trunk/extensions/Narayam/resources/ext.narayam.core/ext.narayam.core.css (added) (history)
  • /trunk/extensions/Narayam/resources/ext.narayam.core/ext.narayam.core.js (added) (history)

Diff [purge]

Index: trunk/extensions/Narayam/resources/ext.narayam.core-monobook.css
@@ -1,4 +0,0 @@
2 -div#narayam-menu div.menu-items {
3 - font-size: 1.2em;
4 -}
5 -
Index: trunk/extensions/Narayam/resources/ext.narayam.core-modern.css
@@ -1,42 +0,0 @@
2 -#p-personal {
3 - /* #p-personal has overflow:hidden. That makes a dropdown menu appearing hidden.
4 - * overriding it this way may not be the best way.
5 - */
6 - overflow: visible !important;
7 -}
8 -
9 -li#pt-narayam {
10 - margin-left: 5px;
11 -}
12 -
13 -div#narayam-menu div.menu-items {
14 - top: 0px;
15 - font-size: 1.2em;
16 - position: relative;
17 -}
18 -
19 -div#narayam-menu ul {
20 - min-width: 15em;
21 - height: auto;
22 -}
23 -div#narayam-menu li {
24 - background-color: #FFFFFF;
25 - font-weight: normal;
26 - white-space: nowrap;
27 - text-transform: none;
28 - font-variant: normal;
29 -}
30 -
31 -div#narayam-menu ul {
32 - background-color: #FFFFFF;
33 - border: solid 1px silver;
34 - height: auto;
35 -}
36 -
37 -div#narayam-menu li a:hover {
38 - color: #0645AD;
39 -}
40 -
41 -div#narayam-menu li:hover {
42 - background-color: #FFFFFF;
43 -}
Index: trunk/extensions/Narayam/resources/ext.narayam.core.css
@@ -1,137 +0,0 @@
2 -.narayam-input {
3 - /* FIXME: needed to add !important because WikiEditor overrides border for #wpTextbox1
4 - * and SimpleSearch overrides background-color for the search box. Talk to Trevor
5 - * about styling this nicely
6 - */
7 - background-color: #EAF3F8 !important;
8 -}
9 -
10 -li#pt-narayam {
11 - padding-left: 15px !important;
12 -}
13 -
14 -/* Variants and Actions */
15 -/* @noflip */
16 -div#narayam-menu {
17 - direction: ltr;
18 - float: left;
19 - display: none;
20 -}
21 -
22 -div#narayam-menu.open {
23 - display: block;
24 -}
25 -/* @noflip */
26 -body.rtl div#narayam-menu {
27 - direction: rtl;
28 -}
29 -div#narayam-menu div.menu-items {
30 - position: absolute;
31 - display: block;
32 - clear: both;
33 - text-align: left;
34 - z-index: 99999;
35 - width: 200px;
36 - top: 20px;
37 - font-size: 0.8em;
38 -}
39 -
40 -div#narayam-menu-items li {
41 - margin: 0;
42 - padding: 5px;
43 - font-size: 100%;
44 - float: none;
45 - z-index: 99999;
46 -
47 -}
48 -ul#imelist{
49 - padding: 5px;
50 -}
51 -/* OVERRIDDEN BY COMPLIANT BROWSERS */
52 -/* @noflip */
53 -body.rtl div#narayam-menu div.menu-items {
54 - margin-left: 24px;
55 -}
56 -/* IGNORED BY IE6 */
57 -/* @noflip */
58 -body.rtl div#narayam-menu > div.menu-items {
59 - margin-left: auto;
60 -}
61 -/* IGNORED BY IE6 */
62 -/* Also fixes old versions of FireFox */
63 -/* @noflip */
64 -body.rtl div#narayam-menu > div.menu-items,
65 -x:-moz-any-link {
66 - margin-left: 23px;
67 -}
68 -
69 -div#narayam-menu ul {
70 - position: absolute;
71 - background-color: white;
72 - border: solid 1px silver;
73 - -moz-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
74 - -webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
75 - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
76 - border-top-width: 0;
77 - list-style: none;
78 - list-style-image: none;
79 - list-style-type: none;
80 - padding: 10px; /* Space for scrollbars etc. */
81 - margin: 0;
82 - margin-left: -1px;
83 - text-align: left;
84 - max-height: 360px;
85 - overflow-y: auto;
86 - width: 100%;
87 -}
88 -
89 -div#narayam-menu li {
90 - margin: 0;
91 - text-align: left;
92 - line-height: 1em;
93 -}
94 -
95 -div#narayam-menu li.selected a,
96 -div#narayam-menu li.selected a:visited {
97 - color: #333333;
98 - text-decoration: none;
99 -}
100 -div#narayam-menu a {
101 - display: block;
102 - padding-left: 10px;
103 - padding-right: 10px;
104 -}
105 -
106 -div#narayam-menu-items li.narayam-help-link a {
107 - /* @embed */
108 - background: url('images/help.png') no-repeat scroll left center transparent;
109 - padding-left: 20px;
110 - line-height: 1.5em;
111 -}
112 -
113 -li#pt-narayam.narayam-active {
114 - /* @embed */
115 - background: url('images/narayam-active.png') no-repeat scroll left top transparent;
116 -}
117 -
118 -li#pt-narayam.narayam-inactive {
119 - /* @embed */
120 - background: url('images/narayam-inactive.png') no-repeat scroll left top transparent;
121 -}
122 -
123 -li.narayam-more-imes-link {
124 - /* @embed */
125 - background: url('images/closed-ltr.png') no-repeat scroll left center transparent;
126 -}
127 -
128 -li.narayam-more-imes-link.open {
129 - /* @embed */
130 - background: url('images/open.png') no-repeat scroll left center transparent;
131 -}
132 -li.narayam-more-imes-link a {
133 - padding-left: 10px;
134 -}
135 -
136 -div#narayam-menu label:hover, div#narayam-menu input:hover {
137 - cursor: pointer;
138 -}
Index: trunk/extensions/Narayam/resources/ext.narayam.core.js
@@ -1,736 +0,0 @@
2 -/**
3 - * Narayam
4 - * Input field rewriter tool for web pages
5 - * @author Junaid P V ([[user:Junaidpv]])(http://junaidpv.in)
6 - * @date 2010-12-18 (Based on naaraayam transliteration tool I first wrote on 2010-05-19)
7 - * @version 3.0
8 - * Last update: 2010-11-28
9 - * License: GPLv3
10 - */
11 -
12 -/**
13 - * NOTE: For documentation on writing schemes and rulesets, see the
14 - * documentation for addScheme().
15 - */
16 -
17 -( function( $ ) {
18 -$.narayam = new ( function() {
19 - /* Private members */
20 -
21 - // Reference to this object
22 - var that = this;
23 - // jQuery array holding all text inputs Narayam applies to
24 - var $inputs = $( [] );
25 - // Whether Narayam is enabled
26 - var enabled = false;
27 - // Registered schemes
28 - var schemes = {};
29 - // List of scheme names, ordered for presentation purposes
30 - // Schemes not in this list won't be allowed to register
31 - // This object is formatted as { 'schemename': '', 'schemename2': '', ... }
32 - // for easy searching
33 - var availableSchemes = mw.config.get( 'wgNarayamAvailableSchemes' ) || {};
34 - // All input methods. This will be used for selecting input methods from languages
35 - // other than uselang- optionally
36 - var allImes = mw.config.get( 'wgNarayamAllSchemes' ) || {};
37 - // Currently selected scheme
38 - var currentScheme = null;
39 - // Shortcut key for turning Narayam on and off
40 - var shortcutKey = getShortCutKey();
41 - // Number of recent input methods to be shown
42 - var recentItemsLength = mw.config.get( 'wgNarayamRecentItemsLength' );
43 -
44 - /* Private functions */
45 -
46 - /**
47 - * Transliterate a string using the current scheme
48 - * @param str String to transliterate
49 - * @param keyBuffer The key buffer
50 - * @param useExtended Whether to use the extended part of the scheme
51 - * @return Transliterated string, or str if no applicable transliteration found.
52 - */
53 - this.transliterate = function( str, keyBuffer, useExtended ) {
54 - var rules = currentScheme.extended_keyboard && useExtended ?
55 - currentScheme.rules_x : currentScheme.rules;
56 - for ( var i = 0; i < rules.length; i++ ) {
57 - var regex = new RegExp( rules[i][0] + '$' );
58 - if ( regex.test( str ) // Input string match
59 - &&
60 - (
61 - rules[i][1].length === 0 // Keybuffer match not required
62 - ||
63 - ( // Keybuffer match specified, so it should be met
64 - rules[i][1].length > 0
65 - && rules[i][1].length <= keyBuffer.length
66 - && new RegExp( rules[i][1] + '$' ).test( keyBuffer )
67 - )
68 - )
69 - ) {
70 - return str.replace( regex, rules[i][2] );
71 - }
72 - }
73 - // No matches, return the input
74 - return str;
75 - }
76 -
77 - /**
78 - * Get the n characters in str that immediately precede pos
79 - * Example: lastNChars( "foobarbaz", 5, 2 ) == "ba"
80 - * @param str String to search in
81 - * @param pos Position in str
82 - * @param n Number of characters to go back from pos
83 - * @return Substring of str, at most n characters long, immediately preceding pos
84 - */
85 - this.lastNChars = function( str, pos, n ) {
86 - if ( n === 0 ) {
87 - return '';
88 - } else if ( pos <= n ) {
89 - return str.substr( 0, pos );
90 - } else {
91 - return str.substr( pos - n, n );
92 - }
93 - }
94 -
95 - /**
96 - * Find the point at which a and b diverge, i.e. the first position
97 - * at which they don't have matching characters.
98 - * @param a String
99 - * @param b String
100 - * @return Position at which a and b diverge, or -1 if a == b
101 - */
102 - this.firstDivergence = function( a, b ) {
103 - var minLength = a.length < b.length ? a.length : b.length;
104 - for ( var i = 0; i < minLength; i++ ) {
105 - if ( a.charCodeAt( i ) !== b.charCodeAt( i ) ) {
106 - return i;
107 - }
108 - }
109 - return -1;
110 - }
111 -
112 - /**
113 - * Check whether a keypress event corresponds to the shortcut key
114 - * @param e Event object
115 - * @return bool
116 - */
117 - function isShortcutKey( e ) {
118 - return e.altKey == shortcutKey.altKey &&
119 - e.ctrlKey == shortcutKey.ctrlKey &&
120 - e.shiftKey == shortcutKey.shiftKey &&
121 - String.fromCharCode( e.which ) == shortcutKey.key;
122 - }
123 -
124 - /**
125 - * Get the shortcut key for the tool, depending on OS, browser
126 - * @return shortcutKey
127 - */
128 - function getShortCutKey() {
129 - var defaultShortcut = {
130 - altKey: false,
131 - ctrlKey: true,
132 - shiftKey: false,
133 - cmdKey: false,
134 - key: 'M'
135 - };
136 - // Browser sniffing to determine the available shortcutKey
137 - // Refer: mediawiki.util.js and en.wikipedia.org/wiki/Access_key
138 - var profile = $.client.profile();
139 - // Safari/Konqueror on any platform, but not Safari on Windows
140 - // or any browser on Mac except chrome and opera
141 - if ( !( profile.platform == 'win' && profile.name == 'safari' ) &&
142 - ( profile.name == 'safari'|| profile.platform == 'mac' || profile.name == 'konqueror' )
143 - && !( profile.name == 'opera' || profile.name == 'chrome' ) ) {
144 - defaultShortcut.key = 'G';
145 - }
146 - // For Opera in OSX, shortcut is control+command+m.
147 - if ( profile.name == 'opera' && profile.platform == 'mac' ) {
148 - defaultShortcut.cmdKey = true;
149 - }
150 - return defaultShortcut;
151 - }
152 -
153 - /**
154 - * Get a description of the shortcut key, e.g. "Ctrl-M"
155 - * @return string
156 - */
157 - function shortcutText() {
158 - var text = '';
159 - // TODO: Localize these things (in core, too)
160 - if ( shortcutKey.ctrlKey ) {
161 - text += 'Ctrl-';
162 - }
163 - if ( shortcutKey.shiftKey ) {
164 - text += 'Shift-';
165 - }
166 - if ( shortcutKey.altKey ) {
167 - text += 'Alt-';
168 - }
169 - if ( shortcutKey.cmdKey ) {
170 - text += 'Command-';
171 - }
172 - text += shortcutKey.key.toUpperCase();
173 - return text;
174 - }
175 -
176 - /**
177 - * Change visual appearance of element (text input, textarea) according
178 - * to the current state of Narayam
179 - */
180 - function changeVisual( $element ) {
181 - if ( enabled ) {
182 - $element.addClass( 'narayam-input' );
183 - } else {
184 - $element.removeClass( 'narayam-input' );
185 - }
186 - }
187 -
188 - /**
189 - * Replace text part from startPos to endPos with peri
190 - * This function is specifically for webkit browsers,
191 - * because of bug: https://bugs.webkit.org/show_bug.cgi?id=66630
192 - * TODO: remove when webkit bug is handled in jQuery.textSelection.js
193 - *
194 - * @param $element jQuery object to wich replacement to be taked place
195 - * @param startPos Starting position of text range to be replaced
196 - * @param endPos Ending position of text range to be replaced
197 - * @param peri String to be substituted
198 - */
199 - function replaceString( $element, startPos, endPos, peri ) {
200 - // Take entire text of the element
201 - var text = $element.val();
202 - var pre = text.substring( 0, startPos );
203 - var post = text.substring( endPos, text.length );
204 -
205 - // Then replace
206 - $element.val( pre + peri + post );
207 - }
208 -
209 - /**
210 - * Keydown event handler. Handles shortcut key presses
211 - * @param e Event object
212 - */
213 - function onkeydown( e ) {
214 - // If the current scheme uses the alt key, ignore keydown for Alt+? combinations
215 - if ( enabled && currentScheme.extended_keyboard && e.altKey && !e.ctrlKey ) {
216 - e.stopPropagation();
217 - return false; // Not in original code -- does this belong here?
218 - } else if ( isShortcutKey( e ) ) {
219 - that.toggle();
220 - changeVisual( $( this ) );
221 - e.stopPropagation();
222 - return false;
223 - }
224 - return true;
225 - }
226 -
227 - /**
228 - * Keypress event handler. This is where the real work happens
229 - * @param e Event object
230 - */
231 - function onkeypress( e ) {
232 - if ( !enabled ) {
233 - return true;
234 - }
235 -
236 - if ( e.which == 8 ) { // Backspace
237 - // Blank the keybuffer
238 - $( this ).data( 'narayamKeyBuffer', '' );
239 - return true;
240 - }
241 -
242 - // Leave ASCII control characters alone, as well as anything involving
243 - // Alt (except for extended keymaps), Ctrl and Meta
244 - if ( e.which < 32 || ( e.altKey && !currentScheme.extended_keyboard ) || e.ctrlKey || e.metaKey ) {
245 - return true;
246 - }
247 -
248 - var $this = $( this );
249 - var c = String.fromCharCode( e.which );
250 - // Get the current caret position. The user may have selected text to overwrite,
251 - // so get both the start and end position of the selection. If there is no selection,
252 - // startPos and endPos will be equal.
253 - var pos = $this.textSelection( 'getCaretPosition', { 'startAndEnd': true } );
254 - var startPos = pos[0];
255 - var endPos = pos[1];
256 - // Get the last few characters before the one the user just typed,
257 - // to provide context for the transliteration regexes.
258 - // We need to append c because it hasn't been added to $this.val() yet
259 - var input = that.lastNChars( $this.val(), startPos, currentScheme.lookbackLength ) + c;
260 - var keyBuffer = $this.data( 'narayamKeyBuffer' );
261 - var replacement = that.transliterate( input, keyBuffer, e.altKey );
262 -
263 - // Update the key buffer
264 - keyBuffer += c;
265 - if ( keyBuffer.length > currentScheme.keyBufferLength ) {
266 - // The buffer is longer than needed, truncate it at the front
267 - keyBuffer = keyBuffer.substring( keyBuffer.length - currentScheme.keyBufferLength );
268 - }
269 - $this.data( 'narayamKeyBuffer', keyBuffer );
270 -
271 - // textSelection() magic is expensive, so we avoid it as much as we can
272 - if ( replacement == input ) {
273 - return true;
274 - }
275 - // Drop a common prefix, if any
276 - // TODO: Profile this, see if it's any faster
277 - var divergingPos = that.firstDivergence( input, replacement );
278 - input = input.substring( divergingPos );
279 - replacement = replacement.substring( divergingPos );
280 -
281 - $this.textSelection( 'encapsulateSelection', {
282 - peri: replacement,
283 - replace: true,
284 - selectPeri: false,
285 - selectionStart: startPos - input.length + 1,
286 - selectionEnd: endPos
287 - } );
288 -
289 - e.stopPropagation();
290 - return false;
291 - }
292 -
293 - /**
294 - * Focus event handler.
295 - * @param e Event object
296 - */
297 - function onfocus( e ) {
298 - if ( !$( this ).data( 'narayamKeyBuffer' ) ) {
299 - // First-time focus on the input field
300 - // So, initialise a key buffer for it
301 - $( this ).data( 'narayamKeyBuffer', '' );
302 - }
303 - changeVisual( $( this ) );
304 - }
305 -
306 - /**
307 - * Blur event handler.
308 - * @param e Event object
309 - */
310 - function onblur( e ) {
311 - $( this ).removeClass( 'narayam-input' );
312 - }
313 -
314 -
315 - /* Public functions */
316 -
317 - /**
318 - * Add more inputs to apply Narayam to
319 - * @param inputs A jQuery object holding one or more input or textarea elements,
320 - * or an array of DOM elements, or a single DOM element, or a selector
321 - */
322 - this.addInputs = function( inputs ) {
323 - if ( typeof( inputs ) === "string" ) {
324 - // If a string is passed, it is a CSS selector
325 - // We can use jQuery's .live() instead of .bind()
326 - // So Narayam can work on elements added later to DOM too
327 - $( inputs )
328 - .live( 'keydown', onkeydown )
329 - .live( 'keypress', onkeypress )
330 - .live( 'focus', onfocus )
331 - .live( 'blur', onblur );
332 - } else {
333 - var $newInputs = $( inputs );
334 - $inputs = $inputs.add( $newInputs );
335 - $newInputs
336 - .bind( 'keydown.narayam', onkeydown )
337 - .bind( 'keypress.narayam', onkeypress )
338 - .bind( 'focus', onfocus )
339 - .bind( 'blur', onblur );
340 - }
341 - };
342 -
343 - /**
344 - * Enable Narayam
345 - */
346 - this.enable = function() {
347 - if ( !enabled ) {
348 - $.cookie( 'narayam-enabled', '1', { path: '/', expires: 30 } );
349 - $( '#narayam-toggle' ).prop( 'checked', true );
350 - $( 'li#pt-narayam' )
351 - .removeClass( 'narayam-inactive' )
352 - .addClass( 'narayam-active' );
353 - enabled = true;
354 - }
355 - };
356 -
357 - /**
358 - * Disable Narayam
359 - */
360 - this.disable = function() {
361 - if ( enabled ) {
362 - $.cookie( 'narayam-enabled', '0', { path: '/', expires: 30 } );
363 - $( '#narayam-toggle' ).prop( 'checked', false );
364 - $( 'li#pt-narayam' )
365 - .removeClass( 'narayam-active' )
366 - .addClass( 'narayam-inactive' );
367 - enabled = false;
368 - }
369 - };
370 -
371 - /**
372 - * Toggle the enabled/disabled state
373 - */
374 - this.toggle = function() {
375 - if ( enabled ) {
376 - that.disable();
377 - } else {
378 - that.enable();
379 - }
380 - };
381 -
382 - this.enabled = function() {
383 - return enabled;
384 - };
385 -
386 - /**
387 - * Add a transliteration scheme. Schemes whose name is not in
388 - * wgNarayamAvailableSchemes will be ignored.
389 - *
390 - * A scheme consists of rules used for transliteration. A rule is an
391 - * array of three strings. The first string is a regex that is matched
392 - * against the input string (the last few characters before the cursor
393 - * followed by the character the user entered), the second string is a
394 - * regex that is matched against the end of the key buffer (the last
395 - * few keys the user pressed), and the third string is the replacement
396 - * string (may contain placeholders like $1 for subexpressions). You do
397 - * not need to add $ to the end of either of the regexes so they match
398 - * at the end, this is done automagically.
399 - *
400 - * The transliteration algorithm processes the rules in the order they
401 - * are specified, and applies the first rule that matches. For a rule
402 - * to match, both the first and second regex have to match (the first
403 - * for the input, the second for the key buffer). Most rules do not use
404 - * the keybuffer and specify an empty string as the second regex.
405 - *
406 - * The scheme data object must have the following keys:
407 - * namemsg: Message key for the name of the scheme
408 - * extended_keyboard: Whether this scheme has an extended ruleset (bool)
409 - * lookbackLength: Number of characters before the cursor to include
410 - * when matching the first regex of each rule. This is
411 - * usually the maximum number of characters a rule
412 - * regex can match minus one.
413 - * keyBufferLength: Length of the key buffer. May be zero if not needed
414 - * rules: Array of rules, which themselves are arrays of three strings.
415 - * rules_x: Extended ruleset. This is used instead of the normal
416 - * ruleset when Alt is held. This key is only required if
417 - * extended_keyboard is true
418 - *
419 - * NOTE: All keys are REQUIRED (except rules_x when not used). Missing
420 - * keys may result in JS errors.
421 - *
422 - * @param name Name of the scheme, must be unique
423 - * @param data Object with scheme data.
424 - * @return True if added, false if not
425 - */
426 - this.addScheme = function( name, data ) {
427 - schemes[name] = data;
428 - return true;
429 - };
430 -
431 - /**
432 - * Get the transliteration rules for the given input method name.
433 - * @param name String
434 - */
435 - this.getScheme = function( name ) {
436 - return schemes[name];
437 - };
438 -
439 - /**
440 - * Change the current transliteration scheme
441 - * @param name String
442 - */
443 - this.setScheme = function( name ) {
444 - var recent = $.cookie( 'narayam-scheme' ) || [];
445 - if ( typeof recent === "string" ) {
446 - recent = recent.split( "," );
447 - }
448 - recent = $.grep( recent, function( value ) {
449 - return value != name;
450 - } );
451 - recent.unshift( name );
452 - recent = recent.slice( 0, recentItemsLength );
453 - recent = recent.join( "," );
454 - $.cookie( 'narayam-scheme', recent, { path: '/', expires: 30 } );
455 - if ( name in schemes ) {
456 - currentScheme = schemes[name];
457 - } else {
458 - // load the rules dynamically.
459 - mw.loader.using( "ext.narayam.rules." + name, function() {
460 - currentScheme = schemes[name];
461 - } );
462 - }
463 - return true;
464 - };
465 -
466 - /**
467 - * Set up Narayam. This adds the scheme dropdown, binds the handlers
468 - * and initializes the enabled/disabled state and selected scheme
469 - * from a cookie or wgNarayamEnabledByDefault
470 - */
471 - this.setup = function() {
472 - that.buildMenu();
473 - // Restore state from cookies
474 - var recent = $.cookie( 'narayam-scheme' );
475 - var lastScheme = null;
476 - if ( typeof recent === "string" ) {
477 - lastScheme = recent.split( "," )[0];
478 - }
479 - if ( lastScheme ) {
480 - that.setScheme( lastScheme );
481 - $( '#narayam-' + lastScheme ).prop( 'checked', true );
482 - } else {
483 - //if no saved input scheme, select the first.
484 - var $firstScheme = $( 'input.narayam-scheme:first' );
485 - that.setScheme( $firstScheme.val() );
486 - $firstScheme.prop( 'checked', true );
487 -
488 - }
489 - var enabledCookie = $.cookie( 'narayam-enabled' );
490 - if ( enabledCookie == '1' || ( mw.config.get( 'wgNarayamEnabledByDefault' ) && enabledCookie !== '0' ) ) {
491 - that.enable();
492 - } else {
493 - $( 'li#pt-narayam' ).addClass( 'narayam-inactive' );
494 - }
495 - // Renew the narayam-enabled cookie. narayam-scheme is renewed by setScheme()
496 - if ( enabledCookie ) {
497 - $.cookie( 'narayam-enabled', enabledCookie, { path: '/', expires: 30 } );
498 - }
499 -
500 - };
501 - /**
502 - * Construct the menu item, for the given scheme name.
503 - */
504 - this.buildMenuItem = function( scheme ) {
505 - var $input = $( '<input type="radio" name="narayam-input-method" class="narayam-scheme" />' );
506 - $input.attr( 'id', 'narayam-' + scheme ).val( scheme );
507 -
508 - var $narayamMenuItemLabel = $( '<label>' )
509 - .attr( 'for' ,'narayam-' + scheme )
510 - .append( $input )
511 - .append( mw.message( 'narayam-' + scheme ).escaped() );
512 -
513 - var $narayamMenuItem = $( '<li>' )
514 - .append( $input )
515 - .append( $narayamMenuItemLabel );
516 -
517 - return $narayamMenuItem;
518 - };
519 -
520 - /**
521 - * prepare the menu list for all the input methods.
522 - * @return The div containing the constructed menu.
523 - */
524 - this.buildMenuItems = function() {
525 - var haveSchemes = false;
526 - // Build schemes option list
527 - var $narayamMenuItems = $( '<ul>' );
528 - var count = 1;
529 - var seen = [];
530 -
531 - var recent = $.cookie( "narayam-scheme" ) || [];
532 - if ( typeof recent === "string" ) {
533 - recent = recent.split( "," );
534 - }
535 -
536 - // Prepare the recent inputmethods menu items
537 - for ( var i = 0; i < recent.length; i++ ) {
538 - var scheme = recent[i];
539 - if ( $.inArray( scheme, seen ) > -1 ) { continue; }
540 - seen.push( scheme );
541 - if ( count++ > recentItemsLength ) { break; }
542 - var $narayamMenuItem = that.buildMenuItem( scheme );
543 - $narayamMenuItem.addClass( 'narayam-recent-menu-item' );
544 - $narayamMenuItems.append( $narayamMenuItem );
545 - }
546 -
547 - // menu items for the language of wiki.
548 - var requested = [mw.config.get( 'wgUserVariant' ), mw.config.get( 'wgContentLanguage' ), mw.config.get( 'wgUserLanguage' )];
549 - $( 'textarea[lang]' ).each( function( index ) {
550 - requested.push( this.lang );
551 - });
552 - for ( var i = 0; i < requested.length; i++ ) {
553 - var lang = requested[i];
554 - var langschemes = allImes[lang];
555 - if ( !langschemes ) continue;
556 - for ( var scheme in langschemes ) {
557 - haveSchemes = true;
558 - if ( $.inArray( scheme, seen ) !== -1 ) { continue; }
559 - seen.push( scheme );
560 - var $narayamMenuItem = that.buildMenuItem( scheme );
561 - $narayamMenuItems.append( $narayamMenuItem );
562 - }
563 - }
564 -
565 - if ( !haveSchemes ) {
566 - // No schemes available, don't show the tool
567 - return null;
568 - }
569 -
570 - // Build enable/disable checkbox and label
571 - var $checkbox = $( '<input type="checkbox" id="narayam-toggle" />' );
572 - $checkbox
573 - .attr( 'title', mw.msg( 'narayam-checkbox-tooltip' ) )
574 - .click( that.toggle );
575 -
576 - var $label = $( '<label>' ).attr( 'for', 'narayam-toggle' );
577 - $label
578 - .text( mw.msg( 'narayam-toggle-ime', shortcutText() ) )
579 - .prepend( $checkbox )
580 - .prop( 'title', mw.msg( 'narayam-checkbox-tooltip' ) );
581 -
582 - var $moreLink = $( '<a>' )
583 - .text( mw.msg( 'narayam-more-imes' ) )
584 - .prop( 'href', '#' )
585 - .click( function( event ) {
586 - $('.narayam-scheme-dynamic-item').toggle( 'fast' );
587 - if ( $('li.narayam-more-imes-link').hasClass( 'open' ) ) {
588 - $('li.narayam-more-imes-link').removeClass( 'open' );
589 - } else {
590 - $('li.narayam-more-imes-link').addClass( 'open' );
591 - }
592 - event.stopPropagation();
593 - } );
594 -
595 - $narayamMenuItems.append( $( '<li>' )
596 - .addClass( 'narayam-more-imes-link' )
597 - .append( $moreLink )
598 - );
599 -
600 - for ( var lang in allImes ) {
601 - var langschemes = allImes[lang];
602 - for ( var langscheme in langschemes ) {
603 - // Do not repeat the input methods in more input methods section.
604 - // If already shown on recent items.
605 - if ( $.inArray( langscheme, seen ) > -1 ) { continue; }
606 -
607 - var $narayamMenuItem = that.buildMenuItem( langscheme );
608 - $narayamMenuItem.addClass( 'narayam-scheme-dynamic-item' );
609 - $narayamMenuItems.append( $narayamMenuItem );
610 - }
611 - }
612 -
613 - // Event listener for scheme selection - dynamic loading of rules.
614 - $narayamMenuItems.delegate( 'input:radio', 'click', function( ) {
615 - that.setScheme( $( this ).val() );
616 - if ( $( this ).parent().hasClass( 'narayam-scheme-dynamic-item' ) ){
617 - // rebuild the menu items with recent items.
618 - $( '#narayam-menu' ).html( $.narayam.buildMenuItems() );
619 - $( '#narayam-menu-items' ).css( 'left', $( 'li#pt-narayam' ).offset().left );
620 - $( '#narayam-' + $( this ).val() ).prop( 'checked', true );
621 - if ( enabled ) {
622 - $( '#narayam-toggle' ).prop( 'checked', true );
623 - }
624 - }
625 - } );
626 -
627 - var helppage = mw.config.get( 'wgNarayamHelpPage' );
628 - if ( helppage ) {
629 - var $link = $( '<a>' )
630 - .text( mw.msg( 'narayam-help' ) )
631 - .prop( 'href', helppage )
632 - .prop( 'target', '_blank' );
633 - var $li = $( '<li>' ).addClass( 'narayam-help-link' );
634 - $narayamMenuItems.append( $li.append( $link ) );
635 - }
636 -
637 - $narayamMenuItems.prepend( $( '<li>' ).append( $label ) );
638 -
639 - return $( '<div>' )
640 - .attr( 'id', 'narayam-menu-items' )
641 - .addClass( 'menu-items' )
642 - .append( $narayamMenuItems );
643 - }
644 -
645 -
646 - /**
647 - * Construct the menu for Narayam
648 - */
649 - this.buildMenu = function() {
650 - // Remove the menu if already exists
651 - if( $( 'li#pt-webfont' ).length > 0 ) {
652 - $( 'li#pt-narayam' ).remove();
653 - $( 'div#narayam-menu' ).remove();
654 - }
655 - var $menuItemsDiv = that.buildMenuItems();
656 - if( $menuItemsDiv == null ) {
657 - return;
658 - }
659 - var $menu = $( '<div>' )
660 - .attr( 'id', 'narayam-menu' )
661 - .addClass( 'narayam-menu' );
662 - var $link = $( '<a>' )
663 - .prop( 'href', '#' )
664 - .text( mw.msg( 'narayam-menu' ) )
665 - .attr( 'title', mw.msg( 'narayam-menu-tooltip' ) );
666 -
667 - $menu.append( $menuItemsDiv );
668 - var $li = $( '<li>' ).attr( 'id', 'pt-narayam' ).append( $link );
669 -
670 - // If rtl, add to the right of top personal links. Else, to the left
671 - var rtlEnv = $( 'body' ).hasClass( 'rtl' );
672 - var positionFunction = rtlEnv ? "append" : "prepend";
673 - $( '#p-personal ul:first' )[positionFunction]( $li );
674 - $( 'body' ).prepend( $menu );
675 - $menu.hide();
676 - $li.click( function( event ) {
677 - var menuSide, menuOffset, distanceToEdge;
678 -
679 - if ( rtlEnv ) {
680 - distanceToEdge = $li.outerWidth() + $li.offset().left;
681 - if ( $menuItemsDiv.outerWidth() > distanceToEdge ) {
682 - menuSide = 'left';
683 - menuOffset = $li.offset().left;
684 - } else {
685 - menuSide = 'right';
686 - menuOffset = $(window).width() - distanceToEdge;
687 - }
688 - } else {
689 - distanceToEdge = $(window).width() - $li.offset().left;
690 - if ( $menuItemsDiv.outerWidth() > distanceToEdge ) {
691 - menuSide = 'right';
692 - menuOffset = distanceToEdge - $li.outerWidth();
693 - } else {
694 - menuSide = 'left';
695 - menuOffset = $li.offset().left;
696 - }
697 - }
698 -
699 - $menuItemsDiv.css( menuSide, menuOffset );
700 -
701 - if( $menu.hasClass( 'open' ) ){
702 - $menu.removeClass( 'open' );
703 - $menu.hide();
704 - } else {
705 - $( 'div.open' ).removeClass( 'open' );
706 - $menu.addClass( 'open' );
707 - $menu.show();
708 - event.stopPropagation();
709 - }
710 - } );
711 -
712 - $( 'html' ).click( function() {
713 - $menu.removeClass( 'open' );
714 - $menu.hide();
715 - } );
716 - $menu.click( function( event ) {
717 - event.stopPropagation();
718 - } );
719 -
720 - // Workaround for IE bug - activex components like input fields
721 - // coming on top of everything.
722 - // TODO: is there a better solution other than hiding it on hover?
723 - if ( $.browser.msie ) {
724 - $( '#narayam-menu' ).hover( function() {
725 - $( '#searchform' ).css( 'visibility', 'hidden' );
726 - }, function() {
727 - $( '#searchform' ).css( 'visibility', 'visible' );
728 - });
729 - }
730 - $('.narayam-scheme-dynamic-item').hide();
731 -
732 - // Narayam controls setup complete, returns true
733 - return true;
734 - };
735 -} )();
736 -
737 -} )( jQuery );
Index: trunk/extensions/Narayam/resources/ext.narayam.core-vector.css
@@ -1,6 +0,0 @@
2 -.narayam-wrapper {
3 - font-size: 80%;
4 - position: absolute;
5 - top: 1.4em;
6 - right: 0.5em;
7 -}
Index: trunk/extensions/Narayam/resources/ext.narayam.core/ext.narayam.core-vector.css
@@ -0,0 +1,6 @@
 2+.narayam-wrapper {
 3+ font-size: 80%;
 4+ position: absolute;
 5+ top: 1.4em;
 6+ right: 0.5em;
 7+}
Property changes on: trunk/extensions/Narayam/resources/ext.narayam.core/ext.narayam.core-vector.css
___________________________________________________________________
Added: svn:eol-style
18 + native
Index: trunk/extensions/Narayam/resources/ext.narayam.core/ext.narayam.core.css
@@ -0,0 +1,137 @@
 2+.narayam-input {
 3+ /* FIXME: needed to add !important because WikiEditor overrides border for #wpTextbox1
 4+ * and SimpleSearch overrides background-color for the search box. Talk to Trevor
 5+ * about styling this nicely
 6+ */
 7+ background-color: #EAF3F8 !important;
 8+}
 9+
 10+li#pt-narayam {
 11+ padding-left: 15px !important;
 12+}
 13+
 14+/* Variants and Actions */
 15+/* @noflip */
 16+div#narayam-menu {
 17+ direction: ltr;
 18+ float: left;
 19+ display: none;
 20+}
 21+
 22+div#narayam-menu.open {
 23+ display: block;
 24+}
 25+/* @noflip */
 26+body.rtl div#narayam-menu {
 27+ direction: rtl;
 28+}
 29+div#narayam-menu div.menu-items {
 30+ position: absolute;
 31+ display: block;
 32+ clear: both;
 33+ text-align: left;
 34+ z-index: 99999;
 35+ width: 200px;
 36+ top: 20px;
 37+ font-size: 0.8em;
 38+}
 39+
 40+div#narayam-menu-items li {
 41+ margin: 0;
 42+ padding: 5px;
 43+ font-size: 100%;
 44+ float: none;
 45+ z-index: 99999;
 46+
 47+}
 48+ul#imelist{
 49+ padding: 5px;
 50+}
 51+/* OVERRIDDEN BY COMPLIANT BROWSERS */
 52+/* @noflip */
 53+body.rtl div#narayam-menu div.menu-items {
 54+ margin-left: 24px;
 55+}
 56+/* IGNORED BY IE6 */
 57+/* @noflip */
 58+body.rtl div#narayam-menu > div.menu-items {
 59+ margin-left: auto;
 60+}
 61+/* IGNORED BY IE6 */
 62+/* Also fixes old versions of FireFox */
 63+/* @noflip */
 64+body.rtl div#narayam-menu > div.menu-items,
 65+x:-moz-any-link {
 66+ margin-left: 23px;
 67+}
 68+
 69+div#narayam-menu ul {
 70+ position: absolute;
 71+ background-color: white;
 72+ border: solid 1px silver;
 73+ -moz-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
 74+ -webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
 75+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
 76+ border-top-width: 0;
 77+ list-style: none;
 78+ list-style-image: none;
 79+ list-style-type: none;
 80+ padding: 10px; /* Space for scrollbars etc. */
 81+ margin: 0;
 82+ margin-left: -1px;
 83+ text-align: left;
 84+ max-height: 360px;
 85+ overflow-y: auto;
 86+ width: 100%;
 87+}
 88+
 89+div#narayam-menu li {
 90+ margin: 0;
 91+ text-align: left;
 92+ line-height: 1em;
 93+}
 94+
 95+div#narayam-menu li.selected a,
 96+div#narayam-menu li.selected a:visited {
 97+ color: #333333;
 98+ text-decoration: none;
 99+}
 100+div#narayam-menu a {
 101+ display: block;
 102+ padding-left: 10px;
 103+ padding-right: 10px;
 104+}
 105+
 106+div#narayam-menu-items li.narayam-help-link a {
 107+ /* @embed */
 108+ background: url('images/help.png') no-repeat scroll left center transparent;
 109+ padding-left: 20px;
 110+ line-height: 1.5em;
 111+}
 112+
 113+li#pt-narayam.narayam-active {
 114+ /* @embed */
 115+ background: url('images/narayam-active.png') no-repeat scroll left top transparent;
 116+}
 117+
 118+li#pt-narayam.narayam-inactive {
 119+ /* @embed */
 120+ background: url('images/narayam-inactive.png') no-repeat scroll left top transparent;
 121+}
 122+
 123+li.narayam-more-imes-link {
 124+ /* @embed */
 125+ background: url('images/closed-ltr.png') no-repeat scroll left center transparent;
 126+}
 127+
 128+li.narayam-more-imes-link.open {
 129+ /* @embed */
 130+ background: url('images/open.png') no-repeat scroll left center transparent;
 131+}
 132+li.narayam-more-imes-link a {
 133+ padding-left: 10px;
 134+}
 135+
 136+div#narayam-menu label:hover, div#narayam-menu input:hover {
 137+ cursor: pointer;
 138+}
Property changes on: trunk/extensions/Narayam/resources/ext.narayam.core/ext.narayam.core.css
___________________________________________________________________
Added: svn:eol-style
1139 + native
Index: trunk/extensions/Narayam/resources/ext.narayam.core/ext.narayam.core-monobook.css
@@ -0,0 +1,4 @@
 2+div#narayam-menu div.menu-items {
 3+ font-size: 1.2em;
 4+}
 5+
Property changes on: trunk/extensions/Narayam/resources/ext.narayam.core/ext.narayam.core-monobook.css
___________________________________________________________________
Added: svn:eol-style
16 + native
Index: trunk/extensions/Narayam/resources/ext.narayam.core/ext.narayam.core-modern.css
@@ -0,0 +1,42 @@
 2+#p-personal {
 3+ /* #p-personal has overflow:hidden. That makes a dropdown menu appearing hidden.
 4+ * overriding it this way may not be the best way.
 5+ */
 6+ overflow: visible !important;
 7+}
 8+
 9+li#pt-narayam {
 10+ margin-left: 5px;
 11+}
 12+
 13+div#narayam-menu div.menu-items {
 14+ top: 0px;
 15+ font-size: 1.2em;
 16+ position: relative;
 17+}
 18+
 19+div#narayam-menu ul {
 20+ min-width: 15em;
 21+ height: auto;
 22+}
 23+div#narayam-menu li {
 24+ background-color: #FFFFFF;
 25+ font-weight: normal;
 26+ white-space: nowrap;
 27+ text-transform: none;
 28+ font-variant: normal;
 29+}
 30+
 31+div#narayam-menu ul {
 32+ background-color: #FFFFFF;
 33+ border: solid 1px silver;
 34+ height: auto;
 35+}
 36+
 37+div#narayam-menu li a:hover {
 38+ color: #0645AD;
 39+}
 40+
 41+div#narayam-menu li:hover {
 42+ background-color: #FFFFFF;
 43+}
Property changes on: trunk/extensions/Narayam/resources/ext.narayam.core/ext.narayam.core-modern.css
___________________________________________________________________
Added: svn:eol-style
144 + native
Index: trunk/extensions/Narayam/resources/ext.narayam.core/ext.narayam.core.js
@@ -0,0 +1,736 @@
 2+/**
 3+ * Narayam
 4+ * Input field rewriter tool for web pages
 5+ * @author Junaid P V ([[user:Junaidpv]])(http://junaidpv.in)
 6+ * @date 2010-12-18 (Based on naaraayam transliteration tool I first wrote on 2010-05-19)
 7+ * @version 3.0
 8+ * Last update: 2010-11-28
 9+ * License: GPLv3
 10+ */
 11+
 12+/**
 13+ * NOTE: For documentation on writing schemes and rulesets, see the
 14+ * documentation for addScheme().
 15+ */
 16+
 17+( function( $ ) {
 18+$.narayam = new ( function() {
 19+ /* Private members */
 20+
 21+ // Reference to this object
 22+ var that = this;
 23+ // jQuery array holding all text inputs Narayam applies to
 24+ var $inputs = $( [] );
 25+ // Whether Narayam is enabled
 26+ var enabled = false;
 27+ // Registered schemes
 28+ var schemes = {};
 29+ // List of scheme names, ordered for presentation purposes
 30+ // Schemes not in this list won't be allowed to register
 31+ // This object is formatted as { 'schemename': '', 'schemename2': '', ... }
 32+ // for easy searching
 33+ var availableSchemes = mw.config.get( 'wgNarayamAvailableSchemes' ) || {};
 34+ // All input methods. This will be used for selecting input methods from languages
 35+ // other than uselang- optionally
 36+ var allImes = mw.config.get( 'wgNarayamAllSchemes' ) || {};
 37+ // Currently selected scheme
 38+ var currentScheme = null;
 39+ // Shortcut key for turning Narayam on and off
 40+ var shortcutKey = getShortCutKey();
 41+ // Number of recent input methods to be shown
 42+ var recentItemsLength = mw.config.get( 'wgNarayamRecentItemsLength' );
 43+
 44+ /* Private functions */
 45+
 46+ /**
 47+ * Transliterate a string using the current scheme
 48+ * @param str String to transliterate
 49+ * @param keyBuffer The key buffer
 50+ * @param useExtended Whether to use the extended part of the scheme
 51+ * @return Transliterated string, or str if no applicable transliteration found.
 52+ */
 53+ this.transliterate = function( str, keyBuffer, useExtended ) {
 54+ var rules = currentScheme.extended_keyboard && useExtended ?
 55+ currentScheme.rules_x : currentScheme.rules;
 56+ for ( var i = 0; i < rules.length; i++ ) {
 57+ var regex = new RegExp( rules[i][0] + '$' );
 58+ if ( regex.test( str ) // Input string match
 59+ &&
 60+ (
 61+ rules[i][1].length === 0 // Keybuffer match not required
 62+ ||
 63+ ( // Keybuffer match specified, so it should be met
 64+ rules[i][1].length > 0
 65+ && rules[i][1].length <= keyBuffer.length
 66+ && new RegExp( rules[i][1] + '$' ).test( keyBuffer )
 67+ )
 68+ )
 69+ ) {
 70+ return str.replace( regex, rules[i][2] );
 71+ }
 72+ }
 73+ // No matches, return the input
 74+ return str;
 75+ }
 76+
 77+ /**
 78+ * Get the n characters in str that immediately precede pos
 79+ * Example: lastNChars( "foobarbaz", 5, 2 ) == "ba"
 80+ * @param str String to search in
 81+ * @param pos Position in str
 82+ * @param n Number of characters to go back from pos
 83+ * @return Substring of str, at most n characters long, immediately preceding pos
 84+ */
 85+ this.lastNChars = function( str, pos, n ) {
 86+ if ( n === 0 ) {
 87+ return '';
 88+ } else if ( pos <= n ) {
 89+ return str.substr( 0, pos );
 90+ } else {
 91+ return str.substr( pos - n, n );
 92+ }
 93+ }
 94+
 95+ /**
 96+ * Find the point at which a and b diverge, i.e. the first position
 97+ * at which they don't have matching characters.
 98+ * @param a String
 99+ * @param b String
 100+ * @return Position at which a and b diverge, or -1 if a == b
 101+ */
 102+ this.firstDivergence = function( a, b ) {
 103+ var minLength = a.length < b.length ? a.length : b.length;
 104+ for ( var i = 0; i < minLength; i++ ) {
 105+ if ( a.charCodeAt( i ) !== b.charCodeAt( i ) ) {
 106+ return i;
 107+ }
 108+ }
 109+ return -1;
 110+ }
 111+
 112+ /**
 113+ * Check whether a keypress event corresponds to the shortcut key
 114+ * @param e Event object
 115+ * @return bool
 116+ */
 117+ function isShortcutKey( e ) {
 118+ return e.altKey == shortcutKey.altKey &&
 119+ e.ctrlKey == shortcutKey.ctrlKey &&
 120+ e.shiftKey == shortcutKey.shiftKey &&
 121+ String.fromCharCode( e.which ) == shortcutKey.key;
 122+ }
 123+
 124+ /**
 125+ * Get the shortcut key for the tool, depending on OS, browser
 126+ * @return shortcutKey
 127+ */
 128+ function getShortCutKey() {
 129+ var defaultShortcut = {
 130+ altKey: false,
 131+ ctrlKey: true,
 132+ shiftKey: false,
 133+ cmdKey: false,
 134+ key: 'M'
 135+ };
 136+ // Browser sniffing to determine the available shortcutKey
 137+ // Refer: mediawiki.util.js and en.wikipedia.org/wiki/Access_key
 138+ var profile = $.client.profile();
 139+ // Safari/Konqueror on any platform, but not Safari on Windows
 140+ // or any browser on Mac except chrome and opera
 141+ if ( !( profile.platform == 'win' && profile.name == 'safari' ) &&
 142+ ( profile.name == 'safari'|| profile.platform == 'mac' || profile.name == 'konqueror' )
 143+ && !( profile.name == 'opera' || profile.name == 'chrome' ) ) {
 144+ defaultShortcut.key = 'G';
 145+ }
 146+ // For Opera in OSX, shortcut is control+command+m.
 147+ if ( profile.name == 'opera' && profile.platform == 'mac' ) {
 148+ defaultShortcut.cmdKey = true;
 149+ }
 150+ return defaultShortcut;
 151+ }
 152+
 153+ /**
 154+ * Get a description of the shortcut key, e.g. "Ctrl-M"
 155+ * @return string
 156+ */
 157+ function shortcutText() {
 158+ var text = '';
 159+ // TODO: Localize these things (in core, too)
 160+ if ( shortcutKey.ctrlKey ) {
 161+ text += 'Ctrl-';
 162+ }
 163+ if ( shortcutKey.shiftKey ) {
 164+ text += 'Shift-';
 165+ }
 166+ if ( shortcutKey.altKey ) {
 167+ text += 'Alt-';
 168+ }
 169+ if ( shortcutKey.cmdKey ) {
 170+ text += 'Command-';
 171+ }
 172+ text += shortcutKey.key.toUpperCase();
 173+ return text;
 174+ }
 175+
 176+ /**
 177+ * Change visual appearance of element (text input, textarea) according
 178+ * to the current state of Narayam
 179+ */
 180+ function changeVisual( $element ) {
 181+ if ( enabled ) {
 182+ $element.addClass( 'narayam-input' );
 183+ } else {
 184+ $element.removeClass( 'narayam-input' );
 185+ }
 186+ }
 187+
 188+ /**
 189+ * Replace text part from startPos to endPos with peri
 190+ * This function is specifically for webkit browsers,
 191+ * because of bug: https://bugs.webkit.org/show_bug.cgi?id=66630
 192+ * TODO: remove when webkit bug is handled in jQuery.textSelection.js
 193+ *
 194+ * @param $element jQuery object to wich replacement to be taked place
 195+ * @param startPos Starting position of text range to be replaced
 196+ * @param endPos Ending position of text range to be replaced
 197+ * @param peri String to be substituted
 198+ */
 199+ function replaceString( $element, startPos, endPos, peri ) {
 200+ // Take entire text of the element
 201+ var text = $element.val();
 202+ var pre = text.substring( 0, startPos );
 203+ var post = text.substring( endPos, text.length );
 204+
 205+ // Then replace
 206+ $element.val( pre + peri + post );
 207+ }
 208+
 209+ /**
 210+ * Keydown event handler. Handles shortcut key presses
 211+ * @param e Event object
 212+ */
 213+ function onkeydown( e ) {
 214+ // If the current scheme uses the alt key, ignore keydown for Alt+? combinations
 215+ if ( enabled && currentScheme.extended_keyboard && e.altKey && !e.ctrlKey ) {
 216+ e.stopPropagation();
 217+ return false; // Not in original code -- does this belong here?
 218+ } else if ( isShortcutKey( e ) ) {
 219+ that.toggle();
 220+ changeVisual( $( this ) );
 221+ e.stopPropagation();
 222+ return false;
 223+ }
 224+ return true;
 225+ }
 226+
 227+ /**
 228+ * Keypress event handler. This is where the real work happens
 229+ * @param e Event object
 230+ */
 231+ function onkeypress( e ) {
 232+ if ( !enabled ) {
 233+ return true;
 234+ }
 235+
 236+ if ( e.which == 8 ) { // Backspace
 237+ // Blank the keybuffer
 238+ $( this ).data( 'narayamKeyBuffer', '' );
 239+ return true;
 240+ }
 241+
 242+ // Leave ASCII control characters alone, as well as anything involving
 243+ // Alt (except for extended keymaps), Ctrl and Meta
 244+ if ( e.which < 32 || ( e.altKey && !currentScheme.extended_keyboard ) || e.ctrlKey || e.metaKey ) {
 245+ return true;
 246+ }
 247+
 248+ var $this = $( this );
 249+ var c = String.fromCharCode( e.which );
 250+ // Get the current caret position. The user may have selected text to overwrite,
 251+ // so get both the start and end position of the selection. If there is no selection,
 252+ // startPos and endPos will be equal.
 253+ var pos = $this.textSelection( 'getCaretPosition', { 'startAndEnd': true } );
 254+ var startPos = pos[0];
 255+ var endPos = pos[1];
 256+ // Get the last few characters before the one the user just typed,
 257+ // to provide context for the transliteration regexes.
 258+ // We need to append c because it hasn't been added to $this.val() yet
 259+ var input = that.lastNChars( $this.val(), startPos, currentScheme.lookbackLength ) + c;
 260+ var keyBuffer = $this.data( 'narayamKeyBuffer' );
 261+ var replacement = that.transliterate( input, keyBuffer, e.altKey );
 262+
 263+ // Update the key buffer
 264+ keyBuffer += c;
 265+ if ( keyBuffer.length > currentScheme.keyBufferLength ) {
 266+ // The buffer is longer than needed, truncate it at the front
 267+ keyBuffer = keyBuffer.substring( keyBuffer.length - currentScheme.keyBufferLength );
 268+ }
 269+ $this.data( 'narayamKeyBuffer', keyBuffer );
 270+
 271+ // textSelection() magic is expensive, so we avoid it as much as we can
 272+ if ( replacement == input ) {
 273+ return true;
 274+ }
 275+ // Drop a common prefix, if any
 276+ // TODO: Profile this, see if it's any faster
 277+ var divergingPos = that.firstDivergence( input, replacement );
 278+ input = input.substring( divergingPos );
 279+ replacement = replacement.substring( divergingPos );
 280+
 281+ $this.textSelection( 'encapsulateSelection', {
 282+ peri: replacement,
 283+ replace: true,
 284+ selectPeri: false,
 285+ selectionStart: startPos - input.length + 1,
 286+ selectionEnd: endPos
 287+ } );
 288+
 289+ e.stopPropagation();
 290+ return false;
 291+ }
 292+
 293+ /**
 294+ * Focus event handler.
 295+ * @param e Event object
 296+ */
 297+ function onfocus( e ) {
 298+ if ( !$( this ).data( 'narayamKeyBuffer' ) ) {
 299+ // First-time focus on the input field
 300+ // So, initialise a key buffer for it
 301+ $( this ).data( 'narayamKeyBuffer', '' );
 302+ }
 303+ changeVisual( $( this ) );
 304+ }
 305+
 306+ /**
 307+ * Blur event handler.
 308+ * @param e Event object
 309+ */
 310+ function onblur( e ) {
 311+ $( this ).removeClass( 'narayam-input' );
 312+ }
 313+
 314+
 315+ /* Public functions */
 316+
 317+ /**
 318+ * Add more inputs to apply Narayam to
 319+ * @param inputs A jQuery object holding one or more input or textarea elements,
 320+ * or an array of DOM elements, or a single DOM element, or a selector
 321+ */
 322+ this.addInputs = function( inputs ) {
 323+ if ( typeof( inputs ) === "string" ) {
 324+ // If a string is passed, it is a CSS selector
 325+ // We can use jQuery's .live() instead of .bind()
 326+ // So Narayam can work on elements added later to DOM too
 327+ $( inputs )
 328+ .live( 'keydown', onkeydown )
 329+ .live( 'keypress', onkeypress )
 330+ .live( 'focus', onfocus )
 331+ .live( 'blur', onblur );
 332+ } else {
 333+ var $newInputs = $( inputs );
 334+ $inputs = $inputs.add( $newInputs );
 335+ $newInputs
 336+ .bind( 'keydown.narayam', onkeydown )
 337+ .bind( 'keypress.narayam', onkeypress )
 338+ .bind( 'focus', onfocus )
 339+ .bind( 'blur', onblur );
 340+ }
 341+ };
 342+
 343+ /**
 344+ * Enable Narayam
 345+ */
 346+ this.enable = function() {
 347+ if ( !enabled ) {
 348+ $.cookie( 'narayam-enabled', '1', { path: '/', expires: 30 } );
 349+ $( '#narayam-toggle' ).prop( 'checked', true );
 350+ $( 'li#pt-narayam' )
 351+ .removeClass( 'narayam-inactive' )
 352+ .addClass( 'narayam-active' );
 353+ enabled = true;
 354+ }
 355+ };
 356+
 357+ /**
 358+ * Disable Narayam
 359+ */
 360+ this.disable = function() {
 361+ if ( enabled ) {
 362+ $.cookie( 'narayam-enabled', '0', { path: '/', expires: 30 } );
 363+ $( '#narayam-toggle' ).prop( 'checked', false );
 364+ $( 'li#pt-narayam' )
 365+ .removeClass( 'narayam-active' )
 366+ .addClass( 'narayam-inactive' );
 367+ enabled = false;
 368+ }
 369+ };
 370+
 371+ /**
 372+ * Toggle the enabled/disabled state
 373+ */
 374+ this.toggle = function() {
 375+ if ( enabled ) {
 376+ that.disable();
 377+ } else {
 378+ that.enable();
 379+ }
 380+ };
 381+
 382+ this.enabled = function() {
 383+ return enabled;
 384+ };
 385+
 386+ /**
 387+ * Add a transliteration scheme. Schemes whose name is not in
 388+ * wgNarayamAvailableSchemes will be ignored.
 389+ *
 390+ * A scheme consists of rules used for transliteration. A rule is an
 391+ * array of three strings. The first string is a regex that is matched
 392+ * against the input string (the last few characters before the cursor
 393+ * followed by the character the user entered), the second string is a
 394+ * regex that is matched against the end of the key buffer (the last
 395+ * few keys the user pressed), and the third string is the replacement
 396+ * string (may contain placeholders like $1 for subexpressions). You do
 397+ * not need to add $ to the end of either of the regexes so they match
 398+ * at the end, this is done automagically.
 399+ *
 400+ * The transliteration algorithm processes the rules in the order they
 401+ * are specified, and applies the first rule that matches. For a rule
 402+ * to match, both the first and second regex have to match (the first
 403+ * for the input, the second for the key buffer). Most rules do not use
 404+ * the keybuffer and specify an empty string as the second regex.
 405+ *
 406+ * The scheme data object must have the following keys:
 407+ * namemsg: Message key for the name of the scheme
 408+ * extended_keyboard: Whether this scheme has an extended ruleset (bool)
 409+ * lookbackLength: Number of characters before the cursor to include
 410+ * when matching the first regex of each rule. This is
 411+ * usually the maximum number of characters a rule
 412+ * regex can match minus one.
 413+ * keyBufferLength: Length of the key buffer. May be zero if not needed
 414+ * rules: Array of rules, which themselves are arrays of three strings.
 415+ * rules_x: Extended ruleset. This is used instead of the normal
 416+ * ruleset when Alt is held. This key is only required if
 417+ * extended_keyboard is true
 418+ *
 419+ * NOTE: All keys are REQUIRED (except rules_x when not used). Missing
 420+ * keys may result in JS errors.
 421+ *
 422+ * @param name Name of the scheme, must be unique
 423+ * @param data Object with scheme data.
 424+ * @return True if added, false if not
 425+ */
 426+ this.addScheme = function( name, data ) {
 427+ schemes[name] = data;
 428+ return true;
 429+ };
 430+
 431+ /**
 432+ * Get the transliteration rules for the given input method name.
 433+ * @param name String
 434+ */
 435+ this.getScheme = function( name ) {
 436+ return schemes[name];
 437+ };
 438+
 439+ /**
 440+ * Change the current transliteration scheme
 441+ * @param name String
 442+ */
 443+ this.setScheme = function( name ) {
 444+ var recent = $.cookie( 'narayam-scheme' ) || [];
 445+ if ( typeof recent === "string" ) {
 446+ recent = recent.split( "," );
 447+ }
 448+ recent = $.grep( recent, function( value ) {
 449+ return value != name;
 450+ } );
 451+ recent.unshift( name );
 452+ recent = recent.slice( 0, recentItemsLength );
 453+ recent = recent.join( "," );
 454+ $.cookie( 'narayam-scheme', recent, { path: '/', expires: 30 } );
 455+ if ( name in schemes ) {
 456+ currentScheme = schemes[name];
 457+ } else {
 458+ // load the rules dynamically.
 459+ mw.loader.using( "ext.narayam.rules." + name, function() {
 460+ currentScheme = schemes[name];
 461+ } );
 462+ }
 463+ return true;
 464+ };
 465+
 466+ /**
 467+ * Set up Narayam. This adds the scheme dropdown, binds the handlers
 468+ * and initializes the enabled/disabled state and selected scheme
 469+ * from a cookie or wgNarayamEnabledByDefault
 470+ */
 471+ this.setup = function() {
 472+ that.buildMenu();
 473+ // Restore state from cookies
 474+ var recent = $.cookie( 'narayam-scheme' );
 475+ var lastScheme = null;
 476+ if ( typeof recent === "string" ) {
 477+ lastScheme = recent.split( "," )[0];
 478+ }
 479+ if ( lastScheme ) {
 480+ that.setScheme( lastScheme );
 481+ $( '#narayam-' + lastScheme ).prop( 'checked', true );
 482+ } else {
 483+ //if no saved input scheme, select the first.
 484+ var $firstScheme = $( 'input.narayam-scheme:first' );
 485+ that.setScheme( $firstScheme.val() );
 486+ $firstScheme.prop( 'checked', true );
 487+
 488+ }
 489+ var enabledCookie = $.cookie( 'narayam-enabled' );
 490+ if ( enabledCookie == '1' || ( mw.config.get( 'wgNarayamEnabledByDefault' ) && enabledCookie !== '0' ) ) {
 491+ that.enable();
 492+ } else {
 493+ $( 'li#pt-narayam' ).addClass( 'narayam-inactive' );
 494+ }
 495+ // Renew the narayam-enabled cookie. narayam-scheme is renewed by setScheme()
 496+ if ( enabledCookie ) {
 497+ $.cookie( 'narayam-enabled', enabledCookie, { path: '/', expires: 30 } );
 498+ }
 499+
 500+ };
 501+ /**
 502+ * Construct the menu item, for the given scheme name.
 503+ */
 504+ this.buildMenuItem = function( scheme ) {
 505+ var $input = $( '<input type="radio" name="narayam-input-method" class="narayam-scheme" />' );
 506+ $input.attr( 'id', 'narayam-' + scheme ).val( scheme );
 507+
 508+ var $narayamMenuItemLabel = $( '<label>' )
 509+ .attr( 'for' ,'narayam-' + scheme )
 510+ .append( $input )
 511+ .append( mw.message( 'narayam-' + scheme ).escaped() );
 512+
 513+ var $narayamMenuItem = $( '<li>' )
 514+ .append( $input )
 515+ .append( $narayamMenuItemLabel );
 516+
 517+ return $narayamMenuItem;
 518+ };
 519+
 520+ /**
 521+ * prepare the menu list for all the input methods.
 522+ * @return The div containing the constructed menu.
 523+ */
 524+ this.buildMenuItems = function() {
 525+ var haveSchemes = false;
 526+ // Build schemes option list
 527+ var $narayamMenuItems = $( '<ul>' );
 528+ var count = 1;
 529+ var seen = [];
 530+
 531+ var recent = $.cookie( "narayam-scheme" ) || [];
 532+ if ( typeof recent === "string" ) {
 533+ recent = recent.split( "," );
 534+ }
 535+
 536+ // Prepare the recent inputmethods menu items
 537+ for ( var i = 0; i < recent.length; i++ ) {
 538+ var scheme = recent[i];
 539+ if ( $.inArray( scheme, seen ) > -1 ) { continue; }
 540+ seen.push( scheme );
 541+ if ( count++ > recentItemsLength ) { break; }
 542+ var $narayamMenuItem = that.buildMenuItem( scheme );
 543+ $narayamMenuItem.addClass( 'narayam-recent-menu-item' );
 544+ $narayamMenuItems.append( $narayamMenuItem );
 545+ }
 546+
 547+ // menu items for the language of wiki.
 548+ var requested = [mw.config.get( 'wgUserVariant' ), mw.config.get( 'wgContentLanguage' ), mw.config.get( 'wgUserLanguage' )];
 549+ $( 'textarea[lang]' ).each( function( index ) {
 550+ requested.push( this.lang );
 551+ });
 552+ for ( var i = 0; i < requested.length; i++ ) {
 553+ var lang = requested[i];
 554+ var langschemes = allImes[lang];
 555+ if ( !langschemes ) continue;
 556+ for ( var scheme in langschemes ) {
 557+ haveSchemes = true;
 558+ if ( $.inArray( scheme, seen ) !== -1 ) { continue; }
 559+ seen.push( scheme );
 560+ var $narayamMenuItem = that.buildMenuItem( scheme );
 561+ $narayamMenuItems.append( $narayamMenuItem );
 562+ }
 563+ }
 564+
 565+ if ( !haveSchemes ) {
 566+ // No schemes available, don't show the tool
 567+ return null;
 568+ }
 569+
 570+ // Build enable/disable checkbox and label
 571+ var $checkbox = $( '<input type="checkbox" id="narayam-toggle" />' );
 572+ $checkbox
 573+ .attr( 'title', mw.msg( 'narayam-checkbox-tooltip' ) )
 574+ .click( that.toggle );
 575+
 576+ var $label = $( '<label>' ).attr( 'for', 'narayam-toggle' );
 577+ $label
 578+ .text( mw.msg( 'narayam-toggle-ime', shortcutText() ) )
 579+ .prepend( $checkbox )
 580+ .prop( 'title', mw.msg( 'narayam-checkbox-tooltip' ) );
 581+
 582+ var $moreLink = $( '<a>' )
 583+ .text( mw.msg( 'narayam-more-imes' ) )
 584+ .prop( 'href', '#' )
 585+ .click( function( event ) {
 586+ $('.narayam-scheme-dynamic-item').toggle( 'fast' );
 587+ if ( $('li.narayam-more-imes-link').hasClass( 'open' ) ) {
 588+ $('li.narayam-more-imes-link').removeClass( 'open' );
 589+ } else {
 590+ $('li.narayam-more-imes-link').addClass( 'open' );
 591+ }
 592+ event.stopPropagation();
 593+ } );
 594+
 595+ $narayamMenuItems.append( $( '<li>' )
 596+ .addClass( 'narayam-more-imes-link' )
 597+ .append( $moreLink )
 598+ );
 599+
 600+ for ( var lang in allImes ) {
 601+ var langschemes = allImes[lang];
 602+ for ( var langscheme in langschemes ) {
 603+ // Do not repeat the input methods in more input methods section.
 604+ // If already shown on recent items.
 605+ if ( $.inArray( langscheme, seen ) > -1 ) { continue; }
 606+
 607+ var $narayamMenuItem = that.buildMenuItem( langscheme );
 608+ $narayamMenuItem.addClass( 'narayam-scheme-dynamic-item' );
 609+ $narayamMenuItems.append( $narayamMenuItem );
 610+ }
 611+ }
 612+
 613+ // Event listener for scheme selection - dynamic loading of rules.
 614+ $narayamMenuItems.delegate( 'input:radio', 'click', function( ) {
 615+ that.setScheme( $( this ).val() );
 616+ if ( $( this ).parent().hasClass( 'narayam-scheme-dynamic-item' ) ){
 617+ // rebuild the menu items with recent items.
 618+ $( '#narayam-menu' ).html( $.narayam.buildMenuItems() );
 619+ $( '#narayam-menu-items' ).css( 'left', $( 'li#pt-narayam' ).offset().left );
 620+ $( '#narayam-' + $( this ).val() ).prop( 'checked', true );
 621+ if ( enabled ) {
 622+ $( '#narayam-toggle' ).prop( 'checked', true );
 623+ }
 624+ }
 625+ } );
 626+
 627+ var helppage = mw.config.get( 'wgNarayamHelpPage' );
 628+ if ( helppage ) {
 629+ var $link = $( '<a>' )
 630+ .text( mw.msg( 'narayam-help' ) )
 631+ .prop( 'href', helppage )
 632+ .prop( 'target', '_blank' );
 633+ var $li = $( '<li>' ).addClass( 'narayam-help-link' );
 634+ $narayamMenuItems.append( $li.append( $link ) );
 635+ }
 636+
 637+ $narayamMenuItems.prepend( $( '<li>' ).append( $label ) );
 638+
 639+ return $( '<div>' )
 640+ .attr( 'id', 'narayam-menu-items' )
 641+ .addClass( 'menu-items' )
 642+ .append( $narayamMenuItems );
 643+ }
 644+
 645+
 646+ /**
 647+ * Construct the menu for Narayam
 648+ */
 649+ this.buildMenu = function() {
 650+ // Remove the menu if already exists
 651+ if( $( 'li#pt-webfont' ).length > 0 ) {
 652+ $( 'li#pt-narayam' ).remove();
 653+ $( 'div#narayam-menu' ).remove();
 654+ }
 655+ var $menuItemsDiv = that.buildMenuItems();
 656+ if( $menuItemsDiv == null ) {
 657+ return;
 658+ }
 659+ var $menu = $( '<div>' )
 660+ .attr( 'id', 'narayam-menu' )
 661+ .addClass( 'narayam-menu' );
 662+ var $link = $( '<a>' )
 663+ .prop( 'href', '#' )
 664+ .text( mw.msg( 'narayam-menu' ) )
 665+ .attr( 'title', mw.msg( 'narayam-menu-tooltip' ) );
 666+
 667+ $menu.append( $menuItemsDiv );
 668+ var $li = $( '<li>' ).attr( 'id', 'pt-narayam' ).append( $link );
 669+
 670+ // If rtl, add to the right of top personal links. Else, to the left
 671+ var rtlEnv = $( 'body' ).hasClass( 'rtl' );
 672+ var positionFunction = rtlEnv ? "append" : "prepend";
 673+ $( '#p-personal ul:first' )[positionFunction]( $li );
 674+ $( 'body' ).prepend( $menu );
 675+ $menu.hide();
 676+ $li.click( function( event ) {
 677+ var menuSide, menuOffset, distanceToEdge;
 678+
 679+ if ( rtlEnv ) {
 680+ distanceToEdge = $li.outerWidth() + $li.offset().left;
 681+ if ( $menuItemsDiv.outerWidth() > distanceToEdge ) {
 682+ menuSide = 'left';
 683+ menuOffset = $li.offset().left;
 684+ } else {
 685+ menuSide = 'right';
 686+ menuOffset = $(window).width() - distanceToEdge;
 687+ }
 688+ } else {
 689+ distanceToEdge = $(window).width() - $li.offset().left;
 690+ if ( $menuItemsDiv.outerWidth() > distanceToEdge ) {
 691+ menuSide = 'right';
 692+ menuOffset = distanceToEdge - $li.outerWidth();
 693+ } else {
 694+ menuSide = 'left';
 695+ menuOffset = $li.offset().left;
 696+ }
 697+ }
 698+
 699+ $menuItemsDiv.css( menuSide, menuOffset );
 700+
 701+ if( $menu.hasClass( 'open' ) ){
 702+ $menu.removeClass( 'open' );
 703+ $menu.hide();
 704+ } else {
 705+ $( 'div.open' ).removeClass( 'open' );
 706+ $menu.addClass( 'open' );
 707+ $menu.show();
 708+ event.stopPropagation();
 709+ }
 710+ } );
 711+
 712+ $( 'html' ).click( function() {
 713+ $menu.removeClass( 'open' );
 714+ $menu.hide();
 715+ } );
 716+ $menu.click( function( event ) {
 717+ event.stopPropagation();
 718+ } );
 719+
 720+ // Workaround for IE bug - activex components like input fields
 721+ // coming on top of everything.
 722+ // TODO: is there a better solution other than hiding it on hover?
 723+ if ( $.browser.msie ) {
 724+ $( '#narayam-menu' ).hover( function() {
 725+ $( '#searchform' ).css( 'visibility', 'hidden' );
 726+ }, function() {
 727+ $( '#searchform' ).css( 'visibility', 'visible' );
 728+ });
 729+ }
 730+ $('.narayam-scheme-dynamic-item').hide();
 731+
 732+ // Narayam controls setup complete, returns true
 733+ return true;
 734+ };
 735+} )();
 736+
 737+} )( jQuery );
Property changes on: trunk/extensions/Narayam/resources/ext.narayam.core/ext.narayam.core.js
___________________________________________________________________
Added: svn:eol-style
1738 + native
Index: trunk/extensions/Narayam/Narayam.php
@@ -188,12 +188,12 @@
189189 'dependencies' => 'ext.narayam.core',
190190 );
191191 $wgResourceModules['ext.narayam.core'] = $narayamTpl + array(
192 - 'scripts' => 'resources/ext.narayam.core.js',
193 - 'styles' => 'resources/ext.narayam.core.css',
 192+ 'scripts' => 'resources/ext.narayam.core/ext.narayam.core.js',
 193+ 'styles' => 'resources/ext.narayam.core/ext.narayam.core.css',
194194 'skinStyles' => array(
195 - 'monobook' => 'resources/ext.narayam.core-monobook.css',
196 - 'vector' => 'resources/ext.narayam.core-vector.css',
197 - 'modern' => 'resources/ext.narayam.core-modern.css',
 195+ 'monobook' => 'resources/ext.narayam.core/ext.narayam.core-monobook.css',
 196+ 'vector' => 'resources/ext.narayam.core/ext.narayam.core-vector.css',
 197+ 'modern' => 'resources/ext.narayam.core/ext.narayam.core-modern.css',
198198 ),
199199 'messages' => array(
200200 'narayam-checkbox-tooltip',

Follow-up revisions

RevisionCommit summaryAuthorDate
r111148Fix th eimage locations broken in r111039santhosh06:08, 10 February 2012

Comments

#Comment by Nikerabbit (talk | contribs)   07:46, 10 February 2012

I would have moved the rules instead.

Status & tagging log