changeset 2:5a44c430b7ac

Added dnd_test module, tons and tons of fixes and changes.
author David Eads <eads@chicagotech.org>
date Tue, 17 Feb 2009 15:34:56 -0600
parents cee053085755
children 5df0783706f7
files dnd-library.tpl.php dnd.admin.inc dnd.info dnd.install dnd.module dnd_test/dnd_test.css dnd_test/dnd_test.info dnd_test/dnd_test.module dnd_test/img-backup/page-1-large.jpg dnd_test/img-backup/page-1-small.jpg dnd_test/img-backup/page-2-large.jpg dnd_test/img-backup/page-2-small.jpg dnd_test/img/page-1-large.jpg dnd_test/img/page-1-small.jpg dnd_test/img/page-2-large.jpg dnd_test/img/page-2-small.jpg js/dnd-library.js
diffstat 17 files changed, 280 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dnd-library.tpl.php	Tue Feb 17 15:34:56 2009 -0600
@@ -0,0 +1,11 @@
+<div id="<?php print $library_id; ?>">
+  <div class="header">
+    <?php print $header; ?>
+  </div>
+  <div class="library">
+    <?php print implode('', $items); ?>
+  </div>
+  <div class="footer">
+    <?php print $footer; ?>
+  </div>
+</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dnd.admin.inc	Tue Feb 17 15:34:56 2009 -0600
@@ -0,0 +1,5 @@
+<?php
+
+function dnd_admin() {
+  return 'stub';
+}
--- a/dnd.info	Mon Feb 16 01:39:54 2009 -0600
+++ b/dnd.info	Tue Feb 17 15:34:56 2009 -0600
@@ -1,6 +1,6 @@
 ; $Id$
 name = DnD Library
-package = User Interface
+package = User interface
 description = Enable a drag and drop media interface for rich text editors.
 dependencies[] = wysiwyg
 core = 6.x
--- a/dnd.install	Mon Feb 16 01:39:54 2009 -0600
+++ b/dnd.install	Tue Feb 17 15:34:56 2009 -0600
@@ -10,6 +10,7 @@
     'fields' => array(
       'textarea' => array('type' => 'varchar', 'not null' => TRUE),
       'source' => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE),
+      'settings' => array('type' => 'text', 'default' => ''),
     ),
     'primary key' => array('textarea'),
   );
--- a/dnd.module	Mon Feb 16 01:39:54 2009 -0600
+++ b/dnd.module	Tue Feb 17 15:34:56 2009 -0600
@@ -1,5 +1,8 @@
 <?php
 
+// A suffix for auto generated IDs
+define(DND_ID_SUFFIX, '-dnd-library');
+
 /**
  * Implementation of hook_menu().
  */
@@ -21,3 +24,120 @@
 function dnd_perm() {
   return array('administer dnd');
 }
