Pj_Leward

CKEditor custom tags plugin

Mar 31st, 2012
671
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. Copyright (c) 2011, Pub-Me CMS - Michal Malenek. All rights reserved.
  3. Custom YouTube plugin for CKEditor by CKSource - Frederico Knabben.
  4. */
  5.  
  6. if ( typeof(PubMeCKEDITOR) == "undefined" || PubMeCKEDITOR === null )
  7. {
  8.     var PubMeCKEDITOR = {};
  9. }
  10.  
  11. (function()
  12. {
  13.  
  14.     /**
  15.      * Function to test if a value is in an array
  16.      * @author Leward
  17.      */
  18.     function inArray(array, p_val) {
  19.         var l = array.length;
  20.         for(var i = 0; i < l; i++) {
  21.             if(array[i] == p_val) {
  22.                 return true;
  23.             }
  24.         }
  25.         return false;
  26.     }
  27.  
  28.     // name of the plugin
  29.     var pubmePluginName = '_pubme_extratags';
  30.  
  31.     // definition of custom tags
  32.     var pubmeCustomTags = {
  33.         myvideo : {
  34.             dtd : [ '$empty','$inline','$body','div' ]
  35.         },
  36.         youtube : {
  37.             dtd : [ '$empty','$inline','$body','div' ]
  38.         },
  39.         mymusic : {
  40.             dtd : [ '$empty','$inline','$body','div' ]
  41.         }
  42.     };
  43.    
  44.     // setttings end
  45.  
  46.     PubMeCKEDITOR[pubmePluginName] = {
  47.         pluginName : pubmePluginName,
  48.         getLang : function ( editor, pubmeTagName )
  49.         {              
  50.             // prevent "lang error"
  51.             if ( !editor.lang.pubme )
  52.                 editor.lang.pubme = {};
  53.             if ( !editor.lang.pubme[this.pluginName] )
  54.                 editor.lang.pubme[pubmePluginName] = {};
  55.             if ( !editor.lang.pubme[this.pluginName][pubmeTagName] )
  56.                 editor.lang.pubme[this.pluginName][pubmeTagName] =
  57.                 {
  58.                     fakeObjectTitle : pubmeTagName,
  59.                     mainMenu : pubmeTagName,
  60.                     properties : pubmeTagName
  61.                 }
  62.             var tagLang = editor.lang.pubme[ this.pluginName ][ pubmeTagName ];
  63.  
  64.             // update on hover title
  65.             if ( !editor.lang.fakeobjects[pubmeTagName] )
  66.                 editor.lang.fakeobjects[pubmeTagName] = tagLang.fakeObjectTitle;
  67.  
  68.             return tagLang;
  69.         },
  70.         loadValue : function ( attributes )
  71.         {
  72.             if ( this.id in attributes )
  73.                 this.setValue ( attributes [ this.id ] );
  74.         },
  75.         commitValue : function ( attributes )
  76.         {
  77.             attributes [ this.id ] = this.getValue();
  78.         },
  79.         onShow : function( t, editor )
  80.         {
  81.             /**
  82.              * Little fix when handling many custom buttons
  83.              * @author Leward
  84.              */
  85.             tagName = t._.name;
  86.  
  87.             // Clear previously saved elements.
  88.             t.fakeImage = t.iframeNode = null;
  89.  
  90.             var fakeImage = t.getSelectedElement();
  91.             if ( fakeImage && fakeImage.data( 'cke-real-element-type' ) && fakeImage.data( 'cke-real-element-type' ) == tagName )
  92.             {
  93.                 // custom tag needs to be parsed using "brutal force" - it is not possible to use inner/outerHTML and getAttributes methods
  94.                 // as custom tags are not included in dom for some reason
  95.                 // so we simply take the "realelement" string and search for quotes and apostrophes instead
  96.                 // We assume the format is <tag arg="something" arg2='something' /> or <tag arg="something" arg2='something'>something</tag>
  97.                 t.fakeImage = fakeImage;
  98.                 var html = decodeURIComponent( fakeImage.data( 'cke-realelement' ) );
  99.                 var attributes = [];
  100.                
  101.                 var i, i1, i2, attribute, attributeValue, useChar;
  102.                
  103.                 i = html.indexOf(" ");
  104.                 html = html.substr ( i );
  105.  
  106.                 while ( html.indexOf("=")>=0 )
  107.                 {
  108.                     i = html.indexOf("=");
  109.                     attribute = html.substr ( 0, i ).replace(/^\s+|\s+$/g,"");
  110.                     html = html.substr ( i+1 );
  111.                    
  112.                     i = -1;
  113.                     i1 =  html.indexOf("'");
  114.                     i2 =  html.indexOf('"');
  115.                     i3 =  html.indexOf('>');
  116.  
  117.                     if (i1 >= 0)
  118.                         i = i1;
  119.  
  120.                     if (i2 >=0 && (i2<i || i<0) )
  121.                         i = i2;
  122.  
  123.                     if (i3 >=0 && (i3<i || i<0) )
  124.                         html = "";
  125.                    
  126.                     useChar = html.substr ( i, 1 );
  127.                     html = html.substr ( i + 1 );
  128.  
  129.                     if ( html.indexOf( useChar )>=0 )
  130.                     {
  131.                         i = html.indexOf( useChar );
  132.                         attributeValue = html.substr ( 0, i ).replace(/^\s+|\s+$/g,"");
  133.                         html = html.substr ( i+1 );
  134.                         attributes [ attribute ] = attributeValue;
  135.                     }
  136.                     else
  137.                         html = "";
  138.                 }
  139.                
  140.                 t.setupContent( attributes );
  141.                
  142.             }
  143.         },
  144.         onOk : function( t, editor )
  145.         {
  146.             var attributes = [];
  147.             t.commitContent( attributes );
  148.            
  149.             var fakeElement = new CKEDITOR.dom.element( tagName );
  150.  
  151.             for (var i in attributes)
  152.             {
  153.                 attributes [ i ] = attributes [ i ].replace(/^\s+|\s+$/g,"");
  154.                 if ( ( i == "width" || i == "height" ) && attributes [ i ] != "" )
  155.                 {
  156.                     attributes [ i ] = parseInt ( attributes [ i ] );
  157.                     if ( attributes [ i ] <= 0 || isNaN (attributes [ i ]) )
  158.                         attributes [i] = "";
  159.                 }
  160.                    
  161.                 if ( attributes[i] != "" )
  162.                     fakeElement.setAttribute( i, attributes[i] );
  163.             }
  164.  
  165.             newFakeImage = editor.createFakeElement( fakeElement, 'cke_' + tagName, tagName, true );
  166.  
  167.             if ( t.fakeImage )
  168.             {
  169.                 newFakeImage.replace( t.fakeImage );
  170.                 editor.getSelection().selectElement( newFakeImage );
  171.             }
  172.             else
  173.                 editor.insertElement( newFakeImage );
  174.  
  175.         }
  176.     };
  177.    
  178.     // extract pubmeCustomTags and update dtd and needed "local" variables
  179.     var pubmeTagNames = [];
  180.     for ( var tagName in pubmeCustomTags )
  181.     {
  182.         // append pubmeTagNames array
  183.         pubmeTagNames.push ( tagName );
  184.        
  185.         // update custom tage dtd definition
  186.         var dtd = CKEDITOR.dtd;
  187.         var customDtd = pubmeCustomTags[ tagName ].dtd;
  188.         dtd[tagName] = 1;
  189.         for (var i in customDtd)
  190.         {
  191.             dtd[customDtd[i]][tagName] = 1;
  192.         }
  193.  
  194.     }
  195.  
  196.    
  197.     CKEDITOR.plugins.add( pubmePluginName,
  198.     {
  199.         init : function( editor )
  200.         {
  201.             for (var tagIndex in pubmeTagNames)
  202.             {
  203.                 pubmeTagName = pubmeTagNames[tagIndex];
  204.                 console.log(pubmeTagName);
  205.  
  206.                 var tagLang = PubMeCKEDITOR[pubmePluginName].getLang( editor, pubmeTagName );
  207.    
  208.                 // create new command
  209.                 editor.addCommand( pubmeTagName, new CKEDITOR.dialogCommand( pubmeTagName ) );
  210.  
  211.                 //
  212.                 var iconImage = this.path + 'images/' + pubmeTagName + '-icon.png';
  213.                
  214.                 // main menu button
  215.                 editor.ui.addButton( pubmeTagName,
  216.                     {
  217.                         label : tagLang.mainMenu || pubmeTagName,
  218.                         command : pubmeTagName,
  219.                         icon : iconImage
  220.                     });
  221.                    
  222.                 // connect with dialog file
  223.                 CKEDITOR.dialog.add( pubmeTagName, this.path + 'dialogs/' + pubmeTagName + '-dialog.js' );
  224.    
  225.                 // If the "menu" plugin is loaded, register the menu items.
  226.                 if ( editor.contextMenu )
  227.                 {
  228.                     editor.addMenuGroup( pubmeTagName );
  229.  
  230.                     var newMenuItems = {};
  231.                     newMenuItems[ pubmeTagName ] =
  232.                     {
  233.                         label : tagLang.properties || pubmeTagName,
  234.                         icon : iconImage,
  235.                         command : pubmeTagName,
  236.                         group : pubmeTagName
  237.                     };
  238.                     editor.addMenuItems ( newMenuItems );                  
  239.                 }
  240.                
  241.                 // bind double click to object
  242.                 /*editor.on( 'doubleclick', function( evt )
  243.                     {
  244.                         var element = evt.data.element;
  245.    
  246.                         if ( element.is( 'img' ) && element.data( 'cke-real-element-type' ) == pubmeTagName )
  247.                             evt.data.dialog = pubmeTagName;
  248.                     });*/
  249.                    
  250.                 // register listeners for contextmenu
  251.                 /*if ( editor.contextMenu )
  252.                 {
  253.                     editor.contextMenu.addListener( function( element, selection )
  254.                         {
  255.                             console.log(element.data( 'cke-real-element-type' ) + ' = ' + tmpTagName);
  256.                             if ( element && element.is( 'img' ) && !element.isReadOnly()
  257.                                     && element.data( 'cke-real-element-type' ) == pubmeTagName )
  258.                                 {
  259.                                     var ret = "var ret = { '" + pubmeTagName + "' : CKEDITOR.TRISTATE_OFF };";
  260.                                     eval (ret);
  261.                                     return ret;
  262.                                 }  
  263.                         });
  264.                 }*/
  265.  
  266.                 // add css for replacement image   
  267.                 editor.addCss(
  268.                     'img.cke_' + pubmeTagName +
  269.                     '{' +
  270.                         'background-image: url(' + CKEDITOR.getUrl( this.path + 'images/' + pubmeTagName + '-placeholder.png' ) + ');' +
  271.                         'background-position: center center;' +
  272.                         'background-repeat: no-repeat;' +
  273.                         'border: 1px solid #a9a9a9;' +
  274.                         'width: 64px;' +
  275.                         'height: 64px;' +
  276.                     '}'
  277.                     );
  278.             }
  279.  
  280.             // register listener for contextmenu
  281.             if ( editor.contextMenu )
  282.             {
  283.                 editor.contextMenu.addListener( function( element, selection )
  284.                 {
  285.                     //if ( element && element.is( 'img' ) && !element.isReadOnly() && element.data( 'cke-real-element-type' ) == pubmeTagName )
  286.                     /**
  287.                      * Fix to handle multi custom tags. Indeed pubmeTagName was referencing always the same value
  288.                      * (the last added).
  289.                      * @author Leward
  290.                      */
  291.                     var tagToTest = element.data( 'cke-real-element-type' );
  292.                     if ( element && element.is( 'img' ) && !element.isReadOnly() && inArray(pubmeTagNames, tagToTest) )
  293.                     {
  294.                         //var ret = "var ret = { '" + pubmeTagName + "' : CKEDITOR.TRISTATE_OFF };";
  295.                         var ret = "var ret = { '" + tagToTest + "' : CKEDITOR.TRISTATE_OFF };";
  296.                         eval (ret);
  297.                         return ret;
  298.                     }  
  299.                 });
  300.             }
  301.  
  302.             // bind double click to object
  303.             editor.on( 'doubleclick', function( evt )
  304.             {
  305.                 var element = evt.data.element;
  306.  
  307.                 //if ( element.is( 'img' ) && element.data( 'cke-real-element-type' ) == pubmeTagName )
  308.                 /**
  309.                  * Fix to handle multi custom tags. Indeed pubmeTagName was referencing always the same value
  310.                  * (the last added).
  311.                  * @author Leward
  312.                  */
  313.                  var tagToTest = element.data( 'cke-real-element-type' );
  314.                  if(element.is( 'img' ) && inArray(pubmeTagNames, tagToTest))
  315.                     evt.data.dialog = tagToTest;
  316.                     //evt.data.dialog = pubmeTagName;
  317.             });
  318.         },
  319.                
  320.         afterInit : function( editor )
  321.         {
  322.  
  323.             for (var tagIndex in pubmeTagNames)
  324.             {
  325.                 pubmeTagName = pubmeTagNames[tagIndex];
  326.        
  327.                 // Tyto chyby jsou jen pri inicializaci - pokud se zada rucne a pak se to ulozi, je to v databazi OK.
  328.                 // TODO  - pridava to divne <p> - chyba je v tom, že fakeImage se normálně formátuje jako obrázek - a ten je inline, tudíž musí být
  329.                 // součástí blokového tagu - a ten je defaultně odstavec.
  330.                 // TODO - v jadru je bug, ktery pri inicializaci tagy v jednom bloku slouci do jednoho (zobrazi jen prvni, ostatni killne - i iframu)
  331.                 //     pozn.: ve skutečnosti to z <tag /><tag /> udělá <tag><tag></tag></tag>!!!
  332.                 var dataProcessor = editor.dataProcessor,
  333.                     dataFilter = dataProcessor && dataProcessor.dataFilter;
  334.                                
  335.                 if ( dataFilter )
  336.                 {
  337.                     var newRules = { elements : {} };
  338.                     newRules.elements[ pubmeTagName ] = function ( element )
  339.                     {
  340.                         var fakeElement = editor.createFakeParserElement( element, 'cke_'+pubmeTagName, pubmeTagName, true );
  341.                         return fakeElement;
  342.                     };
  343.  
  344.                     dataFilter.addRules( newRules );
  345.  
  346.                 }
  347.             }
  348.  
  349.         },
  350.  
  351.         requires : [ 'fakeobjects' ]
  352.     });
  353. })();
RAW Paste Data