diff --git a/l10n_client.css b/l10n_client.css index ed7b2e7..470cec6 100644 --- a/l10n_client.css +++ b/l10n_client.css @@ -10,7 +10,7 @@ how it wants to round. */ line-height:1em; color:#000; background:#fff; position:fixed; - width:100%; height: 2em; + width:100%; bottom:0px; left:0px; overflow:hidden;} @@ -195,3 +195,14 @@ how it wants to round. */ background-color: #F00; color: #fff; } +#l10n-client .collapsed { + height: 2em; + overflow: hidden; +} +#l10n-client .expanded { + height: 22em; +} + +#l10n-client .toggle-expanded { + border-bottom: 22em solid #fff; +} diff --git a/l10n_client.js b/l10n_client.js index def53e7..4301545 100644 --- a/l10n_client.js +++ b/l10n_client.js @@ -1,217 +1,221 @@ -(function ($) { +(function ($, Drupal, undefined) { // Store all l10n_client related data + methods in its own object -$.extend(Drupal, { - l10nClient: new (function() { - // Set "selected" string to unselected, i.e. -1 - this.selected = -1; - // Keybindings - this.keys = {'toggle':'ctrl+shift+s', 'clear': 'esc'}; // Keybindings - // Keybinding functions - this.key = function(pressed) { - switch(pressed) { - case 'toggle': - // Grab user-hilighted text & send it into the search filter - userSelection = window.getSelection ? window.getSelection() : document.getSelection ? document.getSelection() : document.selection.createRange().text; - userSelection = String(userSelection); - if(userSelection.length > 0) { - Drupal.l10nClient.filter(userSelection); - Drupal.l10nClient.toggle(1); - $('#l10n-client .string-search').focus(); - } else { - if($('#l10n-client').is('.hidden')) { - Drupal.l10nClient.toggle(1); - if(!$.browser.safari) { - $('#l10n-client .string-search').focus(); - } - } else { - Drupal.l10nClient.toggle(0); +Drupal.l10nClient = { + // Set "selected" string to unselected, i.e. -1 + selected: -1, + // Keybindings + keys: {'toggle':'ctrl+shift+s', 'clear': 'esc'}, // Keybindings + // Keybinding functions + key: function(pressed) { + var $l10nClient = $('#l10n-client'); + switch(pressed) { + case 'toggle': + // Grab user-hilighted text & send it into the search filter + var userSelection = window.getSelection ? window.getSelection() : document.getSelection ? document.getSelection() : document.selection.createRange().text; + userSelection = String(userSelection); + if(userSelection.length > 0) { + this.filter(userSelection); + this.toggle(1); + $l10nClient.find('.string-search').focus(); + } else { + if($l10nClient.is('.collapsed')) { + this.toggle(1); + if(!$.browser.safari) { + $l10nClient.find('.string-search').focus(); } + } else { + this.toggle(0); } - break; - case 'clear': - this.filter(false); - break; - } - } - // Toggle the l10nclient - this.toggle = function(state) { - switch(state) { - case 1: - $('#l10n-client-string-select, #l10n-client-string-editor, #l10n-client .labels .label').show(); - $('#l10n-client').height('22em').removeClass('hidden'); - $('#l10n-client .labels .toggle').text('X'); - if(!$.browser.msie) { - $('body').css('border-bottom', '22em solid #fff'); - } - $.cookie('Drupal_l10n_client', '1', {expires: 7, path: '/'}); - break; - case 0: - $('#l10n-client-string-select, #l10n-client-string-editor, #l10n-client .labels .label').hide(); - $('#l10n-client').height('2em').addClass('hidden'); - $('#l10n-client .labels .toggle').text(Drupal.t('Translate Text')); - if(!$.browser.msie) { - $('body').css('border-bottom', '0px'); - } - $.cookie('Drupal_l10n_client', '0', {expires: 7, path: '/'}); - break; - } - } - // Get a string from the DOM tree - this.getString = function(index, type) { - return $('#l10n-client-data div:eq('+index+') .'+type).text(); - } - // Set a string in the DOM tree - this.setString = function(index, data) { - $('#l10n-client-data div:eq('+index+') .target').text(data); + } + break; + case 'clear': + this.filter(false); + break; } - // Filter the the string list by a search string - this.filter = function(search) { - if(search == false || search == '') { - $('#l10n-client #l10n-client-search-filter-clear').focus(); - $('#l10n-client-string-select li').show(); - $('#l10n-client .string-search').val(''); - $('#l10n-client .string-search').focus(); - } else { - if(search.length > 0) { - $('#l10n-client-string-select li').hide(); - $('#l10n-client-string-select li:contains('+search+')').show(); - $('#l10n-client .string-search').val(search); + }, + // Toggle the l10nclient + toggle: function(state) { + var $l10nClient = $('#l10n-client'); + var $clientWrapper = $('#l10n-client-string-select, #l10n-client-string-editor, #l10n-client .labels .label'); + switch(state) { + case '1': + case true: + $clientWrapper.show(); + $l10nClient.removeClass('collapsed').addClass('expanded').find('.labels .toggle').text('X'); + if(!$.browser.msie) { + $('body').addClass('toggle-expanded'); } - } + $.cookie('Drupal_l10n_client', '1', {expires: 7, path: '/'}); + break; + case '0': + case false: + $clientWrapper.hide(); + $l10nClient.removeClass('expanded').addClass('collapsed').find('.labels .toggle').text(Drupal.t('Translate Text')); + if(!$.browser.msie) { + $('body').removeClass('.toggle-expanded'); + } + $.cookie('Drupal_l10n_client', '0', {expires: 7, path: '/'}); + break; } - }) -}); - -// Attaches the localization editor behavior to all required fields. -Drupal.behaviors.l10nClient = {} -Drupal.behaviors.l10nClient.attach = function (context) { - // Killswitch - attach only once. - if ($('#l10n-client').is('.l10n-client-processed')) { - return; - } - - // First time - init & attach all handlers. - $('#l10n-client').addClass('l10n-client-processed'); - - switch($.cookie('Drupal_l10n_client')) { - case '1': - Drupal.l10nClient.toggle(1); - break; - default: - Drupal.l10nClient.toggle(0); - break; - } - - // If the selection changes, copy string values to the source and target fields. - // Add class to indicate selected string in list widget. - $('#l10n-client-string-select li').click(function() { - $('#l10n-client-string-select li').removeClass('active'); - $(this).addClass('active'); - var index = $('#l10n-client-string-select li').index(this); - - $('#l10n-client-string-editor .source-text').text(Drupal.l10nClient.getString(index, 'source')); - $('#l10n-client-form .translation-target').val(Drupal.l10nClient.getString(index, 'target')); - $('#l10n-client-form .source-textgroup').val(Drupal.l10nClient.getString(index, 'textgroup')); - $('#l10n-client-form .source-context').val(Drupal.l10nClient.getString(index, 'context')); - $('#l10n-client-string-editor .context').text(Drupal.l10nClient.getString(index, 'context')); - - Drupal.l10nClient.selected = index; - $('#l10n-client-form .form-submit').removeAttr("disabled"); - }); - - // When l10n_client window is clicked, toggle based on current state. - $('#l10n-client .labels .toggle').click(function() { - if($('#l10n-client').is('.hidden')) { - Drupal.l10nClient.toggle(1); + }, + // Get a string from the DOM tree + getString: function(index, type) { + return $('#l10n-client-data div:eq('+index+') .'+type).text(); + }, + // Set a string in the DOM tree + setString: function(index, data) { + $('#l10n-client-data div:eq('+index+') .target').text(data); + }, + // Filter the the string list by a search string + filter: function(search) { + var $l10nClient = $('#l10n-client'); + var $stringSearch = $l10nClient.find('.string-search'); + var $stringSelect = $('#l10n-client-string-select').find('li'); + if(search === false || search === '') { + $('#l10n-client-search-filter-clear').focus(); + $stringSelect.show(); + $stringSearch.val('').focus(); } else { - Drupal.l10nClient.toggle(0); + if(search.length > 0) { + $stringSelect.not(':contains('+search+')').hide(); + $stringSearch.val(search); + } } - }); - - // Copy source text to translation field on button click. - $('#l10n-client-form .edit-copy').click(function() { - $('#l10n-client-form .translation-target').val($('#l10n-client-string-editor .source-text').text()); - return false; - }); - - // Clear translation field on button click. - $('#l10n-client-form .edit-clear').click(function() { - $('#l10n-client-form .translation-target').val(''); - return false; - }); - - // Register keybindings using jQuery hotkeys - if($.hotkeys) { - $.hotkeys.add(Drupal.l10nClient.keys['toggle'], function(){Drupal.l10nClient.key('toggle')}); - $.hotkeys.add(Drupal.l10nClient.keys['clear'], {target:'#l10n-client .string-search', type:'keyup'}, function(){Drupal.l10nClient.key('clear')}); } +}; - // Custom listener for l10n_client livesearch - $('#l10n-client .string-search').keyup(function(key) { - Drupal.l10nClient.filter($('#l10n-client .string-search').val()); - }); - - // Clear search - $('#l10n-client #l10n-client-search-filter-clear').click(function() { - Drupal.l10nClient.filter(false); - return false; - }); - - // Send AJAX POST data on form submit. - $('#l10n-client-form').submit(function() { - $('#l10n-client-form .form-submit').attr("disabled", "true"); - $.ajax({ - type: "POST", - url: $('#l10n-client-form').attr('action'), - // Send source and target strings. - data: { - source: $('#l10n-client-string-editor .source-text').text(), - target: $('#l10n-client-form .translation-target').val(), - textgroup: $('#l10n-client-form .source-textgroup').val(), - context: $('#l10n-client-string-editor .context').text(), - 'form_token': $('#l10n-client-form input[name=form_token]').val() - }, - success: function (data) { - // Store string in local js - Drupal.l10nClient.setString(Drupal.l10nClient.selected, $('#l10n-client-form .translation-target').val()); - - // Figure out the display of the new translation in the selection list. - var newTranslation = $('#l10n-client-form .translation-target').val(); - var newTranslationDisplay = newTranslation; - var newTranslationStripped = newTranslation.replace(/<\/?[^<>]+>/gi, '') - .replace(/"/g, '"') - .replace(/</g, "<") - .replace(/>/g, ">") - .replace(/&/g, "&"); - if (newTranslationStripped.length == 0) { - // Only contains HTML tags (edge case). Keep the whole string. - // HTML tags will show up in the selector, but that is normal in this case. - newTranslationDisplay = newTranslation; - } - else if (newTranslationStripped.length > 81) { - // Long translation, strip length to display only first part. - // We strip at 78 chars and add thre dots, if the total length is - // above 81. - newTranslationDisplay = newTranslationStripped.substr(0, 78) + '...'; - } +// Attaches the localization editor behavior to all required fields. +Drupal.behaviors.l10nClient = { + attach: function (context) { + $('#l10n-client').once('l10n-client', function () { + var $self = $(this); + Drupal.l10nClient.toggle($.cookie('Drupal_l10n_client')); + + var $l10nClientForm = $('#l10n-client-form'); + var $stringEditor = $('#l10n-client-string-editor'); + var $stringEditorSoruceText = $stringEditor.find('.source-text'); + var $stringSelect = $('#l10n-client-string-select'); + // If the selection changes, copy string values to the source and target fields. + // Add class to indicate selected string in list widget. + $stringSelect.find('li').click(function() { + var $this = $(this); + var $lis = $stringSelect.find('li'); + var index = $lis.index(this); + + $lis.removeClass('active'); + $this.addClass('active'); + + $stringEditorSoruceText.text(Drupal.l10nClient.getString(index, 'source')); + $l10nClientForm.find('.translation-target').val(Drupal.l10nClient.getString(index, 'target')); + $l10nClientForm.find('.source-textgroup').val(Drupal.l10nClient.getString(index, 'textgroup')); + $l10nClientForm.find('.source-context').val(Drupal.l10nClient.getString(index, 'context')); + $stringEditor.find('.context').text(Drupal.l10nClient.getString(index, 'context')); + + Drupal.l10nClient.selected = index; + $l10nClientForm.find('.form-submit').removeAttr("disabled"); + }); + + // When l10n_client window is clicked, toggle based on current state. + $self.find('.labels .toggle').click(function() { + Drupal.l10nClient.toggle($('#l10n-client').is('.collapsed')); + }); + + // Copy source text to translation field on button click. + $l10nClientForm.find('.edit-copy').click(function() { + $l10nClientForm.find('.translation-target').val($stringEditorSoruceText.text()); + return false; + }); + + // Clear translation field on button click. + $l10nClientForm.find('.edit-clear').click(function() { + $l10nClientForm.find('.translation-target').val(''); + return false; + }); + + // Register keybindings using jQuery hotkeys + if($.hotkeys) { + $.hotkeys.add(Drupal.l10nClient.keys.toggle, function(){ + Drupal.l10nClient.key('toggle'); + }); + $.hotkeys.add(Drupal.l10nClient.keys.clear, {target:'#l10n-client .string-search', type:'keyup'}, function(){ + Drupal.l10nClient.key('clear'); + }); + } - // Mark string as translated. - $('#l10n-client-string-select li').eq(Drupal.l10nClient.selected).removeClass('untranslated').removeClass('active').addClass('translated').text(newTranslationDisplay); + // Custom listener for l10n_client livesearch + $self.find('.string-search').keyup(function(key) { + Drupal.l10nClient.filter($self.find('.string-search').val()); + }); + + // Clear search + $self.find('#l10n-client-search-filter-clear').click(function() { + Drupal.l10nClient.filter(false); + return false; + }); + + // Send AJAX POST data on form submit. + $l10nClientForm.submit(function() { + var $this = $(this); + + // Prevent submit empty strings. + $this.find('.form-submit').attr("disabled", true); + + $.ajax({ + type: "POST", + url: $this.attr('action'), + // Send source and target strings. + data: { + source: $stringEditorSoruceText.text(), + target: $this.find('.translation-target').val(), + textgroup: $this.find('.source-textgroup').val(), + context: $stringEditor.find('.context').text(), + 'form_token': $this.find('input[name=form_token]').val() + }, + success: function (data) { + var $translationTarget = $l10nClientForm.find('.translation-target'); + var newTranslation = $translationTarget.val(); + // Store string in local js + Drupal.l10nClient.setString(Drupal.l10nClient.selected, newTranslation); + + // Figure out the display of the new translation in the selection list. + var newTranslationStripped = newTranslation.replace(/<\/?[^<>]+>/gi, '') + .replace(/"/g, '"') + .replace(/</g, "<") + .replace(/>/g, ">") + .replace(/&/g, "&"); + + // Only contains HTML tags (edge case). Keep the whole string. + // HTML tags will show up in the selector, but that is normal in this case. + newTranslationDisplay = newTranslation; + if (newTranslationStripped.length > 81) { + // Long translation, strip length to display only first part. + // We strip at 78 chars and add thre dots, if the total length is + // above 81. + newTranslationDisplay = newTranslationStripped.substr(0, 78) + '...'; + } - // Empty input fields. - $('#l10n-client-string-editor .source-text').html(data); - $('#l10n-client-form .translation-target').val(''); + // Mark string as translated. + $stringSelect.find('li') + .eq(Drupal.l10nClient.selected) + .removeClass('untranslated active') + .addClass('translated') + .text(newTranslationDisplay); - }, - error: function (xmlhttp) { - alert(Drupal.t('An HTTP error @status occured.', { '@status': xmlhttp.status })); - } - }); - return false; - }); + // Empty input fields. + $stringEditorSoruceText.html(data); + $translationTarget.val(''); + }, + error: function (xmlhttp) { + alert(Drupal.t('An HTTP error @status occured.', { '@status': xmlhttp.status })); + } + }); + return false; + }); + }); + } }; -})(jQuery); +})(jQuery, Drupal);