Projet

Général

Profil

Paste
Télécharger (10,1 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / media_ckeditor / js / plugins / media / plugin.js @ 98df731a

1
/*
2
Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
3
For licensing, see LICENSE.html or http://ckeditor.com/license
4
*/
5

    
6
/**
7
 * @file Plugin for inserting images from Drupal media module
8
 *
9
 * @TODO Remove all the legecy media wrapper once it's sure nobody uses that
10
 * anymore.
11
 */
12
( function() {
13
  var mediaPluginDefinition = {
14
    icons: 'media',
15
    requires: ['button'],
16
    // All the default distributions of the editor have the widget plugin
17
    // disabled by default.
18
    hasWidgetSupport: false,
19
    mediaLegacyWrappers: false,
20
    onLoad: function() {
21
      // Check if this instance has widget support.
22
      mediaPluginDefinition.hasWidgetSupport = typeof(CKEDITOR.plugins.registered.widget) != 'undefined';
23
      // Add dependency to widget plugin if possible.
24
      if (parseFloat(CKEDITOR.version) >= 4.3 && mediaPluginDefinition.hasWidgetSupport) {
25
        mediaPluginDefinition.requires.push('widget');
26
      }
27
    },
28

    
29
    // Wrap Drupal plugin in a proxy plugin.
30
    init: function(editor){
31
      editor.addCommand( 'media',
32
      {
33
        exec: function (editor) {
34
          var data = {
35
            format: 'html',
36
            node: null,
37
            content: ''
38
          };
39
          var selection = editor.getSelection();
40

    
41
          if (selection) {
42
            data.node = selection.getSelectedElement();
43
            if (data.node) {
44
              data.node = data.node.$;
45
            }
46
            if (selection.getType() == CKEDITOR.SELECTION_TEXT) {
47
              if (CKEDITOR.env.ie && CKEDITOR.env.version < 10) {
48
                data.content = selection.getNative().createRange().text;
49
              }
50
              else {
51
                data.content = selection.getNative().toString();
52
              }
53
            }
54
            else if (data.node) {
55
              // content is supposed to contain the "outerHTML".
56
              data.content = data.node.parentNode.innerHTML;
57
            }
58
          }
59
          Drupal.settings.ckeditor.plugins['media'].invoke(data, Drupal.settings.ckeditor.plugins['media'], editor.name);
60
        }
61
      });
62

    
63
      // Add a Ckeditor context menu item for editing already-inserted media.
64
      if (editor.contextMenu) {
65
        editor.addCommand('mediaConfigure', {
66
          exec: function (editor) {
67
            editor.execCommand('media');
68
          },
69
        });
70

    
71
        editor.addMenuGroup('mediaGroup');
72
        editor.addMenuItem('mediaConfigureItem', {
73
          label: Drupal.t('Media settings'),
74
          icon: this.path + 'images/icon.gif',
75
          command: 'mediaConfigure',
76
          group: 'mediaGroup'
77
        });
78

    
79
        editor.contextMenu.addListener(function(element) {
80
          if (element.getAttribute('data-media-element') ||
81
              element.find('[data-media-element]').count()) {
82
            return { mediaConfigureItem: CKEDITOR.TRISTATE_OFF };
83
          };
84
        });
85
      }
86

    
87
      // Add the toolbar button.
88
      editor.ui.addButton( 'Media',
89
      {
90
        label: 'Add media',
91
        command: 'media',
92
        icon: this.path + 'images/icon.gif'
93
      });
94

    
95
      var ckeditorversion = parseFloat(CKEDITOR.version);
96

    
97
      // Because the media comment wrapper don't work well for CKEditor we
98
      // replace them by using a custom mediawrapper element.
99
      // Instead having
100
      // <!--MEDIA-WRAPPER-START-1--><img /><!--MEDIA-WRAPPER-END-1-->
101
      // We wrap the placeholder with
102
      // <mediawrapper data="1"><img /></mediawrapper>
103
      // That way we can deal better with selections - see selectionChange.
104
      CKEDITOR.dtd['mediawrapper'] = CKEDITOR.dtd;
105
      CKEDITOR.dtd.$blockLimit['mediawrapper'] = 1;
106
      CKEDITOR.dtd.$inline['mediawrapper'] = 1;
107
      CKEDITOR.dtd.$nonEditable['mediawrapper'] = 1;
108
      if (ckeditorversion >= 4.1) {
109
        // Register allowed tag for advanced filtering.
110
        editor.filter.allow( 'mediawrapper[!data]', 'mediawrapper', true);
111
        // Don't remove the data-file_info attribute added by media!
112
        editor.filter.allow( '*[!data-file_info]', 'mediawrapper', true);
113
        // Ensure image tags accept all kinds of attributes.
114
        editor.filter.allow( 'img[*]{*}(*)', 'mediawrapper', true);
115
        // Objects should be selected as a whole in the editor.
116
        CKEDITOR.dtd.$object['mediawrapper'] = 1;
117
      }
118
      function prepareDataForWysiwygMode(data) {
119
        if (typeof Drupal.media !== 'undefined') {
120
          data = Drupal.media.filter.replaceTokenWithPlaceholder(data);
121
        }
122
        // Legacy media wrapper.
123
        mediaPluginDefinition.mediaLegacyWrappers = (data.indexOf("<!--MEDIA-WRAPPER-START-") !== -1);
124
        if (mediaPluginDefinition.mediaLegacyWrappers) {
125
          data = data.replace(/<!--MEDIA-WRAPPER-START-(\d+)-->(.*?)<!--MEDIA-WRAPPER-END-\d+-->/gi, '<mediawrapper data="$1">$2</mediawrapper>');
126
        }
127
        return data;
128
      }
129
      function prepareDataForSourceMode(data) {
130
        var replacement = '$2';
131
        // Legacy wrapper
132
        if (mediaPluginDefinition.mediaLegacyWrappers) {
133
          replacement = '<!--MEDIA-WRAPPER-START-$1-->$2<!--MEDIA-WRAPPER-END-$1-->';
134
        }
135
        data = data.replace(/<mediawrapper data="(.*?)">(.*?)<\/mediawrapper>/gi, replacement);
136
        if (typeof Drupal.media !== 'undefined') {
137
          data = Drupal.media.filter.replacePlaceholderWithToken(data);
138
        }
139
        return data;
140
      }
141

    
142
      // Ensure the tokens are replaced by placeholders while editing.
143
      // Check for widget support.
144
      if (mediaPluginDefinition.hasWidgetSupport) {
145
        editor.widgets.add( 'mediabox',
146
        {
147
          button: 'Create a mediabox',
148
          editables: {},
149
          allowedContent: '*',
150
          upcast: function( element ) {
151
            // Ensure media tokens are converted to media placeholders.
152
            html = Drupal.media.filter.replaceTokenWithPlaceholder(element.getHtml());
153
            // Only replace html if it's different
154
            if (html != element.getHtml()) {
155
              element.setHtml(html);
156
            }
157
            return element.name == 'mediawrapper' || 'data-media-element' in element.attributes;
158
          },
159

    
160
          downcast: function( widgetElement ) {
161
            var token = Drupal.media.filter.replacePlaceholderWithToken(widgetElement.getOuterHtml());
162
            if (token) {
163
              return new CKEDITOR.htmlParser.text(token);
164
            }
165
            return false;
166
          },
167

    
168
          init: function() {
169
            // Add double-click functionality to the widget.
170
            this.on('doubleclick', function(evt) {
171
              editor.execCommand('media');
172
            }, null, null, 5 );
173
          }
174
        });
175
      }
176
      else if (ckeditorversion >= 4) {
177
        // CKEditor >=4.0
178
        editor.on('setData', function( event ) {
179
          event.data.dataValue = prepareDataForWysiwygMode(event.data.dataValue);
180
        });
181
      }
182
      else {
183
        // CKEditor >=3.6 behaviour.
184
        editor.on( 'beforeSetMode', function( event, data ) {
185
          event.removeListener();
186
          var wysiwyg = editor._.modes[ 'wysiwyg' ];
187
          var source = editor._.modes[ 'source' ];
188
          wysiwyg.loadData = CKEDITOR.tools.override( wysiwyg.loadData, function( org )
189
          {
190
            return function( data ) {
191
              return ( org.call( this, prepareDataForWysiwygMode(data)) );
192
            };
193
          } );
194
          source.loadData = CKEDITOR.tools.override( source.loadData, function( org )
195
          {
196
            return function( data ) {
197
              return ( org.call( this, prepareDataForSourceMode(data) ) );
198
            };
199
          } );
200
        });
201
      }
202

    
203
      // Provide alternative to the widget functionality introduced in 4.3.
204
      if (!mediaPluginDefinition.hasWidgetSupport) {
205
        // Ensure tokens instead the html element is saved.
206
        editor.on('getData', function( event ) {
207
          event.data.dataValue = prepareDataForSourceMode(event.data.dataValue);
208
        });
209

    
210
        // Ensure our enclosing wrappers are always included in the selection.
211
        editor.on('selectionChange', function( event ) {
212
          var ranges = editor.getSelection().getRanges().createIterator();
213
          var newRanges = [];
214
          var currRange;
215
          while(currRange = ranges.getNextRange()) {
216
            var commonAncestor = currRange.getCommonAncestor(false);
217
            if (commonAncestor && typeof(commonAncestor.getName) != 'undefined' && commonAncestor.getName() == 'mediawrapper') {
218
              var range = new CKEDITOR.dom.range( editor.document );
219
              if (currRange.collapsed === true) {
220
                // Don't allow selection within the wrapper element.
221
                if (currRange.startOffset == 0) {
222
                  // While v3 plays nice with setting start and end to avoid
223
                  // editing within the media wrapper element, v4 ignores that.
224
                  // Thus we try to move the cursor further away.
225
                  if (parseInt(CKEDITOR.version) > 3) {
226
                    range.setStart(commonAncestor.getPrevious());
227
                    range.setEnd(commonAncestor.getPrevious());
228
                  }
229
                  else {
230
                    range.setStartBefore(commonAncestor);
231
                  }
232
                }
233
                else {
234
                  // While v3 plays nice with setting start and end to avoid
235
                  // editing within the media wrapper element, v4 ignores that.
236
                  // Thus we try to move the cursor further away.
237
                  if (parseInt(CKEDITOR.version) > 3) {
238
                    range.setStart(commonAncestor.getNext(), 1);
239
                    range.setEnd(commonAncestor.getNext(), 1);
240
                  }
241
                  else {
242
                    range.setStartAfter(commonAncestor);
243
                  }
244
                }
245
              }
246
              else {
247
                // Always select the whole wrapper element.
248
                range.setStartBefore(commonAncestor);
249
                range.setEndAfter(commonAncestor);
250
              }
251
              newRanges.push(range);
252
            }
253
          }
254
          if (newRanges.length) {
255
            editor.getSelection().selectRanges(newRanges);
256
          }
257
        });
258
      }
259
    }
260
  };
261

    
262
  CKEDITOR.plugins.add( 'media', mediaPluginDefinition);
263
} )();