/*! * Aloha Editor * Author & Copyright (c) 2011 Gentics Software GmbH * aloha-sales@gentics.com * Licensed under the terms of http://www.aloha-editor.com/license.html */ define( [ 'aloha', 'aloha/jquery', 'aloha/plugin', 'aloha/floatingmenu', 'i18n!wai-lang/nls/i18n', 'i18n!aloha/nls/i18n', 'wai-lang/languages', 'css!wai-lang/css/wai-lang.css' ], function( Aloha, jQuery, Plugin, FloatingMenu, i18n, i18nCore ) { var WAI_LANG_CLASS = 'aloha-wai-lang', GENTICS = window.GENTICS, addMarkupToSelectionButton, langField; return Plugin.create( 'wai-lang', { /** * Configure the available languages (i18n) for this plugin */ languages: [ 'en', 'de' ], /** * Default configuration allows spans everywhere */ config: [ 'span' ], /** * the defined object types to be used for this instance */ objectTypeFilter: [ 'language' ], /** * Initialize the plugin: * Initializes UI components, and binds their event listeners. */ init: function() { if ( this.settings.objectTypeFilter ) { this.objectTypeFilter = this.settings.objectTypeFilter; } this.createButtons(); this.subscribeEvents(); this.bindInteractions(); }, /** * Subscribe for events */ subscribeEvents: function() { var that = this; // add the event handler for selection change Aloha.bind( 'aloha-editable-activated', function( event, rangeObject ) { var config; // show/hide the button according to the configuration config = that.getEditableConfig( Aloha.activeEditable.obj ); if ( jQuery.inArray( 'span', config ) !== -1 ) { addMarkupToSelectionButton.show(); } else { addMarkupToSelectionButton.hide(); return; } } ); // add the event handler for selection change Aloha.bind( 'aloha-selection-changed', function( event, rangeObject ) { var foundMarkup; foundMarkup = that.findLangMarkup( rangeObject ); if ( foundMarkup ) { addMarkupToSelectionButton.setPressed( true ); FloatingMenu.setScope( 'wai-lang' ); langField.setTargetObject( foundMarkup, 'lang' ); } else { langField.setTargetObject( null ); } } ); }, /** * Initialize the buttons: * Places the Wai-Lang UI buttons into the floating menu. */ createButtons: function() { var that = this; // Button for adding a language markup to the current selection addMarkupToSelectionButton = new Aloha.ui.Button( { 'name' : 'wailang', 'iconClass' : 'aloha-button aloha-button-wai-lang', 'size' : 'small', 'onclick' : function() { that.addRemoveMarkupToSelection(); }, 'tooltip' : i18n.t( 'button.add-wai-lang.tooltip' ), 'toggle' : true } ); FloatingMenu.addButton( 'Aloha.continuoustext', addMarkupToSelectionButton, i18nCore.t( 'floatingmenu.tab.format' ), 1 ); // Add the new scope for the wai languages plugin tab FloatingMenu.createScope( 'wai-lang', 'Aloha.continuoustext' ); langField = new Aloha.ui.AttributeField( { 'name' : 'wailangfield', 'width' : 320, 'valueField' : 'id', 'minChars' : 1 } ); langField.setTemplate( '
' + '' + '
{name}
' + '
' ); langField.setObjectTypeFilter( this.objectTypeFilter ); // add the input field for links FloatingMenu.addButton( 'wai-lang', langField, i18n.t( 'floatingmenu.tab.wai-lang' ), 1 ); var removeButton = new Aloha.ui.Button( { 'name' : 'removewailang', 'iconClass' : 'aloha-button aloha-button-wai-lang-remove', 'size' : 'small', 'onclick' : function() { that.removeLangMarkup(); }, 'tooltip' : i18n.t( 'button.add-wai-lang-remove.tooltip' ), 'toggle' : false } ); FloatingMenu.addButton( 'wai-lang', removeButton, i18n.t( 'floatingmenu.tab.wai-lang' ), 1 ); }, /** * Given a range object, finds and returns a Wai-Lang wrapper DOM * element within the range. * * @param {GENTICS.Utils.RangeObject} range * @return {?DOMObject} the dom object found, or false if nothing found */ findLangMarkup: function( range ) { range = range || Aloha.Selection.getRangeObject(); if ( Aloha.activeEditable ) { return range.findMarkup( function() { return jQuery( this ).hasClass( WAI_LANG_CLASS ) || jQuery( this ).is( '[lang]' ); }, Aloha.activeEditable.obj ); } return null; }, /** * Check whether the range is within a span that contains a lang * attribute. * * @param {GENTICS.Utils.RangeObject} range range where to insert the * object (at start or end) * @return {?DOMObject} the dom object found, or false if nothing found * @hide */ findLanguageMarkup: function( range ) { range = range || Aloha.Selection.getRangeObject(); if ( Aloha.activeEditable ) { return range.findMarkup( function() { return this.nodeName === 'SPAN'; }, Aloha.activeEditable.obj ); } return null; }, /** * */ removeLangMarkup: function() { var range = Aloha.Selection.getRangeObject(), foundMarkup = this.findLangMarkup( range ); if ( foundMarkup ) { // remove the abbr GENTICS.Utils.Dom.removeFromDOM( foundMarkup, range, true ); // select the (possibly modified) range range.select(); FloatingMenu.setScope( 'Aloha.continousText' ); langField.setTargetObject( null ); FloatingMenu.doLayout(); } }, /** * Parse a all editables for elements that have a lang attribute and * bind an onclick event */ bindInteractions: function() { var that = this; // on blur check if lang is empty, if so remove the tag langField.addListener( 'blur', function( obj, event ) { // @todo check for a valid value -- now it's also possible to insert abcd; but that's not valid if ( !this.getValue() ) { that.removeMarkup(); } } ); Aloha.ready( function() { that.handleExistingSpans(); } ); }, /** * Find all existing spans and register hotkey hotkeys and make * annotations of languages visible. */ handleExistingSpans: function() { var that = this; // Add the Link shortcut to all editables jQuery.each( Aloha.editables, function( key, editable ) { // Hotkey for adding new language annotations: CTRL+I editable.obj.keydown( that.handleKeyDown ); } ); jQuery.each( Aloha.editables, function( key, editable ) { // Find all spans with lang attributes and add some css and // event handlers editable.obj.find( 'span[lang]' ).each( function( i ) { that.makeVisible( this ); } ); } ); }, /** * @param {Event} e * @return {?Boolean} */ handleKeyDown: function( e ) { if ( e.metaKey && e.which === 73 ) { if ( this.findLangMarkup() ) { FloatingMenu.activateTabOfButton( 'wailangfield' ); langField.focus(); } else { this.addMarkupToSelection(); } // Prevent from further handling. // on a MAC Safari, cursor would jump to location bar. // We have to use ESC and then META+I instead. return false; } }, /** * Make the given element visible by adding some styles to it. */ makeVisible: function( element ) { // Make existing spans with language attribute visible // Flags can be added via the metaview plugin jQuery( element ).css( 'background-image', 'url(' + Aloha.getPluginUrl( 'wai-lang' ) + '/img/flags/' + jQuery( element ).attr( 'lang' ) + '.png)' ); jQuery( element ).addClass( WAI_LANG_CLASS ); }, /** * Format the current selection or if collapsed the current word as * element that should be annotated. */ formatLanguageSpan: function() { if ( Aloha.activeEditable ) { var range = Aloha.Selection.getRangeObject(); if ( this.findLanguageMarkup( range ) ) { this.removeMarkup(); } else { this.insertMarkup(); } } }, /** * Toggles markup around selection. */ addRemoveMarkupToSelection: function() { if ( addMarkupToSelectionButton.pressed ) { this.removeLangMarkup(); } else { this.addMarkupToSelection( false ); } }, /** * Retrieves the current selected range, and wraps it with wai-lang * content. */ addMarkupToSelection: function() { var range = Aloha.Selection.getRangeObject(); // Do not add markup to an area that already contains a markup if ( this.findLangMarkup( range ) ) { return; } FloatingMenu.activateTabOfButton( 'wailangfield' ); FloatingMenu.setScope( 'wai-lang' ); if ( range.isCollapsed() ) { GENTICS.Utils.Dom.extendToWord( range ); } if ( !range.isCollapsed() ) { GENTICS.Utils.Dom.addMarkup( range, jQuery( '' ), false ); } range.select(); // langField.focus(); }, /** * Remove an a tag. */ removeMarkup: function() { var foundMarkup = this.findLangMarkup(), range; if ( foundMarkup ) { range = Aloha.Selection.getRangeObject(); GENTICS.Utils.Dom.removeFromDOM( foundMarkup, range, true ); // select the (possibly modified) range range.select(); } }, /** * Make the given jQuery object (representing an editable) clean for saving * Find all elements with lang attributes and remove the attribute. * @param {jQuery} obj jQuery object to make clean */ makeClean: function( obj ) { obj.find( 'span[lang]' ).each( function() { jQuery( this ).removeClass( WAI_LANG_CLASS ); } ); } } ); } );