Input method integration with ULS

The file ext.uls.settingspanel.js is a draft for common
code in the different settings panels.

Change-Id: I057274f16b27b2c18d43d41c1d43f485a18ef0bf
This commit is contained in:
Santhosh Thottingal
2012-10-18 16:27:25 +05:30
parent 90de05cb97
commit f13e474e43
67 changed files with 8867 additions and 22 deletions

102
resources/js/ext.uls.ime.js Normal file
View File

@@ -0,0 +1,102 @@
/**
* ULS-Webfonts 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 ( $, mw, document, undefined ) {
'use strict';
var mwImeRulesPath, inputSelector, inputPreferences;
mwImeRulesPath = mw.config.get( 'wgExtensionAssetsPath' )
+ '/UniversalLanguageSelector/lib/jquery.ime/';
inputSelector = 'input:not([type]), input[type=text], input[type=search], textarea';
inputPreferences = mw.uls.preferences();
function getLanguagesWithIME () {
var language,
availableLanguages = {};
for ( language in $.ime.languages ) {
availableLanguages[language] = mw.config.get( 'wgULSLanguages' )[language];
}
return availableLanguages;
}
function getIMELanguageList () {
var unique = [],
imeLanguageList,
previousIMELanguages;
previousIMELanguages = $.ime.preferences.getPreviousLanguages() || [];
imeLanguageList = previousIMELanguages.concat( mw.uls.getFrequentLanguageList() );
$.each( imeLanguageList, function ( i, v ) {
if ( $.inArray( v, unique ) === -1 ) {
unique.push( v );
}
} );
return unique.slice( 0, 6 );
}
$( document ).ready( function () {
// MediaWiki specific overrides for jquery.webfonts
$.extend( $.ime.defaults, {
imePath: mwImeRulesPath
} );
$( 'body' ).on( 'focus', inputSelector, function () {
var $input = $( this );
$input.ime( {
languages: getIMELanguageList(),
languageSelector: function () {
var $ulsTrigger;
$ulsTrigger = $( '<a>' ).text( '...' );
$ulsTrigger.uls( {
onSelect: function ( language ) {
$input.data( 'ime' ).setLanguage( language );
},
languages: getLanguagesWithIME(),
top: $input.offset().top,
left: $input.offset().left
} );
return $ulsTrigger;
}
} );
} );
$.extend( $.ime.preferences, {
save: function ( callback ) {
inputPreferences.set( 'ime', this.registry );
inputPreferences.save( callback );
},
load: function () {
this.registry = inputPreferences.get( 'ime' ) || this.registry;
}
} );
$.ime.preferences.load();
} );
}( jQuery, mediaWiki, document ) );

View File

@@ -130,11 +130,26 @@
return $displaySettings;
}
function inputSettings () {
var $inputSettingsTitle, $inputSettingsText, $inputSettings;
$inputSettingsTitle = $( '<div data-i18n="ext-uls-input-settings-title">' )
.addClass( 'settings-title' );
$inputSettingsText = $( '<span data-i18n="ext-uls-input-settings-desc">' )
.addClass( 'settings-text' );
$inputSettings = $( '<div>' )
.addClass( 'input-settings-block' )
.prop( 'id', 'input-settings-block' )
.append( $inputSettingsTitle )
.append( $inputSettingsText );
return $inputSettings;
}
function addDisplaySettings ( uls ) {
var $displaySettings, position;
$displaySettings = displaySettings();
uls.$menu.find( 'div#settings-block' ).append( $displaySettings );
uls.$menu.find( '#settings-block' ).append( $displaySettings );
position = uls.position();
$displaySettings.languagesettings( {
@@ -151,9 +166,31 @@
} );
}
function addInputSettings ( uls ) {
var $inputSettings, position;
$inputSettings = inputSettings();
uls.$menu.find( '#settings-block' ).append( $inputSettings );
position = uls.position();
$inputSettings.languagesettings( {
defaultModule: 'input',
onClose: function () {
uls.show();
},
top: position.top,
left: position.left
} );
$inputSettings.on( 'click', function () {
uls.hide();
} );
}
$ulsTrigger.uls( {
onReady: function () {
addDisplaySettings( this );
addInputSettings( this );
},
onSelect: function ( language ) {
mw.uls.changeLanguage( language );

View File

@@ -0,0 +1,383 @@
/**
* ULS-based ime settings panel
*
* 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 ( $, mw, undefined ) {
'use strict';
var template = '<div class="uls-input-settings">'
+ '<div class="row">' // Top "Display settings" title
+ '<div class="twelve columns">'
+ '<h3 data-i18n="ext-uls-input-settings-title"></h3>'
+ '</div>'
+ '</div>'
// "Language for ime", title above the buttons row
+ '<div class="row">'
+ '<div class="eleven columns">'
+ '<h4 data-i18n="ext-uls-input-settings-ui-language"></h4>'
+ '</div>'
+ '</div>'
// UI languages buttons row
+ '<div class="row">'
+ '<div class="uls-ui-languages eleven columns"></div>'
+ '</div>'
// Web IMEs enabling chechbox with label
+ '<div class="row">'
+ '<div class="eleven columns uls-input-settings-inputmethods-list">'
// "Input settings for language xyz" title
+ '<h4 class="ext-uls-input-settings-imes-title"></h4>'
+ '</div>'
+ '</div>'
// Separator
+ '<div class="row"></div>'
// Apply and Cancel buttons
+ '<div class="row language-settings-buttons">'
+ '<div class="eleven columns">'
+ '<button class="button uls-input-settings-close" data-i18n="ext-uls-language-settings-cancel"></button>'
+ '<button class="active blue button uls-input-settings-apply" data-i18n="ext-uls-language-settings-apply"></button>'
+ '</div>'
+ '</div>'
+ '</div>';
function InputSettings( $parent ) {
this.name = $.i18n( 'ext-uls-input-settings-title-short' );
this.description = $.i18n( 'ext-uls-input-settings-desc' );
this.$template = $( template );
this.imeLanguage = this.getImeLanguage();
this.contentLanguage = this.getContentLanguage();
this.$imes = null;
this.$parent = $parent;
}
InputSettings.prototype = {
Constructor: InputSettings,
/**
* Render the module into a given target
*/
render: function () {
this.$parent.$settingsPanel.empty();
this.$imes = $( 'body' ).data( 'ime' );
this.$parent.$settingsPanel.append( this.$template );
this.prepareLanguages();
this.prepareInputmethods( this.imeLanguage );
this.$template.i18n();
this.listen();
},
prepareInputmethods: function ( language ) {
var inputsettings, $imeListContainer, defaultInputmethod, imes, selected, imeId,
index = 0, $imeListTitle;
imes = $.ime.languages[language];
this.imeLanguage = language;
$imeListTitle = this.$template.find( '.ext-uls-input-settings-imes-title' );
$imeListContainer = this.$template.find( '.uls-input-settings-inputmethods-list' );
$imeListContainer.find( 'label' ).remove();
if ( !imes ) {
$imeListTitle.text( '' );
return;
}
inputsettings = this;
$imeListTitle.text( $.i18n( 'ext-uls-input-settings-ime-settings',
$.uls.data.getAutonym( language ) ) );
defaultInputmethod = $.ime.preferences.getIM( language ) || imes.inputmethods[0];
for ( index in imes.inputmethods ) {
imeId = imes.inputmethods[index];
selected = defaultInputmethod === imeId;
//$.ime.load( imeId, function () {
$imeListContainer.append( inputsettings.renderInputmethodOption( imeId,
selected ) );
//} );
}
$imeListContainer.append( inputsettings.renderInputmethodOption( 'system',
defaultInputmethod === 'system' ) );
},
renderInputmethodOption: function ( imeId, selected ) {
var $imeLabel, name, description, inputmethod, $inputMethodItem;
$imeLabel = $( '<label>' ).attr( {
'for': imeId,
'class': 'imelabel'
} );
// TODO Niklas: Was there some problems with IE needing the type=foo immediately?
$inputMethodItem = $( '<input>' ).attr( {
name: 'ime',
id: imeId,
type: 'radio',
value: imeId,
checked: selected
} );
$imeLabel.append( $inputMethodItem );
if ( imeId === 'system' ) {
name = $.i18n( 'ext-uls-disable-input-method' );
description = $.i18n( 'ext-uls-disable-input-method-desc' );
} else {
inputmethod = $.ime.inputmethods[imeId];
if ( !inputmethod ) {
// Delay in registration?
name = $.ime.sources[imeId].name;
description = '';
} else {
name = inputmethod.name;
description = $.ime.inputmethods[imeId].description;
}
}
$imeLabel.append( $( '<strong>' ).text( name ) ).append(
$( '<span>' ).text( description ) );
return $imeLabel;
},
/**
* Prepare the UI language selector
*/
prepareLanguages: function () {
var imeSettings = this, languagesForButtons, $languages, suggestedLanguages,
SUGGESTED_LANGUAGES_NUMBER, lang, i, language, $button;
SUGGESTED_LANGUAGES_NUMBER = 3;
imeSettings = this;
$languages = this.$template.find( 'div.uls-ui-languages' );
suggestedLanguages = this.frequentLanguageList()
// Common world languages, for the case that there are
// too few suggested languages
.concat( [ 'en', 'zh', 'fr' ] );
// Content language is always on the first button
languagesForButtons = [ this.contentLanguage ];
// This is needed when drawing the panel for the second time
// after selecting a different language
$languages.empty();
// UI language must always be present
if ( this.imeLanguage !== this.contentLanguage ) {
languagesForButtons.push( this.imeLanguage );
}
for ( lang in suggestedLanguages ) {
// Skip already found languages
if ( $.inArray( suggestedLanguages[lang], languagesForButtons ) > -1 ) {
continue;
}
languagesForButtons.push( suggestedLanguages[lang] );
// No need to add more languages than buttons
if ( languagesForButtons.length === SUGGESTED_LANGUAGES_NUMBER ) {
break;
}
}
function buttonHandler( button ) {
return function () {
var selectedLanguage = button.data( 'language' ) || imeSettings.imeLanguage;
$.ime.preferences.setLanguage( selectedLanguage );
$( 'div.uls-ui-languages button.button' ).removeClass( 'down' );
button.addClass( 'down' );
imeSettings.prepareInputmethods( selectedLanguage );
};
}
// Add the buttons for the most likely languages
for ( i = 0; i < SUGGESTED_LANGUAGES_NUMBER; i++ ) {
language = languagesForButtons[i];
$button = $( '<button>' )
.addClass( 'button uls-language-button' )
.text( $.uls.data.getAutonym( language ) )
.prop({
lang: language,
dir: $.uls.data.getDir( language )
});
if ( language === this.imeLanguage ) {
$button.addClass( 'down' );
}
$button.data( 'language', language );
$languages.append( $button );
$button.on( 'click', buttonHandler( $button ) );
}
this.prepareMoreLanguages();
},
/**
* Prepare the more languages button. It is a ULS trigger
*/
prepareMoreLanguages: function () {
var that, $languages, $moreLanguagesButton;
that = this;
$languages = this.$template.find( 'div.uls-ui-languages' );
$moreLanguagesButton = $( '<button>' )
.prop( 'id', 'uls-more-languages' )
.addClass( 'button' ).text( '...' );
$languages.append( $moreLanguagesButton );
// Show the long language list to select a language for ime settings
$moreLanguagesButton.uls( {
left: that.$parent.left,
top: that.$parent.top,
onReady: function () {
var uls = this,
$back = $( '<a>' ).prop( 'href', '#' )
.text( $.i18n( 'ext-uls-back-to-input-settings' ) );
$back.click( function () {
uls.hide();
that.$parent.show();
} );
uls.$menu.find( 'div.uls-title' ).append( $back );
},
onSelect: function ( langCode ) {
that.imeLanguage = langCode;
that.$parent.show();
that.prepareLanguages();
that.prepareInputmethods( langCode );
},
quickList: function () {
return mw.uls.getFrequentLanguageList();
}
} );
$moreLanguagesButton.on( 'click', function () {
that.$parent.hide();
} );
},
/**
* Get previous languages
* @returns {Array}
*/
frequentLanguageList: function () {
return mw.uls.getFrequentLanguageList();
},
/**
* Get the current user interface language.
* @returns String Current UI language
*/
// XXX: Probably bad name
getImeLanguage: function () {
return mw.config.get( 'wgUserLanguage' );
},
/**
* Get the current content language.
* @returns String Current content language
*/
getContentLanguage: function () {
return mw.config.get( 'wgContentLanguage' );
},
/**
* Register general event listeners
*/
listen: function () {
var that = this, $imeListContainer;
$imeListContainer = this.$template.find( '.uls-input-settings-inputmethods-list' );
// Apply and close buttons
this.$template.find( 'button.uls-input-settings-apply' ).on( 'click', function () {
that.apply();
} );
this.$template.find( 'button.uls-input-settings-close' ).on( 'click', function () {
that.close();
} );
$imeListContainer.on( 'change', 'input:radio[name=ime]:checked', function () {
var ime = $( this ).val();
$.ime.preferences.setLanguage( that.imeLanguage );
$.ime.preferences.setIM( ime );
} );
},
/**
* Hide this window.
* Used while navigating to language selector and need coming back
*/
hide: function () {
this.$parent.hide();
},
/**
* Close the language settings window.
* Depending on the context, actions vary.
*/
close: function () {
this.$parent.close();
},
/**
* Callback for save preferences
*/
onSave: function ( success ) {
if ( success ) {
// Live ime update
this.$parent.hide();
} else {
// FIXME failure. what to do?!
}
},
/**
* Handle the apply button press
*/
apply: function () {
var that = this;
// Save the preferences
$.ime.preferences.save( function ( result ) {
// closure for not losing the scope
that.onSave( result );
} );
}
};
// Register this module to language settings modules
$.fn.languagesettings.modules = $.extend( $.fn.languagesettings.modules, {
input: InputSettings
} );
} ( jQuery, mediaWiki ) );

