diff --git a/picture.module b/picture.module
index 4591968..499d2f0 100644
--- a/picture.module
+++ b/picture.module
@@ -1113,6 +1113,27 @@ function picture_page_build(&$page) {
   drupal_add_library('picture', 'matchmedia', TRUE);
   drupal_add_library('picture', 'picturefill', TRUE);
   drupal_add_library('picture', 'picture.ajax', TRUE);
+
+  // Integrate with the WYSIWYG module, and the CKEditor module.
+  $picture_groups = picture_get_mapping_options();
+  $ckeditor_groups = variable_get('picture_ckeditor_groups', array());
+  $groups = array();
+  // CKEditor library expects an array of options formatted as
+  // ['Display name', 'machine_name'].
+  foreach ($picture_groups as $key => $value) {
+    if ($ckeditor_groups[$key]['enabled'] == 1) {
+      $groups[] = array($value, $key);
+    }
+  }
+  if (!empty($groups)) {
+    $groups[] = array('Not Set', 'not_set');
+    drupal_add_js(array(
+      'picture' => array(
+        'groups' => $groups,
+        'label' => variable_get('picture_ckeditor_label', 'Image size (required)'),
+        ),
+      ), 'setting');
+  }
 }
 
 /**
@@ -1176,69 +1197,40 @@ function picture_image_uri($src) {
 }
 
 /**
- * Implements hook_wysiwyg_plugin to modify the CKEditor image dialog for use
- * with the picture module. The integration technique here is borrowed from
- * imce_wysiwyg.
- *
- * Normally an array of plugin settings would be returned, but since it's
- * problematic to have the WYSIWYG module load a plugin which doesn't have a
- * button (an 'extension', in other words), this module takes care of
- * loading the plugin itself. As a consequence, this plugin does not appear
- * on the WYSIWYG button/plugin configuration page, and is always enabled
- * for all WYSIWYG CKEditor profiles when picture groups have been enabled from
- * /admin/config/media/picture/ckeditor
- * @TODO: low priority - make a checkbox control loading of this extension. The
- * imce_wysiwyg module does this by passing a CKEditor options array in the
- * extension definition which is loaded only when the extension is enabled on
- * the WYSIWYG config page.
- *
- * example code to get started with a checkbox would be:
- *
- * return array(
- *   'picture_ckeditor' => array(
- *       'extensions' => array('picture_ckeditor' => t('Responsive images
- *       with the Picture module')),
- *       'url' => 'http://drupal.org/projects/picture',
- *       'load' => FALSE,
- *     ),
- * );
+ * Implements hook_wysiwyg_plugin() to modify the CKEditor image dialog for use
+ * with the picture module.
  */
 function picture_wysiwyg_plugin($editor, $version) {
-
-  // Keep track of whether the JS has already been added since this hook is
-  // called multiple times on a page load.
-  static $picture_ckeditor_integrated = FALSE;
-
-  if ($editor == 'ckeditor' ) {
-    // Load our invocation scripts.
-    if (!$picture_ckeditor_integrated) {
-      // Create the Javascript array of picture group options.
-      $picture_groups = picture_get_mapping_options();
-      $ckeditor_groups = variable_get('picture_ckeditor_groups', array());
-      $groups = array();
-      // CKEditor expects an array of options formatted as
-      // ['Display name', 'machine_name'].
-      foreach ($picture_groups as $key => $value) {
-        if ($ckeditor_groups[$key]['enabled'] == 1) {
-          $groups[] = array($value, $key);
-        }
-      }
-      if (!empty($groups)) {
-        $groups[] = array('Not Set', 'not_set');
-        drupal_add_js(array(
-          'picture' => array(
-            'groups' => $groups,
-            'label' => variable_get('picture_ckeditor_label', 'Image size (required)'),
-            ),
-          ), 'setting');
-        drupal_add_js(drupal_get_path('module', 'picture') . '/picture_ckeditor.js');
-        $picture_ckeditor_integrated = TRUE;
-      }
-    }
+  if ($editor == 'ckeditor') {
+    return array('picture_ckeditor' => array(
+      'path' => drupal_get_path('module', 'picture') .'/plugins/',
+      'load' => TRUE,
+      'extensions' => array('picture_ckeditor' => t('Responsive images with the Picture Module')),
+      'url' => 'http://drupal.org/projects/picture',
+    ));
   }
 }
 
 /**
+ * Implements hook_ckeditor_plugin() to modify the CKEditor image dialog for use
+ * with the picture module.
+ */
+function picture_ckeditor_plugin() {
+  return array(
+    'picture_ckeditor' => array(
+      // Name of the plugin used to write it.
+      'name' => 'picture_ckeditor',
+      // Description of the plugin - it would be displayed in the plugins management section of profile settings.
+      'desc' => t('Support responsive images with the Picture module.'),
+      // The full path to the CKEditor plugins directory, with the trailing slash.
+      'buttons' => FALSE,
+      'path' => drupal_get_path('module', 'picture') . '/plugins/',
+      'default' => 't',
+    )
+  );
+}
+
+/**
  * Implements hook_uninstall().
  */
 function picture_uninstall() {
diff --git a/picture_ckeditor.js b/picture_ckeditor.js
deleted file mode 100644
index 7e159d2..0000000
--- a/picture_ckeditor.js
+++ /dev/null
@@ -1,177 +0,0 @@
-/**
- * @file picture_ckeditor.js
- * Modify the CKEditor image dialog to insert responsive images.
- *
- * Supports inline responsive images with the Picture module.
- * It also simplifies for the CKEditor image dialog.
- */
-
-CKEDITOR.editorConfig = function(config)
-{
-  // This disables the browser resize handles since the width will now be set
-  // in the image dialog. This also prevents CKEditor from automatically adding
-  // pesky inline width and height styles, although these inline styles are
-  // still added when an image is dragged and dropped.
-  // Resize handles are also removed from tables as an unintended consequence.
-  config.disableObjectResizing = true;
-
-};
-
-// When opening a dialog, a 'definition' is created for it. For
-// each editor instance the 'dialogDefinition' event is then
-// fired. We can use this event to make customizations to the
-// definition of existing dialogs.
-CKEDITOR.on('dialogDefinition', function(event) {
-  // Take the dialog name.
-  var dialogName = event.data.name;
-  // The definition holds the structured data that is used to eventually
-  // build the dialog and we can use it to customize just about anything.
-  // In Drupal terms, it's sort of like CKEditor's version of a Forms API and
-  // what we're doing here is a bit like a hook_form_alter.
-  var dialogDefinition = event.data.definition;
-
-
-  // Resources for the following:
-  // Download: https://github.com/ckeditor/ckeditor-dev
-  // See /plugins/image/dialogs/image.js
-  // and refer to http://docs.ckeditor.com/#!/api/CKEDITOR.dialog.definition
-  // Visit: file:///[path_to_ckeditor-dev]/plugins/devtools/samples/devtools.html
-  // for an excellent way to find machine names for dialog elements.
-  if (dialogName == 'image') {
-    dialogDefinition.removeContents('advanced');
-    dialogDefinition.removeContents('Link');
-    var infoTab = dialogDefinition.getContents('info');
-    var altText = infoTab.get('txtAlt');
-    var IMAGE = 1,
-        LINK = 2,
-        PREVIEW = 4,
-        CLEANUP = 8;
-    // UpdatePreview is copied from ckeditor image plugin.
-    var updatePreview = function(dialog) {
-      // Don't load before onShow.
-      if (!dialog.originalElement || !dialog.preview) {
-        return 1;
-      }
-
-      // Read attributes and update imagePreview.
-      dialog.commitContent(PREVIEW, dialog.preview);
-      return 0;
-    };
-    // Add the select list for choosing the image width.
-    infoTab.add({
-      type: 'select',
-      id: 'imageSize',
-      label: Drupal.settings.picture.label,
-      items: Drupal.settings.picture.groups,
-      'default': 'not_set',
-      onChange: function() {
-        var dialog = this.getDialog();
-        var element = dialog.originalElement;
-        element.setAttribute('data-picture-group', this.getValue());
-        updatePreview(this.getDialog());
-      },
-      setup: function(type, element) {
-        if (type == IMAGE) {
-          var value = element.getAttribute('data-picture-group');
-          this.setValue(value);
-        }
-      },
-      // Create a custom data-picture-group attribute.
-      commit: function(type, element) {
-        if (type == IMAGE) {
-          if (this.getValue() || this.isChanged()) {
-            element.setAttribute('data-picture-group', this.getValue());
-          }
-        } else if (type == PREVIEW) {
-          element.setAttribute('data-picture-group', this.getValue());
-        } else if (type == CLEANUP) {
-          element.setAttribute('data-picture-group', '');
-        }
-      },
-      validate: function() {
-        if (this.getValue() == 'not_set') {
-          var message = 'Please make a selection from ' + Drupal.settings.picture.label;
-          alert(message);
-          return false;
-        } else {
-          return true;
-        }
-      }
-    },
-      // Position before preview.
-      'htmlPreview'
-    );
-
-    // Put a title attribute field on the main 'info' tab.
-    infoTab.add( {
-      type: 'text',
-      id: 'txtTitle',
-      label: 'The title attribute is used as a tooltip when the mouse hovers over the image.',
-      onChange: function() {
-        updatePreview(this.getDialog());
-      },
-      setup: function(type, element) {
-        if (type == IMAGE)
-          this.setValue(element.getAttribute('title'));
-      },
-      commit: function(type, element) {
-        if (type == IMAGE) {
-          if (this.getValue() || this.isChanged())
-            element.setAttribute('title', this.getValue());
-        } else if (type == PREVIEW) {
-          element.setAttribute('title', this.getValue());
-        } else if (type == CLEANUP) {
-          element.removeAttribute('title');
-        }
-      }
-    },
-      // Position before the imageSize select box.
-      'htmlPreview'
-    );
-
-    // Add a select widget to choose image alignment.
-    infoTab.add({
-      type: 'select',
-      id: 'imageAlign',
-      label: 'Image Alignment',
-      items: [ [ 'Not Set', '' ], [ 'Left', 'left'],
-               [ 'Right', 'right' ], [ 'Center', 'center'] ],
-      'default': '',
-      onChange: function() {
-        updatePreview(this.getDialog());
-      },
-      setup: function(type, element) {
-        if (type == IMAGE) {
-          var value = element.getAttribute('data-picture-align');
-          this.setValue(value);
-        }
-      },
-      // Creates a custom data-picture-align attribute since working with classes
-      // is more difficult. If we used classes, then we'd have to search for
-      // exisiting alignment classes and remove them before adding a new one.
-      // With the custom attribute we can always just overwrite it's value.
-      commit: function(type, element) {
-        if (type == IMAGE) {
-          if (this.getValue() || this.isChanged()) {
-            element.setAttribute('data-picture-align', this.getValue());
-          }
-        } else if (type == PREVIEW) {
-          element.setAttribute('data-picture-align', this.getValue());
-        } else if (type == CLEANUP) {
-          element.setAttribute('data-picture-align', '');
-        }
-      }
-
-    },
-      // Position before imageSize.
-      'imageSize'
-    );
-
-    // Improve the alt field label. Copied from Drupal's image field.
-    altText.label = 'The alt attribute may be used by search engines, and screen readers.';
-
-    // Remove a bunch of extraneous fields. These properties will be set in
-    // the theme or module CSS.
-    infoTab.remove('basic');
-  }
-});
diff --git a/plugins/plugin.js b/plugins/plugin.js
new file mode 100644
index 0000000..14eed86
--- /dev/null
+++ b/plugins/plugin.js
@@ -0,0 +1,180 @@
+/**
+ * @file Plugin to support responsive images with the Picture module and 
+ * the CKEditor module.
+ */
+( function(){
+  CKEDITOR.plugins.add('picture_ckeditor',
+  {
+      init : function(editor)
+      {
+                
+          // This disables the browser resize handles since the width will now be set
+          // in the image dialog. This also prevents CKEditor from automatically adding
+          // pesky inline width and height styles, although these inline styles are
+          // still added when an image is dragged and dropped.
+          // Resize handles are also removed from tables as an unintended consequence.
+        CKEDITOR.config.disableObjectResizing = true; 
+
+
+        // When opening a dialog, a 'definition' is created for it. For
+        // each editor instance the 'dialogDefinition' event is then
+        // fired. We can use this event to make customizations to the
+        // definition of existing dialogs.
+        CKEDITOR.on('dialogDefinition', function(event) {
+          // Take the dialog name.
+          if ((event.editor != editor)) return;
+          var dialogName = event.data.name;
+          // The definition holds the structured data that is used to eventually
+          // build the dialog and we can use it to customize just about anything.
+          // In Drupal terms, it's sort of like CKEditor's version of a Forms API and
+          // what we're doing here is a bit like a hook_form_alter.
+          var dialogDefinition = event.data.definition;
+
+
+          // Resources for the following:
+          // Download: https://github.com/ckeditor/ckeditor-dev
+          // See /plugins/image/dialogs/image.js
+          // and refer to http://docs.ckeditor.com/#!/api/CKEDITOR.dialog.definition
+          // Visit: file:///[path_to_ckeditor-dev]/plugins/devtools/samples/devtools.html
+          // for an excellent way to find machine names for dialog elements.
+          if (dialogName == 'image') {
+            dialogDefinition.removeContents('advanced');
+            dialogDefinition.removeContents('Link');
+            var infoTab = dialogDefinition.getContents('info');
+            var altText = infoTab.get('txtAlt');
+            var IMAGE = 1,
+                LINK = 2,
+                PREVIEW = 4,
+                CLEANUP = 8;
+            // UpdatePreview is copied from ckeditor image plugin.
+            var updatePreview = function(dialog) {
+              // Don't load before onShow.
+              if (!dialog.originalElement || !dialog.preview) {
+                return 1;
+              }
+
+              // Read attributes and update imagePreview.
+              dialog.commitContent(PREVIEW, dialog.preview);
+              return 0;
+            };
+            // Add the select list for choosing the image width.
+            infoTab.add({
+              type: 'select',
+              id: 'imageSize',
+              label: Drupal.settings.picture.label,
+              items: Drupal.settings.picture.groups,
+              'default': 'not_set',
+              onChange: function() {
+                var dialog = this.getDialog();
+                var element = dialog.originalElement;
+                element.setAttribute('data-picture-group', this.getValue());
+                updatePreview(this.getDialog());
+              },
+              setup: function(type, element) {
+                if (type == IMAGE) {
+                  var value = element.getAttribute('data-picture-group');
+                  this.setValue(value);
+                }
+              },
+              // Create a custom data-picture-group attribute.
+              commit: function(type, element) {
+                if (type == IMAGE) {
+                  if (this.getValue() || this.isChanged()) {
+                    element.setAttribute('data-picture-group', this.getValue());
+                  }
+                } else if (type == PREVIEW) {
+                  element.setAttribute('data-picture-group', this.getValue());
+                } else if (type == CLEANUP) {
+                  element.setAttribute('data-picture-group', '');
+                }
+              },
+              validate: function() {
+                if (this.getValue() == 'not_set') {
+                  var message = 'Please make a selection from ' + Drupal.settings.picture.label;
+                  alert(message);
+                  return false;
+                } else {
+                  return true;
+                }
+              }
+            },
+              // Position before preview.
+              'htmlPreview'
+            );
+
+            // Put a title attribute field on the main 'info' tab.
+            infoTab.add( {
+              type: 'text',
+              id: 'txtTitle',
+              label: 'The title attribute is used as a tooltip when the mouse hovers over the image.',
+              onChange: function() {
+                updatePreview(this.getDialog());
+              },
+              setup: function(type, element) {
+                if (type == IMAGE)
+                  this.setValue(element.getAttribute('title'));
+              },
+              commit: function(type, element) {
+                if (type == IMAGE) {
+                  if (this.getValue() || this.isChanged())
+                    element.setAttribute('title', this.getValue());
+                } else if (type == PREVIEW) {
+                  element.setAttribute('title', this.getValue());
+                } else if (type == CLEANUP) {
+                  element.removeAttribute('title');
+                }
+              }
+            },
+              // Position before the imageSize select box.
+              'htmlPreview'
+            );
+
+            // Add a select widget to choose image alignment.
+            infoTab.add({
+              type: 'select',
+              id: 'imageAlign',
+              label: 'Image Alignment',
+              items: [ [ 'Not Set', '' ], [ 'Left', 'left'],
+                       [ 'Right', 'right' ], [ 'Center', 'center'] ],
+              'default': '',
+              onChange: function() {
+                updatePreview(this.getDialog());
+              },
+              setup: function(type, element) {
+                if (type == IMAGE) {
+                  var value = element.getAttribute('data-picture-align');
+                  this.setValue(value);
+                }
+              },
+              // Creates a custom data-picture-align attribute since working with classes
+              // is more difficult. If we used classes, then we'd have to search for
+              // exisiting alignment classes and remove them before adding a new one.
+              // With the custom attribute we can always just overwrite it's value.
+              commit: function(type, element) {
+                if (type == IMAGE) {
+                  if (this.getValue() || this.isChanged()) {
+                    element.setAttribute('data-picture-align', this.getValue());
+                  }
+                } else if (type == PREVIEW) {
+                  element.setAttribute('data-picture-align', this.getValue());
+                } else if (type == CLEANUP) {
+                  element.setAttribute('data-picture-align', '');
+                }
+              }
+
+            },
+              // Position before imageSize.
+              'imageSize'
+            );
+
+            // Improve the alt field label. Copied from Drupal's image field.
+            altText.label = 'The alt attribute may be used by search engines, and screen readers.';
+
+            // Remove a bunch of extraneous fields. These properties will be set in
+            // the theme or module CSS.
+            infoTab.remove('basic');
+          }
+        });
+      }
+  });
+})();
