summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2005-08-31 18:37:30 +0000
committerDries Buytaert <dries@buytaert.net>2005-08-31 18:37:30 +0000
commite03ce2f99670b75a7f3e0709dd8705a2a3f4625e (patch)
treea7678fa8a55ccd2927cbbc8d0e30bbacf630ad3d /modules
parent3029da00d62c20a4d97d668931bf9f0c918d1b09 (diff)
downloadbrdo-e03ce2f99670b75a7f3e0709dd8705a2a3f4625e.tar.gz
brdo-e03ce2f99670b75a7f3e0709dd8705a2a3f4625e.tar.bz2
- Patch #28483 by Steven: JavaScript enabled uploading.
Comment from Steven: It does this by redirecting the submission of the form to a hidden <iframe> when you click "Attach" (we cannot submit data through Ajax directly because you cannot read file contents from JS for security reasons). Once the file is submitted, the upload-section of the form is updated. Things to note: * The feature degrades back to the current behaviour without JS. * If there are errors with the uploaded file (disallowed type, too big, ...), they are displayed at the top of the file attachments fieldset. * Though the hidden-iframe method sounds dirty, it's quite compact and is 100% implemented in .js files. The drupal.js api makes it a snap to use. * I included some minor improvements to the Drupal JS API and code. * I added an API drupal_call_js() to bridge the PHP/JS gap: it takes a function name and arguments, and outputs a <script> tag. The kicker is that it preserves the structure and type of arguments, so e.g. PHP associative arrays end up as objects in JS. * I also included a progressbar widget that I wrote for drumm's ongoing update.php work. It includes Ajax status updating/monitoring, but it is only used as a pure throbber in this patch. But as the code was already written and is going to be used in the near future, I left that part in. It's pretty small ;). If PHP supports ad-hoc upload info in the future like Ruby on Rails, we can implement that in 5 minutes.
Diffstat (limited to 'modules')
-rw-r--r--modules/upload.module38
-rw-r--r--modules/upload/upload.module38
2 files changed, 70 insertions, 6 deletions
diff --git a/modules/upload.module b/modules/upload.module
index 3cf56d16c..335fd8dfc 100644
--- a/modules/upload.module
+++ b/modules/upload.module
@@ -60,6 +60,12 @@ function upload_menu($may_cache) {
'access' => user_access('administer site configuration'),
'type' => MENU_NORMAL_ITEM
);
+ $items[] = array(
+ 'path' => 'upload/js',
+ 'callback' => 'upload_js',
+ 'access' => user_access('upload files'),
+ 'type' => MENU_CALLBACK
+ );
}
else {
// Add handlers for previewing new uploads.
@@ -378,8 +384,18 @@ function upload_delete($node) {
}
function upload_form($node) {
+ drupal_add_js('misc/progress.js');
+ drupal_add_js('misc/upload.js');
+
+ $output = '<div id="fileop-wrapper">'. _upload_form($node) .'</div>';
+
+ return '<div class="attachments">'. form_group_collapsible(t('File attachments'), $output, empty($node->files), t('Changes made to the attachments are not permanent until you save this post. The first "listed" file will be included in RSS feeds.')) .'</div>';
+}
+
+function _upload_form($node) {
$header = array(t('Delete'), t('List'), t('Url'), t('Size'));
$rows = array();
+ $output = '';
if (is_array($node->files)) {
foreach ($node->files as $key => $file) {
@@ -393,15 +409,19 @@ function upload_form($node) {
}
if (count($node->files)) {
- $output = theme('table', $header, $rows);
+ $output .= theme('table', $header, $rows);
}
if (user_access('upload files')) {
+ $output .= '<div id="fileop-hide">';
$output .= form_file(t('Attach new file'), "upload", 40);
$output .= form_button(t('Attach'), 'fileop');
+ // The class triggers the js upload behaviour.
+ $output .= form_hidden('fileop', url('upload/js', NULL, NULL, TRUE), 'edit', array('class' => 'upload'));
+ $output .= '</div>';
}
- return '<div class="attachments">'. form_group_collapsible(t('File attachments'), $output, empty($node->files), t('Changes made to the attachments are not permanent until you save this post. The first "listed" file will be included in RSS feeds.')) .'</div>';
+ return $output;
}
function upload_load($node) {
@@ -438,4 +458,16 @@ function _upload_image($file) {
return $file;
}
-
+/**
+ * Menu-callback for JavaScript-based uploads.
+ */
+function upload_js() {
+ // We only do the upload.module part of the node validation process.
+ $node = array2object($_POST['edit']);
+ upload_nodeapi(&$node, 'validate', NULL);
+ $output = theme('status_messages') . _upload_form($node);
+
+ // We send the updated file attachments form.
+ print drupal_call_js('window.parent.iframeHandler', $output);
+ exit;
+}
diff --git a/modules/upload/upload.module b/modules/upload/upload.module
index 3cf56d16c..335fd8dfc 100644
--- a/modules/upload/upload.module
+++ b/modules/upload/upload.module
@@ -60,6 +60,12 @@ function upload_menu($may_cache) {
'access' => user_access('administer site configuration'),
'type' => MENU_NORMAL_ITEM
);
+ $items[] = array(
+ 'path' => 'upload/js',
+ 'callback' => 'upload_js',
+ 'access' => user_access('upload files'),
+ 'type' => MENU_CALLBACK
+ );
}
else {
// Add handlers for previewing new uploads.
@@ -378,8 +384,18 @@ function upload_delete($node) {
}
function upload_form($node) {
+ drupal_add_js('misc/progress.js');
+ drupal_add_js('misc/upload.js');
+
+ $output = '<div id="fileop-wrapper">'. _upload_form($node) .'</div>';
+
+ return '<div class="attachments">'. form_group_collapsible(t('File attachments'), $output, empty($node->files), t('Changes made to the attachments are not permanent until you save this post. The first "listed" file will be included in RSS feeds.')) .'</div>';
+}
+
+function _upload_form($node) {
$header = array(t('Delete'), t('List'), t('Url'), t('Size'));
$rows = array();
+ $output = '';
if (is_array($node->files)) {
foreach ($node->files as $key => $file) {
@@ -393,15 +409,19 @@ function upload_form($node) {
}
if (count($node->files)) {
- $output = theme('table', $header, $rows);
+ $output .= theme('table', $header, $rows);
}
if (user_access('upload files')) {
+ $output .= '<div id="fileop-hide">';
$output .= form_file(t('Attach new file'), "upload", 40);
$output .= form_button(t('Attach'), 'fileop');
+ // The class triggers the js upload behaviour.
+ $output .= form_hidden('fileop', url('upload/js', NULL, NULL, TRUE), 'edit', array('class' => 'upload'));
+ $output .= '</div>';
}
- return '<div class="attachments">'. form_group_collapsible(t('File attachments'), $output, empty($node->files), t('Changes made to the attachments are not permanent until you save this post. The first "listed" file will be included in RSS feeds.')) .'</div>';
+ return $output;
}
function upload_load($node) {
@@ -438,4 +458,16 @@ function _upload_image($file) {
return $file;
}
-
+/**
+ * Menu-callback for JavaScript-based uploads.
+ */
+function upload_js() {
+ // We only do the upload.module part of the node validation process.
+ $node = array2object($_POST['edit']);
+ upload_nodeapi(&$node, 'validate', NULL);
+ $output = theme('status_messages') . _upload_form($node);
+
+ // We send the updated file attachments form.
+ print drupal_call_js('window.parent.iframeHandler', $output);
+ exit;
+}