/*! * ULS - jQuery IME integration * * Copyright (C) 2012 Alolita Sharma, Amir Aharoni, Arun Ganesh, Brandon Harris, * Niklas Laxström, Pau Giner, Santhosh Thottingal, Siebrand Mazeland and other * contributors. See CREDITS for a list. * * UniversalLanguageSelector is dual licensed GPLv2 or later and MIT. You don't * have to do anything special to choose one license or the other and you don't * have to notify anyone which license you are using. You are free to use * UniversalLanguageSelector in commercial projects as long as the copyright * header is left intact. See files GPL-LICENSE and MIT-LICENSE for details. * * @file * @ingroup Extensions * @licence GNU General Public Licence 2.0 or later * @licence MIT License */ ( function () { 'use strict'; var mwImeRulesPath, inputSelector, inputPreferences, ulsIMEPreferences, customHelpLink; mwImeRulesPath = mw.config.get( 'wgExtensionAssetsPath' ) + '/UniversalLanguageSelector/lib/jquery.ime/'; inputSelector = 'input:not([type]), input[type=text], input[type=search], textarea, [contenteditable]'; inputPreferences = mw.uls.preferences(); mw.ime = mw.ime || {}; mw.ime.getLanguagesWithIME = function () { var language, ulsLanguages = mw.config.get( 'wgULSLanguages' ) || {}, availableLanguages = {}; for ( language in $.ime.languages ) { availableLanguages[ language ] = ulsLanguages[ language ] || $.uls.data.getAutonym( language ); } return availableLanguages; }; mw.ime.getIMELanguageList = function () { var unique = [], imeLanguageList, previousIMELanguages; previousIMELanguages = $.ime.preferences.getPreviousLanguages() || []; imeLanguageList = previousIMELanguages.concat( mw.uls.getFrequentLanguageList() ); imeLanguageList.forEach( function ( lang ) { if ( unique.indexOf( lang ) === -1 ) { unique.push( lang ); } } ); return unique.slice( 0, 6 ); }; ulsIMEPreferences = { save: function ( callback ) { if ( !this.registry.isDirty ) { if ( callback ) { callback.call( this, true ); } return; } // we don't want to save isDirty field. this.registry.isDirty = undefined; // get updated copy of preferences inputPreferences = mw.uls.preferences(); inputPreferences.set( 'ime', this.registry ); inputPreferences.save( callback ); // reset the dirty bit this.registry.isDirty = false; }, load: function () { this.registry = inputPreferences.get( 'ime' ) || this.registry; }, disable: function () { this.registry.isDirty = true; this.registry.enable = false; }, enable: function () { this.registry.isDirty = true; this.registry.enable = true; }, isEnabled: function () { if ( this.registry.enable === undefined ) { return mw.config.get( 'wgULSIMEEnabled' ); } else { return this.registry.enable; } }, getDefaultLanguage: function () { return mw.config.get( 'wgContentLanguage' ); } }; function imeNotification() { var notificationMsg = ( mw.config.get( 'wgULSPosition' ) === 'personal' ) ? 'ext-uls-input-disable-notification-info-personal' : 'ext-uls-input-disable-notification-info-interlanguage', $notification = $( '
' ) .addClass( 'uls-ime-notification-bubble' ) .append( $( '
' ) .attr( 'data-i18n', 'ext-uls-input-disable-notification' ), $( '
' ) .addClass( 'link' ) .attr( 'data-i18n', 'ext-uls-input-disable-notification-undo' ) .on( 'click', function () { $.ime.preferences.enable(); $.ime.preferences.save( function () { mw.ime.setup(); } ); } ), $( '
' ).attr( 'data-i18n', notificationMsg ) ); mw.notify( $notification.i18n() ); } // Add a 'more settings' link that takes to input settings of ULS customHelpLink = function () { var $disableInputToolsLink, $moreSettingsLink, imeselector = this; $disableInputToolsLink = $( '' ) .addClass( 'uls-ime-disable-link' ) .attr( 'data-i18n', 'ext-uls-input-disable' ); $moreSettingsLink = $( '' ) .addClass( 'uls-ime-more-settings-link' ); // Apparently we depend on some styles which are loaded with // these modules. This needs refactoring. mw.loader.using( mw.uls.languageSettingsModules, function () { $moreSettingsLink.languagesettings( { defaultModule: 'input', onClose: function () { // on close of input settings, keep focus in input area. imeselector.$element.trigger( 'focus' ); }, top: imeselector.$element.offset().top } ); } ); // Hide the menu. $moreSettingsLink.on( 'click', function ( e ) { imeselector.hide(); e.stopPropagation(); } ); $disableInputToolsLink.i18n(); $disableInputToolsLink.on( 'click', function ( e ) { $.ime.preferences.disable(); imeselector.hide(); imeselector.$imeSetting.hide(); $.ime.preferences.save( function () { mw.ime.disable(); imeNotification(); mw.hook( 'mw.uls.ime.disable' ).fire( 'menu' ); } ); e.stopPropagation(); } ); // If the webfonts are loaded, apply webfonts to the selector if ( $.fn.webfonts ) { imeselector.$menu.webfonts(); } return $( '
' ) .addClass( 'uls-ime-menu-settings-item' ) .append( $disableInputToolsLink, $moreSettingsLink ); }; mw.ime.disable = function () { $( inputSelector ).trigger( 'destroy.ime' ); }; mw.ime.init = function () { if ( !$.ime ) { // jquery.ime not loaded yet. return; } if ( $.ime.preferences.isEnabled ) { // mw.ime already initialized. return; } // Extend the ime preference system $.extend( $.ime.preferences, ulsIMEPreferences ); // MediaWiki specific overrides for jquery.ime $.extend( $.ime.defaults, { imePath: mwImeRulesPath } ); // Load the ime preferences $.ime.preferences.load(); $.fn.imeselector.Constructor.prototype.helpLink = customHelpLink; // Override the autonym function for the case that // somebody tries to select a language for which there are // no input methods, which is possible in MediaWiki $.fn.imeselector.Constructor.prototype.getAutonym = function ( languageCode ) { return $.uls.data.getAutonym( languageCode ); }; }; /** * Binds the event listeners. */ mw.ime.setup = function () { var imeSelectors = mw.config.get( 'wgULSImeSelectors' ).join( ', ' ); mw.ime.init(); $( 'body' ).on( 'focus.ime', imeSelectors, function () { mw.ime.handleFocus( $( this ) ); } ); }; /** * Loads necessary dependencies, checks input for validity and * adds the ime menu for elements that should have it. * * @param {jquery.Element} $input * @since 2013.11 */ mw.ime.handleFocus = function ( $input ) { var noImeSelectors; if ( $input.is( '.noime' ) || $input.data( 'ime' ) ) { // input does not need IME or already applied return; } noImeSelectors = mw.config.get( 'wgULSNoImeSelectors' ).join( ', ' ); if ( noImeSelectors.length && $input.is( noImeSelectors ) ) { $input.addClass( 'noime' ); return; } if ( !$.ime.preferences.isEnabled() ) { return; } if ( $input.is( '[contenteditable]' ) && !window.rangy ) { // For supporting content editable divs we need rangy library mw.loader.using( 'rangy.core', function () { mw.ime.addIme( $input ); } ); return; } mw.ime.addIme( $input ); }; /** * Just adds ime menu to any input element. * * @param {jquery.Element} $input * @since 2013.11 */ mw.ime.addIme = function ( $input ) { var imeselector; $input.ime( { languages: mw.ime.getIMELanguageList(), languageSelector: function () { var $ulsTrigger; $ulsTrigger = $( '' ).text( '...' ) .addClass( 'ime-selector-more-languages selectable-row selectable-row-item' ) .attr( { title: $.i18n( 'ext-uls-input-settings-more-languages-tooltip' ) } ); $ulsTrigger.uls( { onSelect: function ( language ) { $input.data( 'imeselector' ).selectLanguage( language ); $input.trigger( 'focus' ); }, languages: mw.ime.getLanguagesWithIME(), ulsPurpose: 'ime-selector', top: $input.offset().top } ); return $ulsTrigger; }, helpHandler: function ( ime ) { return $( '' ) .attr( { href: mw.msg( 'uls-ime-helppage', ime ), target: '_blank', title: $.i18n( 'ext-uls-ime-help' ) } ) .addClass( 'ime-perime-help' ) .on( 'click', function ( event ) { event.stopPropagation(); } ); } } ); // Some fields may be uninitialized imeselector = $input.data( 'imeselector' ); if ( imeselector ) { imeselector.selectLanguage( imeselector.decideLanguage() ); imeselector.$element.on( 'setim.ime', function ( event, inputMethod ) { mw.hook( 'mw.uls.ime.change' ).fire( inputMethod ); } ); } }; }() );