From f3233d8134be6b35d35c45403d3bb893b329c23a Mon Sep 17 00:00:00 2001
From: James Elliott <james.elliott@acquia.com>
Date: Tue, 19 Apr 2011 08:44:16 -0400
Subject: [PATCH 10/15] Refactor media browser

---
 includes/media.admin.inc                     |    2 +
 includes/media.browser.inc                   |  171 +++++++++++++++++++++-----
 includes/media.pages.inc                     |    9 +--
 js/media.browser.js                          |   26 ++---
 js/media.dialog.js                           |  110 ++++++++++-------
 media.module                                 |   25 +---
 modules/media_internet/media_internet.module |    8 +-
 templates/media-dialog-page.tpl.php          |   65 ----------
 8 files changed, 222 insertions(+), 194 deletions(-)
 delete mode 100644 templates/media-dialog-page.tpl.php

diff --git a/includes/media.admin.inc b/includes/media.admin.inc
index 63877cc..109ab61 100644
--- a/includes/media.admin.inc
+++ b/includes/media.admin.inc
@@ -50,6 +50,7 @@ function media_admin($form, $form_state) {
     '#value' => t('Submit'),
     '#submit' => array('media_admin_submit'),
     '#validate' => array('media_admin_validate'),
+    '#attributes' => array('class' => array('use-ajax-submit')),
   );
   
   // Enable the add media button
@@ -61,6 +62,7 @@ function media_admin($form, $form_state) {
             'submit' => array(
               'disabledPlugins' => array('library'),
             ),
+            'url' => '/media/browser',
             'base' => 'media-admin-base',
           ),
         ),
diff --git a/includes/media.browser.inc b/includes/media.browser.inc
index 3a6295a..e79c578 100644
--- a/includes/media.browser.inc
+++ b/includes/media.browser.inc
@@ -4,22 +4,31 @@
  * @file
  * Media Browser page callback
  */