+
+/**
+ * Implementation of hook_theme().
+ */
+function dnd_theme() {
+  return array(
+    'dnd_library' => array('arguments' => array('element' => NULL, 'settings' => NULL), 'template' => 'dnd-library'),
+  );
+}
+
+
+/**
+ * Implementation of hook_elements().
+ *
+ * Overload textareas.
+ */
+function dnd_elements() {
+  $type = array();
+  $type['textarea'] = array(
+    '#input' => TRUE, 
+    '#cols' => 60, 
+    '#rows' => 5, 
+    '#resizable' => TRUE,
+    '#dnd-enabled' => FALSE,
+    '#dnd-settings' => NULL,
+    '#process' => array('form_expand_ahah', 'dnd_process_textarea'),
+  );
+  return $type;
+}
+
+/**
+ * Settings array:
+ * What should it take, if anything?  Probably a source...
+ * maybe editor specific configuration shit? 
+ *
+ * - source for library json/ajax shit
+ * - target selector
+ * - item selector
+ *
+ * perhaps like so:  
+ *
+ * global => 
+ *   droppable targets
+ *   library source for textarea
+ * 
+ * tinymce/othereditor =>
+ *   target selector logic
+ *   configuration options
+ *   callback should be smart about attachment and detachment
+ */
+function dnd_process_textarea($element, $form_state) {
+  if ($element['#dnd-enabled']) {
+
+    drupal_add_js(drupal_get_path('module', 'dnd') .'/dnd/dnd.js');
+    drupal_add_js(drupal_get_path('module', 'dnd') .'/js/dnd-library.js', 'footer');
+
+    $settings = array();
+
+    // We take a string or an 
+    if (is_string($element['#dnd-settings'])) {
+      // @TODO load settings
+    } 
+    else if (is_object($element['#dnd-settings'])) {
+      $settings = (array) $element['#dnd-settings'];
+    }
+    else if (is_array($element['#dnd-settings'])) {
+      $settings = $element['#dnd-settings'];
+    }
+
+    // Set some important defaults
+    $settings = array('library_id' => $element['#id'] . DND_ID_SUFFIX) + $settings;
+
+    // Add enabled libraries to settings for tracking
+    drupal_add_js(array(
+      'dndEnabledLibraries' => array($element['#id'] => $settings),
+    ), 'setting');
+
+    $element['#prefix'] = theme('dnd_library', $element, $settings);
+  }
+  return $element;
+}
+
+function template_preprocess_dnd_library(&$variables) {
+  global $base_url;
+  list($element, $settings) = array($variables['element'], $variables['settings']);
+
+  // Get library via a backdoor HTTP request.  This is plenty fast for this
+  // application and keeps things nice and consistent.
+  if (!($url = parse_url($settings['url']))) {
+    return t('This library is not available');
+  }
+
+  // Handle both relative and absolute urls
+  if (!isset($url['scheme'])) {
+    $settings['url'] = $base_url .'/'. $settings['url'];
+  }
+
+  $request = drupal_http_request($settings['url']);
+
+  // We must remove some Drupal escaping
+  $json = json_decode(str_replace(array('\x3c', '\x3e', '\x26'), array("<", ">", "&"), $request->data), TRUE);
+
+  foreach ($json['library'] as $id=>$item) {
+    $editor_representations[$id] = filter_xss_admin($item['editor']);
+    $library_representations[$id] = filter_xss_admin($item['library']);
+  }
+
+  $variables['library_id'] = $settings['library_id'];
+  $variables['header'] = filter_xss_admin($json['header']);
+  $variables['items'] = $library_representations;
+  $variables['footer'] = filter_xss_admin($json['footer']);
+
+  // Store editor representations in Drupal setting
+  drupal_add_js(array(
+    'dndEditorRepresentations' => $editor_representations, 
+  ), 'setting');
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dnd_test/dnd_test.css	Tue Feb 17 15:34:56 2009 -0600
@@ -0,0 +1,25 @@
+.body-field-wrapper {
+  float: left;
+  width: 100%;
+}
+
+#edit-body-dnd-library {
+  float: left;
+  width: 15%;
+  text-align: center;
+}
+#edit-body-dnd-library img {
+  display: block;
+  margin: 2px auto;
+}
+#edit-body-dnd-library .library a {
+  color: #000;
+  display: block;
+  padding: 4px;
+  margin-bottom: 6px;
+  text-decoration: none;
+}
+#edit-body-wrapper {
+  float: left;
+  width: 85%;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dnd_test/dnd_test.info	Tue Feb 17 15:34:56 2009 -0600
@@ -0,0 +1,7 @@
+; $Id$
+name = DnD Library Tests
+package = User interface
+description = Defines some menu callbacks and form alterations which test the drag and drop plugin.
+dependencies[] = dnd
+core = 6.x
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dnd_test/dnd_test.module	Tue Feb 17 15:34:56 2009 -0600
@@ -0,0 +1,46 @@
+<?php
+
+function dnd_test_menu() {
+  $items = array();
+  $items['dnd-test/library'] = array(
+    'title' => 'Drag and drop test library',
+    'page callback' => 'dnd_test_library',
+    'access arguments' => array('access dnd test library'),
+  );
+  return $items;
+}
+
+function dnd_test_perm() {
+  return array('access dnd test library');
+}
+
+function dnd_test_form_alter(&$form, &$form_state) {
+  if ($form['#id'] == 'node-form' && $form['type']['#value'] == 'page') {
+    drupal_add_css(drupal_get_path('module', 'dnd_test') .'/dnd_test.css');
+    $form['body_field']['body']['#dnd-enabled'] = TRUE;
+    $form['body_field']['body']['#dnd-settings'] = array(
+      'drop_selector' => '#edit-body-dnd-library .drop',
+      'url' => 'dnd-test/library',
+    );
+    $form['body_field']['body']['#rows'] = 28;
+  }
+}
+
+function dnd_test_library() {
+
+  $var = array(
+    'header' => '<h3>Test library</h3>',
+    'footer' => '<div class="pager">'. l(1, 'dnd-test/library') . ' '. l(2, 'dnd-test/library', array('query' => array('page' => 2))) .'</div>',
+  );
+  $modifier = ($_GET['page'] == 2) ? 'page-2' : 'page-1';
+  for ($i=1; $i < 6; $i++) {
+    $library = '<div class="row"><a href="" class="drop" id="image-'. $i .'-'. $modifier .'">'. theme('image', drupal_get_path('module', 'dnd_test') .'/img/'. $modifier .'-small.jpg') .'Image '. $i .'</a></div>';
+    $editor = theme('image', drupal_get_path('module', 'dnd_test') .'/img/'. $modifier .'-large.jpg');
+    $var['library']['image-'. $i .'-'. $modifier] = array(
+      'library' => $library,
+      'editor'  => $editor,
+    );
+  }
+  drupal_json($var);
+  exit();
+}
Binary file dnd_test/img-backup/page-1-large.jpg has changed
Binary file dnd_test/img-backup/page-1-small.jpg has changed
Binary file dnd_test/img-backup/page-2-large.jpg has changed
Binary file dnd_test/img-backup/page-2-small.jpg has changed
Binary file dnd_test/img/page-1-large.jpg has changed
Binary file dnd_test/img/page-1-small.jpg has changed
Binary file dnd_test/img/page-2-large.jpg has changed
Binary file dnd_test/img/page-2-small.jpg has changed
--- a/js/dnd-library.js	Mon Feb 16 01:39:54 2009 -0600
+++ b/js/dnd-library.js	Tue Feb 17 15:34:56 2009 -0600
@@ -0,0 +1,64 @@
+Drupal.behaviors.dndLibrary = function(context) {
+  var libraries = Drupal.settings.dndEnabledLibraries;
+
+  // Loop over libraries keyed by the textarea they are associated with
+  for (var textarea_id in libraries) {
+
+    var library = $('#' + textarea_id + '-dnd-library');
+
+    // Ajax pager:  This seems like it is bad to be here
+    $('.pager a', library).click(function(e, data) {
+      $.getJSON(this.href, function(data) {
+        $('.library', library).html('');
+        for (item in data.library) {
+          $('.library', library).append(data.library[item].library);
+          Drupal.settings.dndEditorRepresentations[item] = data.library[item].editor;
+          Drupal.behaviors.dndLibrary(context);  // Durn event reattachment
+        }
+      });
+      return false;
+    });
+
+    // Bind Drag and Drop plugin invocation to wywsiwygAttach event
+    $('#' + textarea_id).bind('wysiwygAttach', function(e, data) {
+      var settings = {
+        renderRepresentation: function(target, drop, representation_id) {
+          console.log(representation_id);
+          return Drupal.settings.dndEditorRepresentations[representation_id];
+        }
+      }
+      settings = $.extend(settings, libraries[textarea_id]);
+
+      // Get editor attachment function
+      var editor_fn = 'attach_' + data.editor;
+      if ($.isFunction(window.Drupal.behaviors.dndLibrary[editor_fn])) {
+        window.Drupal.behaviors.dndLibrary[editor_fn](data, settings); 
+      }
+    });
+
+    // @TODO track and clear intervals to save memory at the cost of 
+    // more processing?
+    $('#' + textarea_id).bind('wysiwygDetach', function(e, data) {
+      console.log('detach');
+    });
+  }
+}
+
+Drupal.behaviors.dndLibrary.attach_tinymce = function(data, settings) {
+  var tiny = tinyMCE.getInstanceById(data.field);
+  $('#'+ data.field +'-wrapper iframe').load(function() {
+    settings = $.extend({
+      targets: $('#'+ data.field +'-wrapper iframe'),
+      insertAfter: '<p><span id="__caret">_</span></p>',
+      postprocessDrop: function() {
+        // Get our special span, select it, delete it, and hope the caret
+        // resets correctly.
+        tiny.selection.select(tiny.dom.get('__caret'));
+        tiny.execCommand('Delete', false, null);
+				tiny.dom.remove('__caret');
+      }
+    }, settings);
+
+    $(settings.drop_selector).dnd(settings);
+  });
+}