View File

@@ -0,0 +1,313 @@
/**
* -- DRAFT --
*
* ULS-based generic settings panel. Common code for IME settings,
* fonts settings, and possible other setings.
*
* 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 ( $, mw, undefined ) {
'use strict';
function templateTopTitle( msg ) {
// XXX Niklas: escape msg
return '<div class="row">'
+ '<div class="twelve columns">'
+ '<h3 data-i18n="' + msg + '"></h3>'
+ '</div>'
+ '</div>';
}
function templateButtonsTitle( msg ) {
return '<div class="row">'
+ '<div class="eleven columns">'
+ '<h4 data-i18n="' + msg + '"></h4>'
+ '</div>'
+ '</div>';
}
var templateButtonsRow = '<div class="row">'
+ '<div class="uls-ui-languages eleven columns"></div>'
+ '</div>',
templateSeparator = '<div class="row"></div>';
var templateApplyCancel( id ) {
return '<div class="row language-settings-buttons">'
+ '<div class="eleven columns">'
+ '<button class="button uls-settings-close" data-i18n="ext-uls-language-settings-cancel"></button>'
+ '<button id="' + id + '" class="active blue button" data-i18n="ext-uls-language-settings-apply"></button>'
+ '</div>'
+ '</div>';
}
function SettingsPanel( $parent, options ) {
var template = templateTopTitle( options.topTitleMsg )
+ templateButtonsTitle( options.buttonsTitleMsg )
+ templateButtonsRow
+ templateSeparator
+ options.customTemplate
+ templateApplyCancel( options.applyCancelId );
this.name = $.i18n( options.nameMsg );
this.description = $.i18n( options.descMsg );
this.$template = $( '<div class="uls-settings-panel>' )
.html( template );
this.uiLanguage = this.getUILanguage();
this.contentLanguage = this.getContentLanguage();
this.$parent = $parent;
}
InputSettings.prototype = {
Constructor: SettingsPanel,
/**
* Render the module into a given target
*/
render: function () {
this.$parent.$settingsPanel.empty();
this.$parent.$settingsPanel.append( this.$template );
this.prepareLanguages();
this.prepareCustomPanel();
this.listen();
},
/**
* To be overriden
*/
prepareCustomPanel: function () {
return;
}
/**
* Prepare the UI language selector
*/
prepareLanguages: function () {
var SUGGESTED_LANGUAGES_NUMBER = 3,
languagesForButtons, $languages, suggestedLanguages,
SUGGESTED_LANGUAGES_NUMBER, lang, i, language, $button;
$languages = this.$template.find( 'div.uls-ui-languages' );
suggestedLanguages = this.frequentLanguageList()
// Common world languages, for the case that there are
// too few suggested languages
.concat( [ 'en', 'zh', 'fr' ] );
// Content language is always on the first button
languagesForButtons = [ this.contentLanguage ];
// This is needed when drawing the panel for the second time
// after selecting a different language
$languages.empty();
// UI language must always be present
if ( this.uiLanguage !== this.contentLanguage ) {
languagesForButtons.push( this.uiLanguage );
}
for ( lang in suggestedLanguages ) {
// Skip already found languages
if ( $.inArray( suggestedLanguages[lang], languagesForButtons ) > -1 ) {
continue;
}
languagesForButtons.push( suggestedLanguages[lang] );
// No need to add more languages than buttons
if ( languagesForButtons.length === SUGGESTED_LANGUAGES_NUMBER ) {
break;
}
}
// Add the buttons for the most likely languages
for ( i = 0; i < SUGGESTED_LANGUAGES_NUMBER; i++ ) {
language = languagesForButtons[i];
$button = $( '<button>' )
.addClass( 'button uls-language-button' )
.text( $.uls.data.getAutonym( language ) )
.prop({
lang: language,
dir: $.uls.data.getDir( language )
});
if ( language === this.uiLanguage ) {
$button.addClass( 'down' );
}
$button.data( 'language', language );
$languages.append( $button );
$button.on( 'click', this.buttonHandler( $button ) );
}
this.prepareMoreLanguages();
},
languageButtonHandler: function( button ) {
var selectedLanguage = button.data( 'language' ) || this.uiLanguage;
$( 'div.uls-ui-languages button.button' ).removeClass( 'down' );
button.addClass( 'down' );
this.customLanguageButton( selectedLanguage );
},
/**
* To be overriden
*/
customLanguageButton: function( selectedLanguage ) {
return;
}
/**
* Prepare the more languages button. It is a ULS trigger
*/
prepareMoreLanguages: function () {
var settingsPanel, $languages, $moreLanguagesButton;
settingsPanel = this;
$languages = this.$template.find( 'div.uls-ui-languages' );
$moreLanguagesButton = $( '<button>' )
.prop( 'id', 'uls-more-languages' )
.addClass( 'button' ).text( '...' );
$languages.append( $moreLanguagesButton );
// Show the long language list to select a language for the settings
$moreLanguagesButton.uls( {
left: settingsPanel.$parent.left,
top: settingsPanel.$parent.top,
onReady: function ( ) {
var uls = this,
$back = $( '<a>' ).prop( 'href', '#' )
.data( 'i18n', settingsPanel.options.backFromMoreLanguagesMsg )
.i18n();
$back.click( function () {
uls.hide();
settingsPanel.$parent.show();
} );
uls.$menu.find( 'div.uls-title' ).append( $back );
uls.$menu.find( 'div.uls-title h1' )
.data( 'i18n', settingsPanel.options.moreLanguagesTitleMsg )
.i18n();
},
onSelect: function ( langCode ) {
settingsPanel.uiLanguage = langCode;
settingsPanel.$parent.show();
settingsPanel.moreLanguagesSelectHandler( langCode );
},
quickList: function () {
return mw.uls.getFrequentLanguageList();
}
} );
$moreLanguagesButton.on( 'click', function () {
that.$parent.hide();
} );
},
/**
* To be overriden
*/
moreLanguagesSelectHandler: function ( langCode ) {
return;
}
/**
* Get previous languages
* @returns {Array}
*/
frequentLanguageList: function () {
return mw.uls.getFrequentLanguageList();
},
/**
* Get the current user interface language.
* @returns String Current UI language
*/
getUILanguage: function () {
return mw.config.get( 'wgUserLanguage' );
},
/**
* Get the current content language.
* @returns String Current content language
*/
getContentLanguage: function () {
return mw.config.get( 'wgContentLanguage' );
},
/**
* TODO
*/
listen: function () {
return;
},
/**
* Hide this window.
* Used while navigating to language selector and need coming back
*/
hide: function () {
this.$parent.hide();
},
/**
* Close the language settings window.
* Depending on the context, actions vary.
*/
close: function () {
this.$parent.close();
},
/**
* Callback for save preferences
*/
onSave: function ( success ) {
if ( success ) {
// Live feature update
this[this.options.feature].refresh();
this.$parent.hide();
// we delay change UI language to here, because it causes a page refresh
if ( this.uiLanguage !== this.getUILanguage() ) {
mw.uls.changeLanguage( this.uiLanguage );
}
} else {
// FIXME failure. what to do?!
}
},
/**
* Handle the apply button press
*/
apply: function () {
var settingsPanel = this;
// Save the preferences
this[this.options.preferences].save( function ( result ) {
// closure for not losing the scope
settingsPanel.onSave( result );
} );
}
};
// Register this module to language settings modules
$.fn.languagesettings.modules = $.extend( $.fn.languagesettings.modules, {
input: InputSettings
} );
} ) ( jQuery, mediaWiki );