-function media_browser($selected = NULL) {
-  $output = array();
-  $output['#attached']['library'][] = array('media', 'media_browser_page');
+function media_browser($form, &$form_state) {
+
+//  if ($messages = theme('status_messages')) {
+//    $form['ajax']['messages'] = array(
+//      '#markup' => $messages,
+//      '#weight' => -1,
+//    );
+//  }
   
-  $params = array_merge(drupal_get_query_parameters(), drupal_get_query_parameters($_POST));
-  array_walk_recursive($params, '_media_recursive_check_plain');
-  media_set_browser_params($params);
-  
-  // How do we validate these?  I don't know.
-  // I think PDO should protect them, but I'm not 100% certain.
-  if (isset($params['fid'])) {
-    // A form has submitted, selected a piece (or pieces) of media and we refreshed.
+  $commands = array();
+
+  if (isset($form_state['dismiss'])) {
+    $command = 'mediaBrowserDismiss';
+    $data = '';
+  }
+  else if (form_get_errors()) {
+    $command = 'mediaBrowserRefresh';
+    $data = drupal_render($form);
+  }
+  else if (isset($form_state['values']['fid'])) {
+    // The form has submitted, selected a piece (or pieces) of media and we refreshed.
     // So we're just going to send the media entity out as a JS setting so the browser can close itself.
-    $selected = $params['fid'];
-    if (!is_array($params['fid'])) {
-      $selected = array($params['fid']);
+    $selected = $form_state['values']['fid'];
+    if (!is_array($form_state['values']['fid'])) {
+      $selected = array($form_state['values']['fid']);
     }
     if (!is_numeric($selected[0])) {
       throw new Exception('Error selecting media, fid param is not an fid or an array of fids');
@@ -29,9 +38,33 @@ function media_browser($selected = NULL) {
       media_browser_build_media_item($media);
     }
     $setting = array('media' => array('selectedMedia' => array_values($selectedMedia)));
-    drupal_add_js($setting, 'setting');
-    return $output;
+    #drupal_add_js($setting, 'setting');
+    
+    $command = 'mediaBrowserSelected';
+    $data = array_values($selectedMedia);
+  } 
+  else {
+    $command = 'mediaBrowserLaunch';
+    $data = drupal_render(media_browser_forms());
   }
+  
+  $commands[] = array(
+    'command' => $command,
+    'data' => $data,
+    'post' => $_POST,
+  );
+
+  return array('#type' => 'ajax', '#commands' => $commands);
+}  
+  
+function media_browser_forms() {
+  $build = array();
+  
+  $_POST['disabledPlugins'] = array('library');
+  
+  $params = array_merge(drupal_get_query_parameters(), drupal_get_query_parameters($_POST));
+  array_walk_recursive($params, '_media_recursive_check_plain');
+  media_set_browser_params($params);
 
   // Normal browser operation.
   foreach (module_implements('media_browser_plugin_info') as $module) {
@@ -62,13 +95,11 @@ function media_browser($selected = NULL) {
   drupal_alter('media_browser_plugins', $plugins);
   
   $tabs = array(); // List of tabs to render.
+  
+  $browser_settings = array();
 
-  $settings = array('media' => array('dialog' => array('open' => array('selector' => '#media-browser-tabset', 'callback' => 'console.log'))));
-  $browser_settings =& $settings['media']['dialog'];
-
-  //@todo: replace with Tabs module if it gets upgraded.
   foreach (element_children($plugins, TRUE) as $key) {
-    $plugin =& $plugins[$key];
+    $plugin = $plugins[$key];
 
     //Add any JS settings
     $browser_settings[$key] = isset($plugin['#settings']) ? $plugin['#settings'] : array();
@@ -85,21 +116,50 @@ EOS;
     </div>
     <!-- End #media-tab-$key -->
 EOS;
+    
+    $plugin['form']['actions'] = array(
+      'submit' => array(
+        '#type' => 'submit',
+        '#value' => t('Okay'),
+        '#attributes' => array('class' => array('use-ajax-submit')),
+      ),
+      'cancel' => array(
+        '#type' => 'submit',
+        '#value' => t('Cancel'),
+        '#name' => 'cancel',
+        '#attributes' => array('class' => array('use-ajax-submit')),
+      )
+    );
+    
+    $plugins[$key] = $plugin;
   }
   
-  drupal_add_js($settings, 'setting');
-
-  $output['tabset'] = array(
+  drupal_add_js(array('media' => array('dialog' => $browser_settings)), 'setting');
+  
+  $build['tabset'] = array(
     '#prefix' => '<div id="media-browser-tabset">',
     '#suffix' => '</div>',
+    '#weight' => 1,
   );
-  $output['tabset']['list'] = array(
+  
+  $build['tabset']['list'] = array(
     '#markup' => '<ul><li>' . implode('</li><li>', $tabs) . '</li></ul>'
-  );
+  );  
+  
+  $build['tabset']['plugins'] = $plugins;
 
-  $output['tabset']['plugins'] = $plugins;
+  return $build;
+}
 
-  return $output;
+function media_browser_form_validate($form, &$form_state) {
+  if (isset($form_state['clicked_button']) && $form_state['clicked_button']['#name'] == 'cancel') {
+    $form_state['dismiss'] = TRUE;
+  }
+  #module_load_include('inc', 'media', 'includes/media.pages');
+  $fs = form_state_defaults();
+  $fs['values'] = array(1,2);
+  drupal_form_submit('media_add_upload', $fs);
+  form_set_error('upload', 'This is a fake error');
 }
 
 function media_browser_build() {
@@ -130,14 +190,18 @@ function media_browser_get_display() {
     $display[$key] = $data;
   }
   $display['name'] = $type;
-  
+
   return $display;
 }
 
 function media_browser_set_display($type) {
   global $user;
-  $user->data['media_display_type'] = $type;
-  user_save($user);
+
+  if (in_array($type, array_keys(media_display_types()))) {
+    $user->data['media_display_type'] = $type;
+    user_save($user);
+  }
+
   drupal_goto(drupal_get_destination());
 }
 
@@ -400,10 +464,11 @@ function media_media_browser_plugin_view($plugin_name, $params) {
         $upload_form_id = 'media_add_upload';
       }
 
-      $upload_form = drupal_get_form($upload_form_id, $types);
+      $upload_form = drupal_get_form($upload_form_id);
+      
       return array(
         '#title' => t('Upload'),
-        'form' => array($upload_form),
+        'form' => $upload_form,
         '#attached' => $attached,
       );
       break;
@@ -427,7 +492,7 @@ function media_media_browser_plugin_view($plugin_name, $params) {
         // We should probably change this to load dynamically when requested
         // via the JS file.
         ),
-        'media' => media_browser_build(),
+        'form' => drupal_get_form('media_library'),
       );
     break;
   }
@@ -581,3 +646,41 @@ function media_browser_build_media_item(&$media) {
   $media->preview = drupal_render($preview);
   $media->url = file_create_url($media->uri);
 }
+
+/**
+ * Creates a Drupal AJAX 'mediaBrowserLaunch' command.
+ *
+ * @param $output
+ *   The form to display in the modal.
+ * @param $title
+ *   The title.
+ * @param $url
+ *   An optional URL.
+ *
+ * @return
+ *   An array suitable for use with the ajax_render() function.
+ */
+function media_browser_ajax_command_set_form($output, $title, $url = NULL) {
+  $command = array(
+    'command' => 'mediaBrowserLaunch',
+    'output' => $output,
+    'title' => $title,
+  );
+  if (isset($url)) {
+    $command['url'] = $url;
+  }
+  return $command;
+}
+
+/**
+ * Creates a Drupal AJAX 'mediaBrowserDismiss' command.
+ *
+ * @return
+ *   An array suitable for use with the ajax_render() function.
+ */
+function media_browser_ajax_command_dismiss_form() {
+  $command = array(
+    'command' => 'mediaBrowserDismiss',
+  );
+  return $command;
+}
diff --git a/includes/media.pages.inc b/includes/media.pages.inc
index c005a2e..5647680 100644
--- a/includes/media.pages.inc
+++ b/includes/media.pages.inc
@@ -176,7 +176,7 @@ function media_multiple_delete_confirm_submit($form, &$form_state) {
  * @todo: should use the AJAX uploader
  */
 function media_add_upload($form, &$form_state, $types = NULL) {
-
+  module_load_include('inc', 'media', '/includes/media.pages');
   $validators = array(
    'file_validate_extensions' => array(media_variable_get('file_extensions')),
    'file_validate_size' => array(parse_size(media_variable_get('max_filesize'))),
@@ -209,11 +209,6 @@ function media_add_upload($form, &$form_state, $types = NULL) {
     '#upload_validators' => $validators,
   );
 
-  $form['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Submit'),
-  );
-
   return $form;
 }
 
@@ -259,8 +254,6 @@ function media_add_upload_submit($form, &$form_state) {
     drupal_set_message(t('An error occurred and no file was uploaded.'), 'error');
     return;
   }
-
-  $form_state['redirect'] = array('media/browser', array('query' => array('render' => 'media-popup', 'fid' => $file->fid)));
 }
 
 function media_add_upload_multiple($form, &$form_state, $types) {
diff --git a/js/media.browser.js b/js/media.browser.js
index b9fc5fa..284d7e2 100644
--- a/js/media.browser.js
+++ b/js/media.browser.js
@@ -14,23 +14,22 @@ Drupal.media.browser.selectionFinalized = function (selectedMedia) {
 
 Drupal.behaviors.experimentalMediaBrowser = {
   attach: function (context) {
-    if (Drupal.settings.media.selectedMedia) {
-      Drupal.media.browser.selectMedia(Drupal.settings.media.selectedMedia);
-      // Fire a confirmation of some sort.
-      Drupal.media.browser.finalizeSelection();
-    }
+    var tab = $('.media-browser-active-tab', context).val();
     $('#media-browser-tabset').tabs({
-      show: Drupal.media.browser.resizeIframe
+      show: Drupal.media.browser.tabSwitch,
+      selected: tab
     });
-
-    //$('.media-browser-tab').each( Drupal.media.browser.validateButtons );
-
   }
-  // Wait for additional params to be passed in.
 };
 
-Drupal.media.browser.launch = function () {
+Drupal.media.browser.launch = function (event, ui) {
+  return ;
+};
 
+Drupal.media.browser.tabSwitch = function (event, ui) {
+  var value = $(this).tabs( "option", "selected" );
+  console.warn('Tab index: ' + value);
+  $('.media-browser-active-tab').val(value);
 };
 
 Drupal.media.browser.validateButtons = function() {
@@ -94,9 +93,4 @@ Drupal.media.browser.finalizeSelection = function () {
   }
 };
 
-Drupal.media.browser.resizeIframe = function (event) {
-  var h = $('body').height();
-  $(parent.window.document).find('#mediaBrowser').height(h);
-};
-
 }(jQuery));
diff --git a/js/media.dialog.js b/js/media.dialog.js
index 0dfcc52..c0779aa 100644
--- a/js/media.dialog.js
+++ b/js/media.dialog.js
@@ -4,72 +4,96 @@ Drupal.media = Drupal.media || {};
 Drupal.media.dialog = Drupal.media.dialog || {};
 
 Drupal.behaviors.dialog = {
-  attach: function (context) {
-    // If we've just received a dialog back, load the dialog
-    if (typeof Drupal.settings.media.dialog.open != 'undefined') {
-      var selector = Drupal.settings.media.dialog.open.selector;
-      var callback = Drupal.settings.media.dialog.open.callback;
-      $(selector).dialog(Drupal.media.dialog.defaults(callback));
-    }
-    
+  attach: function (context, settings) {
     // Enable any dialog launchers
-    for(var launcher in Drupal.settings.media.dialog.launchers) {
-      var element = $(launcher).not('.media-ajax');
-      if (element.length) {
-        element.addClass('media-ajax');
-        var options = Drupal.settings.media.dialog.launchers[launcher];
-        var base = element.attr('id') ? element.attr('id') : options.base;
-        Drupal.media.dialog.launcher(element, base, options);
-      }
+    for(var launcher in settings.media.dialog.launchers) {
+      $(launcher, context).once('media-launcher', function() {
+        var $this = $(this);
+        var element_settings = $.extend(Drupal.media.dialog.ajaxDefaults(), settings.media.dialog.launchers[launcher]);
+        var id = $this.attr('id');
+        if (!id) {
+          id = element_settings.base;
+          $this.attr('id', element_settings.base);
+        }
+        Drupal.ajax[id] = new Drupal.ajax(id, this, element_settings);
+      });
     }
   }
 };
 
-Drupal.media.dialog.defaults = function (callback) {
+Drupal.media.dialog.ajaxDefaults = function () {
+  var element_settings = {};
+  element_settings.progress = {'type': 'throbber'};
+  element_settings.wrapper = 'page';
+  element_settings.method = 'append';
+  element_settings.url = Drupal.settings.media.browserUrl;
+  element_settings.event = 'click';
+  element_settings.submit = {
+    limit: 15
+  };
+  return element_settings;
+};
+
+Drupal.media.dialog.defaults = function () {
   return {
     modal: true,
     width: '80%',
     maxHeight: '80%',
     resizable: false,
     draggable: false,
-    autoOpen: true,
-    buttons: {
-      'ok': Drupal.media.dialog.confirm,
-      cancel: this.close
-    },
-    callback: callback,
+    autoOpen: false,
     close: Drupal.media.dialog.close
   };
 };
 
 Drupal.media.dialog.close = function () {
-  Drupal.detachBehaviors(this, Drupal.settings);
+  Drupal.detachBehaviors(this);
   $(this).remove();
 };
 
-Drupal.media.dialog.confirm = function () {
-  $(this).data().dialog.options.callback();
-  $(this).dialog('destory');
+Drupal.media.dialog.tabs = function (wrapper) {
+  var tab = $('.media-browser-active-tab', wrapper).val();
+  $('#media-browser-tabset', wrapper).tabs({
+    show: Drupal.media.dialog.tabSwitch,
+    selected: tab
+  });
+};
+
+Drupal.media.dialog.tabSwitch = function (event, ui) {
+  var value = $(this).tabs( "option", "selected" );
+  $('.media-browser-active-tab').val(value);
 };
 
-Drupal.media.dialog.launcher = function (element, base, options) {
-  var element_settings = $.extend(Drupal.media.dialog.ajaxDefaults(), options);
+Drupal.ajax.prototype.commands.mediaBrowserLaunch = function (ajax, response, status) {
+  // Create the dialog
+  var wrapper = $('<div id="media-browser-wrapper"></div>');
+  wrapper.dialog(Drupal.media.dialog.defaults());
+  wrapper.html(response.data);
+  
+  // Add the tabs to the dialog if multiple plugins are enabled
+  Drupal.media.dialog.tabs(wrapper);
   
-  Drupal.ajax[element_settings.base] = new Drupal.ajax(element_settings.base, element, element_settings);
+  // Attach behaviors
+  Drupal.attachBehaviors(wrapper, ajax.settings);
+  
+  // Open the dialog
+  wrapper.dialog('open');
 };
 
-Drupal.media.dialog.ajaxDefaults = function () {
-  var element_settings = {};
-  element_settings.progress = { 'type': 'throbber' };
-  element_settings.wrapper = 'page';
-  element_settings.method = 'append';
-  element_settings.url = Drupal.settings.media.browserUrl;
-  element_settings.event = 'click';
-  element_settings.submit = {
-    js: true,
-    limit: 15
-  };
-  return element_settings;
-}
+Drupal.ajax.prototype.commands.mediaBrowserRefresh = function (ajax, response, status) {
+  var wrapper = $('#media-browser-wrapper');
+  $('#media-browser-ajax-wrapper', wrapper).replaceWith(response.data);
+  Drupal.media.dialog.tabs($('#media-browser-wrapper'));
+  Drupal.attachBehaviors($('.media-browser-tabset', wrapper), ajax.settings);
+};
+
+Drupal.ajax.prototype.commands.mediaBrowserSelected = function (ajax, response, status) {
+  console.log(response);
+  //$('#media-browser-wrapper').dialog('close');
+};
+
+Drupal.ajax.prototype.commands.mediaBrowserDismiss = function (ajax, response, status) {
+  $('#media-browser-wrapper').dialog('close');
+};
 
 })(jQuery);
\ No newline at end of file
diff --git a/media.module b/media.module
index 637c9b2..aa0d854 100644
--- a/media.module
+++ b/media.module
@@ -129,7 +129,7 @@ function media_menu() {
     'description' => 'Import files into your media library.',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('media_add_upload'),
-    'file' => 'includes/media.pages.inc',
+    'file' => 'includes/media.browser.inc',
     'access arguments' => array('import media'),
     'type' => MENU_LOCAL_ACTION,
     'options' => array(
@@ -267,7 +267,7 @@ function media_menu() {
     'type' => MENU_CALLBACK,
     'file' => 'includes/media.pages.inc',
   );
-
+  
   return $items;
 }
 
@@ -764,26 +764,9 @@ function media_library() {
       array('system', 'ui.resizable'),
       array('system', 'ui.draggable'),
       array('system', 'ui.dialog'),
-      array('system', 'drupal.ajax'),
-    ),
-  );
-
-  /**
-   * Resources needed in the media browser itself.
-   */
-  $libraries['media_browser_page'] = array(
-    'title' => 'Media browser',
-    'js' => array(
-      $path . '/js/media.browser.js'  => array('group' => JS_DEFAULT),
-    ),
-    'css' => array(
-      $path . '/css/media.browser.css' => array('group' => CSS_DEFAULT),
-    ),
-    'dependencies' => array(
-      array('media', 'media_base'),
       array('system', 'ui.tabs'),
-      array('system', 'ui.draggable'),
-      array('system', 'ui.dialog'),
+      array('system', 'drupal.ajax'),
+      array('system', 'jquery.form'),
     ),
   );
 
diff --git a/modules/media_internet/media_internet.module b/modules/media_internet/media_internet.module
index 7374d98..a260a9d 100644
--- a/modules/media_internet/media_internet.module
+++ b/modules/media_internet/media_internet.module
@@ -42,13 +42,9 @@ function media_internet_media_browser_plugin_view($plugin_name, $params) {
   switch ($plugin_name) {
     case 'media_internet':
       // @todo: implement the multiselect argument here.
-      $from_web_form = drupal_get_form('media_internet_add',  $types, $multiselect);
       return array(
         '#title' => t('Web'),
-        'form' => array($from_web_form),
-        '#attached' => array(
-          //'js' => array($path . '/js/plugins/media.fromurl.js'),
-        ),
+        'form' => drupal_get_form('media_internet_add'),
       );
       break;
   }
@@ -105,8 +101,6 @@ function media_internet_add($form, &$form_state = array(), $types = NULL) {
     unset($form['providers']['header']);
   }
 
-  $form['actions'] = array('#type' => 'actions');
-  $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Submit'));
   return $form;
 }
 
diff --git a/templates/media-dialog-page.tpl.php b/templates/media-dialog-page.tpl.php
deleted file mode 100644
index 54f5a2d..0000000
--- a/templates/media-dialog-page.tpl.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-
-/**
- * @file
- * Default theme implementation to display the media browser.
- *
- * Available variables:
- *
- * General utility variables:
- * - $base_path: The base URL path of the Drupal installation. At the very
- *   least, this will always default to /.
- * - $directory: The directory the template is located in, e.g. modules/system
- *   or themes/garland.
- * - $is_front: TRUE if the current page is the front page.
- * - $logged_in: TRUE if the user is registered and signed in.
- * - $is_admin: TRUE if the user has permission to access administration pages.
- *
- * Site identity:
- * - $front_page: The URL of the front page. Use this instead of $base_path,
- *   when linking to the front page. This includes the language domain or
- *   prefix.
- * - $logo: The path to the logo image, as defined in theme configuration.
- * - $site_name: The name of the site, empty when display has been disabled
- *   in theme settings.
- * - $site_slogan: The slogan of the site, empty when display has been disabled
- *   in theme settings.
- *
- * Navigation:
- * - $main_menu (array): An array containing the Main menu links for the
- *   site, if they have been configured.
- * - $secondary_menu (array): An array containing the Secondary menu links for
- *   the site, if they have been configured.
- * - $breadcrumb: The breadcrumb trail for the current page.
- *
- * Page content (in order of occurrence in the default page.tpl.php):
- * - $title_prefix (array): An array containing additional output populated by
- *   modules, intended to be displayed in front of the main title tag that
- *   appears in the template.
- * - $title: The page title, for use in the actual HTML content.
- * - $title_suffix (array): An array containing additional output populated by
- *   modules, intended to be displayed after the main title tag that appears in
- *   the template.
- * - $messages: HTML for status and error messages. Should be displayed
- *   prominently.
- * - $tabs (array): Tabs linking to any sub-pages beneath the current page
- *   (e.g., the view and edit tabs when displaying a node).
- * - $action_links (array): Actions local to the page, such as 'Add menu' on the
- *   menu administration interface.
- * - $feed_icons: A string of all feed icons for the current page.
- * - $node: The node object, if there is an automatically-loaded node
- *   associated with the page, and the node ID is the second argument
- *   in the page's path (e.g. node/12345 and node/12345/revisions, but not
- *   comment/reply/12345).
- *
- * @see template_preprocess()
- * @see template_preprocess_page()
- * @see template_preprocess_media_dialog_page()
- * @see template_process()
- */
-?>
-
-<div id="media-browser-page-wrapper"><div id="media-browser-page">
-  <?php if (isset($messages)) { print $messages; } ?>
-  <?php print render($page['content']); ?>
-</div></div> <!-- /#page, /#page-wrapper -->
-- 
1.7.4.msysgit.0

