CKEditor 4 के लिए एक प्लगइन लिखना

CKEditor ब्राउज़रों के लिए एक WYSIWYG HTML संपादक है। जब भी मैं इसके डॉक्यूमेंटेशन या इसके सोर्स कोड, इसके प्लग इन के सोर्स कोड के सामने आया, मैं हार गया। और यह आश्चर्य की बात नहीं है, क्योंकि सीकेएडिटर एक बहुत बड़ा उत्पाद है जो एक जटिल संरचना के साथ है। लेकिन, अक्सर, मानक विशेषताएं पर्याप्त नहीं होती हैं और आपको अपना स्वयं का जोड़ना पड़ता है। इस लेख में, मैं एक प्लगइन पर ध्यान केंद्रित करना चाहता हूं जो आपको संपादक में यैंडेक्स-कार्ड को एम्बेड और संचालित करने की अनुमति देता है।

यह संपादन के अंत में दिखेगा:


और इसलिए संपादन मोड में:


कार्य सिद्धांत


So. आइए निर्धारित करें कि हम भविष्य के टूल को काम में कैसे देखना चाहते हैं। यह आवश्यक है कि कार्ड को दस्तावेज़ में एम्बेड किया जा सकता है, इसे हटा दिया गया है और इसके किसी भी पैरामीटर को बदलना संभव था। क्योंकि HTML संपादन मोड में <script /> के साथ काम करना कम से कम एक तुच्छ कार्य नहीं है, फिर हम मानक फर्जी विशेषण प्लगइन का उपयोग करेंगे, जो हमें अपने HTML को कुछ और समय के लिए सुविधाजनक बनाने की अनुमति देता है, अधिक सटीक, <img /> (यह फर्जीवाड़ा है जो उनका उपयोग करता है)। अन्य बातों के अलावा, हमें मानचित्र सेटिंग्स को संपादित करने के लिए एक "संवाद" प्लगइन की आवश्यकता है। मैं तुरंत ध्यान दूंगा कि प्लगिन आदिम हो जाएगा, जैसे कि मेरे पास कुछ भी जटिल करने का काम नहीं था। प्लगइन आपको 2 निर्देशांक (अक्षांश और देशांतर), स्केल (1-17) के मूल्यों का उपयोग करके एक मानचित्र रखने की अनुमति देगा, नक्शे पर एक लेबल लगाने में सक्षम होगा, साथ ही साथ मानचित्र के तहत एक विवरण के साथ पाठ भी।

क्योंकि यैंडेक्स-कार्ड एक ऐसी वस्तु है जो गतिशील रूप से जुड़ा हुआ है, और अनावश्यक <script /> s एम्बेड कर रहा है, साथ या इसके बिना, एक कृतघ्न कार्य, मुझे आउटपुट पर निम्न HTML कोड प्राप्त होगा: <em data-plugin = "- jon -data -"> MAP < / ईएम>। और एक साधारण जावास्क्रिप्ट फ़ंक्शन की सहायता से, यैंडेक्सपैप एपीआई का उपयोग करके <em /> गाड़ी को एक कार्ड में बदल दें।

मैं यह नोट करना चाहता हूं कि कई मामलों में मैं मानक प्लगइन "फ्लैश" के काम पर निर्भर था, इसलिए कुछ चीजें जो मैं उपयोग करता हूं, वे पूरी तरह से मेरे द्वारा समझ में नहीं आती हैं। अधूरे दस्तावेज के कारण, आंशिक रूप से मेरी समझ में कमी के कारण। मैंने स्रोत कोड के आधार पर अधिकांश निष्कर्ष निकाले, और स्टैकऑवरफ्लो में प्रतिक्रिया डेटाबेस पर भाग लिया।

प्लगइन निर्माण


सुविधा के लिए, हम सभी प्लगइन कोड को एक स्व-निष्पादित अनाम फ़ंक्शन के अंदर रखेंगे:
function() { /* code */ } )(); 


सिस्टम में एक प्लगइन जोड़ने के लिए, हम उपयोग करेंगे:
 CKEDITOR.plugins.add( 'ymap' /*   */, //      { //  requires: [ 'dialog', 'fakeobjects' ], //      init: function( editor /*   -   */ ) { }, //     ,      API afterInit: function( editor ) { } } ); 


Init पर अधिक:
 this._initTranslations( editor ); // ,    var req = 'em' /* tag */ + '[!data-plugin,!width,!height]' /* attrs */ + '(' + ymap_class_name + ')' /* classes */ + '{width,height}' /* styles */; //      editor.addCommand( 'ymap', new CKEDITOR.dialogCommand( 'ymap', { allowedContent: req } ) ); //      editor.ui.addButton( 'YMap', { label: lang.button_label, command: 'ymap' } ); //    CKEDITOR.dialog.add( 'ymap', add_dialog /* ,    */ ); //      - //     fakeobject -    editor.on( 'doubleclick', function( evt ) { var element = evt.data.element; if( element.is('img') && element.data('cke-real-element-type') == 'ymap' ) { evt.data.dialog = 'ymap'; } } ); 

नई टीम बनाते समय सबसे महत्वपूर्ण बिंदु अनुमतकंटेंट की परिभाषा है। तथ्य यह है कि CKEditor 4 में उन्होंने एक नई प्रणाली जोड़ी है - "अनुमत सामग्री नियम"। यह प्रणाली गलत HTML कोड के खिलाफ लड़ती है (उदाहरण के लिए, जब बाहर से चिपकती है)। यह HTML कोड से अतिरिक्त टैग, विशेषताएँ, शैलियाँ और कक्षाएं निकालता है। और सिस्टम में यह स्पष्ट करने के लिए कि क्या अतिशयोक्तिपूर्ण है और क्या नहीं है, कमांड दर्ज करते समय, हम एक ऑब्जेक्ट निर्दिष्ट करते हैं जिसमें अनुमत और आवश्यक क्षेत्र शामिल हो सकते हैं। पहले का कार्य अवसरों का अनुरोध करना है, दूसरे का कार्य कमांड को अक्षम करना है यदि पर्याप्त अवसर नहीं हैं। यह मेरे लिए केवल अनुमत अनुमति का उपयोग करने के लिए पर्याप्त था। इसके काम के सिद्धांत यहां देखे जा सकते हैं । मैं सबसे बुनियादी पर ध्यान केंद्रित करूंगा:

स्थानीयकरण के साथ एक अलग पल। आप इसे अपनी इच्छानुसार व्यवस्थित करने के लिए स्वतंत्र हैं; मैं निम्नलिखित दृष्टिकोण पर बस गया:
 var translations = { ru: { fake_object_label: 'Yandex ', title: 'Yandex ', // ... }, en: { fake_object_label: 'Yandex Map', title: 'Yandex Map', // ... }, def: 'ru' }; var lang; // shotrcut // ... CKEDITOR.plugins.add( 'ymap', { // ... _initTranslations: function( editor ) { var current_lang = CKEDITOR.lang.detect(); CKEDITOR.lang[ current_lang ]['ymap'] = translations[ current_lang ] ? translations[ current_lang ] : translations[ translations.def_lang ]; lang = editor.lang.ymap; //      fakeobject editor.lang.fakeobjects.ymap = lang.fake_object_label; }, // ... } ); 


afterInit


इस फ़ंक्शन के कोड में, हम अपने स्वयं के संपादक के फ़िल्टर में जोड़ देंगे, जो कि स्रोत कोड मोड से स्विच करते समय (या बस जब संपादक आरंभ किया जाता है) संपादन मोड में, हमें नकली कोड के साथ वास्तविक कोड को बदलने की अनुमति देगा:

 afterInit: function( editor ) { //     var dataProcessor = editor.dataProcessor, dataFilter = dataProcessor && dataProcessor.dataFilter; if( dataFilter ) { //     dataFilter.addRules ( { //   elements: { //       em.    //   ,    inline-,  //   CKEditor-     //  P- 'em': function( el ) { //   em -  Ymap,    if( ! is_plugin_node( el ) ) { for( var i = 0 ; i < el.children.length; ++ i ) { if( el.children[ i ].name === 'cke:ymap' ) { if( ! is_plugin_node( el.children[ i ] ) ) { return null; //    } //   fakeobject return create_fake_element( editor, el ); } } return null; //    } //  -   fakeobject return create_fake_element( editor, el ); } } }, 1 /*   */ ) } // if dataFilter } 


जाँच करने के लिए कि क्या आइटम एक "नक्शा" है
 var is_plugin_node = function( el ) { return el.attributes['class'] === ymap_class_name; }; 


उन्हें नकली में बदलने का कार्य:
 var create_fake_element = function( editor, real_el ) { //  ,   IMG,  ,  return editor.createFakeParserElement( real_el, 'cke_ymap', 'ymap', true ); }; 

स्ट्रेचबिलिटी के द्वारा, किसी को ऑब्जेक्ट की चौड़ाई और ऊंचाई होने की संभावना को समझना चाहिए। यदि गलत है, तो नकली तत्व मूल तत्व की चौड़ाई और ऊंचाई विरासत में नहीं मिलेगा।

संवाद


इसलिए हम सबसे महत्वपूर्ण बात पर आते हैं - संवाद। लगभग सब कुछ इसमें है। यह इस प्रकार वर्णित है:
 var add_dialog = function( editor ) { var dialog = { title: lang.title, //   //    width: 300, height: 100, //    —  , ,  … contents: [ ], //  onShow: function(){}, onOk: function(){} }; return dialog; }; 


खैर, अब क्रम में। चलो घटकों के साथ शुरू करते हैं:
 { // , ,   1,     id: 'tab_info', expand: true, padding: 0, elements: [ { //  id: 'name', type: 'text', label: lang.f_name, commit: commit, setup: load }, { //  id: 'label', type: 'text', label: lang.f_label, commit: commit, setup: load }, { // . type: 'hbox', align: 'left', children: [ { // latitude id: 'lon', type: 'text', label: lang.f_lat, commit: commit, validate: CKEDITOR.dialog.validate .regex( /^[\d\,\.]+$/, lang.inc_coord ), setup: load, 'default': '43.2503' }, // … 


आप घटकों के लिए निम्नलिखित हैंडलर सेट कर सकते हैं:

आईडी फ़ील्ड का उपयोग घटक के पहचानकर्ता के रूप में किया जाता है, न कि एक विशेषता के रूप में। आप CKEDITOR.dialog.validate ऑब्जेक्ट में सभी प्रकार के तैयार किए गए सत्यापनकर्ता देख सकते हैं।

onShow


जैसा कि आप अनुमान लगा सकते हैं, जब संवाद प्रदर्शित होता है तो यह विधि कहलाएगी। इसमें हमारा कार्य सभी तैयारी करना और खेतों के मूल्यों को भरना है यदि कॉल से पहले हमारे फर्जीवाड़े को उजागर किया गया था।

 //     this.fake_image = this.ymap_node = null; //     -     var fake_image = this.getSelectedElement(); //    ... if( fake_image && fake_image.data( 'cke-real-element-type' ) === 'ymap' ) { this.fake_image = fake_image; //     EM- (   ,   //  ) this.ymap_node = editor.restoreRealElement( fake_image ); // ..       JSON   "data-plugin", //       cfg var cfg = JSON.parse( this.ymap_node.getAttribute('data-plugin') ) //    setup    . //  setup-    ,    // .     cfg this.setupContent( cfg ); } 


सेटअप फ़ंक्शन (घटकों के लिए):
 var load = function( cfg ) { //      -   cfg //       data-plugin  //      (   :) ) this.setValue( cfg[ '_' + this.id ] ); }; 


onOk


यह फ़ंक्शन तब कहा जाता है जब उपयोगकर्ता ने संवाद में "ओके" बटन पर क्लिक किया, और सभी फ़ील्ड में त्रुटियां नहीं थीं। हमारे सभी कार्यों में सबसे महत्वपूर्ण है :) इसमें हम फर्जीवाड़ा करते हैं और उसमें हेरफेर करते हैं, और अंतिम EM-ku भी बनाते हैं।
 // this.fake_image    onShow,  //     fakeobject //   ,          //      if( ! this.fake_image ) { //   EM- var node = CKEDITOR.dom.element .createFromHtml( '<cke:em>MAP</cke:em>', editor.document ); //      node.addClass( ymap_class_name ); } else { //      //    EM-  , //     onShow //  restoreRealElement var node = this.ymap_node; } //      var extra_styles = {}, extra_attributes = {}; //    commit      //       load. //       ,    //     this.commitContent( node, extra_styles, extra_attributes ); //    EM- node.setStyles( extra_styles ); //   -      node.$.setAttribute( 'data-plugin', JSON.stringify( extra_attributes ) ); //   fakeobject- //   - ,     //   - ,     IMG //   -    //  -          var new_fake_image = editor.createFakeElement( node, 'cke_ymap', 'ymap', true ); new_fake_image.setAttributes( extra_attributes ); new_fake_image.setStyles( extra_styles ); //      fakeobject if( this.fake_image ) { //    new_fake_image.replace( this.fake_image ); //   editor.getSelection().selectElement( new_fake_image ); } else { //       //     -  //     editor.insertElement( new_fake_image ); } 


घटकों का प्रतिबद्ध कार्य (हम इसे जबरन कमिटमेंट का उपयोग करके कहते हैं):
 var commit = function( ymap, styles, attrs ) { var value = this.getValue(); if( this.id === 'width' || this.id === 'height' ) { //       //       styles[ this.id ] = value; } else if( this.id === 'lat' || this.id === 'lon' ) { //      -     value = value.replace( ',', '.' ); } //     , //    onOk     data-plugin attrs[ '_' + this.id ] = value; }; 


मैं ध्यान देता हूं कि यदि यह मान लिया जाए कि वस्तु में चौड़ाई और ऊंचाई के क्षेत्र हैं, तो उनका उपयोग किया जाना चाहिए, अन्यथा अनुमत सामग्री बंद हो सकती है :(

सीएसएस



CSS में, हमें EM के लिए और IMG के फर्जी अंक के लिए उपस्थिति सेट करने की आवश्यकता है। EM के लिए उपस्थिति आपकी साइट की शैलियों में सेट होती है, और IMG की शैली शैलियों में संपादक से जुड़ती है। वे भी जेएस के माध्यम से सेट किया जा सकता है, का उपयोग कर:
 CKEDITOR.addCss( 'img.cke_ymap { /* css */ }' ); 


परिणाम


एक पूरे के रूप में प्लगइन जटिल नहीं था। इसका कारण नकली नोट प्लगइन की उपस्थिति और तथ्य यह है कि हम एक ब्लॉक ऑब्जेक्ट के साथ काम करते हैं। मेरा मानना ​​है कि लोअरकेस टैग के साथ काम करना अधिक जटिल है क्योंकि उपयोगकर्ता पाठ का चयन कर सकता है ताकि विभिन्न टैग की सामग्री के अलग-अलग हिस्से इसमें मिल जाएं। हालाँकि, मैंने कोशिश नहीं की :)

यदि वांछित है, तो हम एक संदर्भ मेनू को हमारे प्लगइन से जोड़ सकते हैं, फ़ील्ड जोड़ सकते हैं (उदाहरण के लिए, आप कई लेबल निर्दिष्ट करते हैं, और न केवल एक), एक पूर्वावलोकन पैनल, और बहुत कुछ।

प्लगइन यहाँ (github) स्थित है । भंडार में YandexMaps से जुड़ने का एक उदाहरण भी है। लेकिन, वास्तव में, आप किसी अन्य ऑनलाइन कार्ड सेवा का उपयोग कर सकते हैं।

संदर्भ


Source: https://habr.com/ru/post/In204176/


All Articles