From c6447e2ce289188493590ec0d5449fa3692eed08 Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Wed, 02 Jul 2014 07:03:22 -0400
Subject: [PATCH] Use treelist widget for folders list in Settings/Folders (#1489648)

---
 program/js/app.js |  320 +++++++++++++++++++++++++++--------------------------
 1 files changed, 164 insertions(+), 156 deletions(-)

diff --git a/program/js/app.js b/program/js/app.js
index 9c2acfc..2b9c3f0 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -46,12 +46,12 @@
   this.messages = {};
   this.group2expand = {};
   this.http_request_jobs = {};
-  this.menu_stack = new Array();
+  this.menu_stack = [];
 
   // webmail client settings
   this.dblclick_time = 500;
   this.message_time = 5000;
-  this.identifier_expr = new RegExp('[^0-9a-z\-_]', 'gi');
+  this.identifier_expr = /[^0-9a-z_-]/gi;
 
   // environment defaults
   this.env = {
@@ -314,9 +314,9 @@
               });
 
             // avoid textarea loosing focus when hitting the save-response button/link
-            for (var i=0; this.buttons['save-response'] && i < this.buttons['save-response'].length; i++) {
-              $('#'+this.buttons['save-response'][i].id).mousedown(function(e){ return rcube_event.cancel(e); })
-            }
+            $.each(this.buttons['save-response'] || [], function (i, v) {
+              $('#' + v.id).mousedown(function(e){ return rcube_event.cancel(e); })
+            });
           }
 
           // init message compose form
@@ -346,10 +346,10 @@
           this.contact_list
             .addEventListener('initrow', function(o) { ref.triggerEvent('insertrow', { cid:o.uid, row:o }); })
             .addEventListener('select', function(o) { ref.compose_recipient_select(o); })
-            .addEventListener('dblclick', function(o) { ref.compose_add_recipient('to'); })
+            .addEventListener('dblclick', function(o) { ref.compose_add_recipient(); })
             .addEventListener('keypress', function(o) {
               if (o.key_pressed == o.ENTER_KEY) {
-                if (!ref.compose_add_recipient('to')) {
+                if (!ref.compose_add_recipient()) {
                   // execute link action on <enter> if not a recipient entry
                   if (o.last_selected && String(o.last_selected).charAt(0) == 'G') {
                     $(o.rows[o.last_selected].obj).find('a').first().click();
@@ -358,6 +358,9 @@
               }
             })
             .init();
+
+          // remember last focused address field
+          $('#_to,#_cc,#_bcc').focus(function() { ref.env.focused_field = this; });
         }
 
         if (this.gui_objects.addressbookslist) {
@@ -403,15 +406,23 @@
             .addEventListener('dragend', function(e) { ref.drag_end(e); })
             .init();
 
-          if (this.env.cid)
-            this.contact_list.highlight_row(this.env.cid);
-
           this.gui_objects.contactslist.parentNode.onmousedown = function(e){ return ref.click_on_list(e); };
 
           $(this.gui_objects.qsearchbox).focusin(function() { ref.contact_list.blur(); });
 
           this.update_group_commands();
           this.command('list');
+        }
+
+        if (this.gui_objects.savedsearchlist) {
+          this.savedsearchlist = new rcube_treelist_widget(this.gui_objects.savedsearchlist, {
+            id_prefix: 'rcmli',
+            id_encode: this.html_identifier_encode,
+            id_decode: this.html_identifier_decode
+          });
+
+          this.savedsearchlist.addEventListener('select', function(node) {
+            ref.triggerEvent('selectfolder', { folder:node.id, prefix:'rcmli' }); });
         }
 
         this.set_page_buttons();
@@ -471,9 +482,6 @@
             })
             .init()
             .focus();
-
-          if (this.env.iid)
-            this.identity_list.highlight_row(this.env.iid);
         }
         else if (this.gui_objects.sectionslist) {
           this.sections_list = new rcube_list_widget(this.gui_objects.sectionslist, {multiselect:false, draggable:false, keyboard:true});
@@ -557,6 +565,7 @@
     // init treelist widget
     if (this.gui_objects.folderlist && window.rcube_treelist_widget) {
       this.treelist = new rcube_treelist_widget(this.gui_objects.folderlist, {
+          selectable: true,
           id_prefix: 'rcmli',
           id_encode: this.html_identifier_encode,
           id_decode: this.html_identifier_decode,
@@ -621,7 +630,7 @@
   {
     var ret, uid, cid, url, flag, aborted = false;
 
-    if (obj && obj.blur && !(event || rcube_event.is_keyboard(event)))
+    if (obj && obj.blur && !(event && rcube_event.is_keyboard(event)))
       obj.blur();
 
     // do nothing if interface is locked by other command (with exception for searching reset)
@@ -1344,7 +1353,7 @@
   this.command_enabled = function(cmd)
   {
     return this.commands[cmd];
-  }
+  };
 
   // lock/unlock interface
   this.set_busy = function(a, message, id)
@@ -1386,10 +1395,11 @@
   // switch to another application task
   this.switch_task = function(task)
   {
-    if (this.task===task && task!='mail')
+    if (this.task === task && task != 'mail')
       return;
 
     var url = this.get_task_url(task);
+
     if (task == 'mail')
       url += '&_mbox=INBOX';
     else if (task == 'logout')
@@ -1444,10 +1454,10 @@
 
   this.save_pref = function(prop)
   {
-    var request = {'_name': prop.name, '_value': prop.value};
+    var request = {_name: prop.name, _value: prop.value};
 
     if (prop.session)
-      request['_session'] = prop.session;
+      request._session = prop.session;
     if (prop.env)
       this.env[prop.env] = prop.value;
 
@@ -1587,7 +1597,7 @@
 
       // select the folder if one of its childs is currently selected
       // don't select if it's virtual (#1488346)
-      if (this.env.mailbox && this.env.mailbox.startsWith(name + this.env.delimiter) && !node.virtual)
+      if (!node.virtual && this.env.mailbox && this.env.mailbox.startsWith(name + this.env.delimiter))
         this.command('list', name);
     }
     else {
@@ -1629,7 +1639,7 @@
     }
 
     // reset popup menus; delayed to have updated menu_stack data
-    window.setTimeout(function(e){
+    setTimeout(function(e){
       var obj, skip, config, id, i, parents = $(target).parents();
       for (i = ref.menu_stack.length - 1; i >= 0; i--) {
         id = ref.menu_stack[i];
@@ -1681,8 +1691,8 @@
       case 40:
       case 63232: // "up", in safari keypress
       case 63233: // "down", in safari keypress
-        focus_menu_item(mod = keyCode == 38 || keyCode == 63232 ? -1 : 1);
-        break;
+        focus_menu_item(keyCode == 38 || keyCode == 63232 ? -1 : 1);
+        return rcube_event.cancel(e);
 
       case 9:   // tab
         if (this.focused_menu) {
@@ -1845,9 +1855,6 @@
         return (this.env.mailboxes[id]
             && !this.env.mailboxes[id].virtual
             && (this.env.mailboxes[id].id != this.env.mailbox || this.is_multifolder_listing())) ? 1 : 0;
-
-      case 'settings':
-        return id != this.env.mailbox ? 1 : 0;
 
       case 'addressbook':
         var target;
@@ -2480,7 +2487,7 @@
         selection.push(selected[i]);
 
     this.message_list.selection = selection;
-  }
+  };
 
   // expand all threads with unread children
   this.expand_unread = function()
@@ -2493,8 +2500,10 @@
         this.message_list.expand_all(r);
         this.set_unread_children(r.uid);
       }
+
       new_row = new_row.nextSibling;
     }
+
     return false;
   };
 
@@ -2711,8 +2720,8 @@
     }
 
     // update unread_children for roots
-    for (var i=0; i<roots.length; i++)
-      this.set_unread_children(roots[i].uid);
+    for (r=0; r<roots.length; r++)
+      this.set_unread_children(roots[r].uid);
 
     return count;
   };
@@ -3488,6 +3497,12 @@
 
   this.compose_add_recipient = function(field)
   {
+    // find last focused field name
+    if (!field) {
+      field = $(this.env.focused_field).filter(':visible');
+      field = field.length ? field.attr('id').replace('_', '') : 'to';
+    }
+
     var recipients = [], input = $('#_'+field), delim = this.env.recipients_delimiter;
 
     if (this.contact_list && this.contact_list.selection.length) {
@@ -3556,26 +3571,32 @@
         myprompt = $('<div class="prompt">').html('<div class="message">' + this.get_label('nosubjectwarning') + '</div>')
           .appendTo(document.body),
         prompt_value = $('<input>').attr({type: 'text', size: 30}).val(this.get_label('nosubject'))
-          .appendTo(myprompt);
+          .appendTo(myprompt),
+        save_func = function() {
+          input_subject.val(prompt_value.val());
+          myprompt.dialog('close');
+          ref.command(cmd, { nocheck:true });  // repeat command which triggered this
+        };
 
-      buttons[this.get_label('cancel')] = function(){
+      buttons[this.get_label('sendmessage')] = function() {
+        save_func($(this));
+      };
+      buttons[this.get_label('cancel')] = function() {
         input_subject.focus();
         $(this).dialog('close');
-      };
-      buttons[this.get_label('sendmessage')] = function(){
-        input_subject.val(prompt_value.val());
-        $(this).dialog('close');
-        ref.command(cmd, { nocheck:true });  // repeat command which triggered this
       };
 
       myprompt.dialog({
         modal: true,
         resizable: false,
         buttons: buttons,
-        close: function(event, ui) { $(this).remove() }
+        close: function(event, ui) { $(this).remove(); }
       });
 
-      prompt_value.select();
+      prompt_value.select().keydown(function(e) {
+        if (e.which == 13) save_func();
+      });
+
       return false;
     }
 
@@ -3653,7 +3674,7 @@
       $(this).dialog('close');
     };
 
-    this.show_popup_dialog(html, this.gettext('savenewresponse'), buttons);
+    this.show_popup_dialog(html, this.gettext('newresponse'), buttons);
 
     $('#ffresponsetext').val(text);
     $('#ffresponsename').select();
@@ -3712,8 +3733,9 @@
   {
     var active = this.editor.spellcheck_state();
 
-    if (this.buttons.spellcheck)
-      $('#'+this.buttons.spellcheck[0].id)[active ? 'addClass' : 'removeClass']('selected');
+    $.each(this.buttons.spellcheck || [], function(i, v) {
+      $('#' + v.id)[active ? 'addClass' : 'removeClass']('selected');
+    });
 
     return active;
   };
@@ -3911,7 +3933,7 @@
       }
       this.local_storage_remove_item('compose.index');
     }
-  }
+  };
 
 
   this.change_identity = function(obj, show_sig)
@@ -4058,6 +4080,14 @@
     if (upload_id)
       this.triggerEvent('fileuploaded', {name: name, attachment: att, id: upload_id});
 
+    if (!this.env.attachments)
+      this.env.attachments = {};
+
+    if (upload_id && this.env.attachments[upload_id])
+      delete this.env.attachments[upload_id];
+
+    this.env.attachments[name] = att;
+
     if (!this.gui_objects.attachmentlist)
       return false;
 
@@ -4066,7 +4096,7 @@
 
     if (!att.complete && att.frame)
       att.html = '<a title="'+this.get_label('cancel')+'" onclick="return rcmail.cancel_attachment_upload(\''+name+'\', \''+att.frame+'\');" href="#cancelupload" class="cancelupload">'
-        + (this.env.cancelicon ? '<img src="'+this.env.cancelicon+'" alt="" />' : this.get_label('cancel')) + '</a>' + att.html;
+        + (this.env.cancelicon ? '<img src="'+this.env.cancelicon+'" alt="'+this.get_label('cancel')+'" />' : this.get_label('cancel')) + '</a>' + att.html;
 
     var indicator, li = $('<li>');
 
@@ -4083,10 +4113,9 @@
       li.appendTo(this.gui_objects.attachmentlist);
     }
 
-    if (upload_id && this.env.attachments[upload_id])
-      delete this.env.attachments[upload_id];
-
-    this.env.attachments[name] = att;
+    // set tabindex attribute
+    var tabindex = $(this.gui_objects.attachmentlist).attr('data-tabindex') || '0';
+    li.find('a').attr('tabindex', tabindex);
 
     return true;
   };
@@ -4125,7 +4154,7 @@
 
   this.upload_progress_update = function(param)
   {
-    var elem = $('#'+param.name + '> span');
+    var elem = $('#'+param.name + ' > span');
 
     if (!elem.length || !param.text)
       return;
@@ -4282,21 +4311,22 @@
     this.display_message(msg, type);
 
     if (this.env.extwin) {
-      var rc = this.opener();
       this.lock_form(this.gui_objects.messageform);
+
+      var rc = this.opener();
       if (rc) {
         rc.display_message(msg, type);
         // refresh the folder where sent message was saved or replied message comes from
         if (folders && rc.env.task == 'mail' && rc.env.action == '' && $.inArray(rc.env.mailbox, folders) >= 0) {
-          // @TODO: try with 'checkmail' here when #1485186 is fixed. See also #1489249.
-          rc.command('list');
+          rc.command('checkmail');
         }
       }
-      setTimeout(function(){ window.close() }, 1000);
+
+      setTimeout(function() { window.close(); }, 1000);
     }
     else {
       // before redirect we need to wait some time for Chrome (#1486177)
-      setTimeout(function(){ ref.list_mailbox(); }, 500);
+      setTimeout(function() { ref.list_mailbox(); }, 500);
     }
   };
 
@@ -4519,7 +4549,7 @@
 
       // register (delegate) event handlers
       ul.on('mouseover', 'li', function(e){ ref.ksearch_select(e.target); })
-        .on('onmouseup', 'li', function(e){ ref.ksearch_click(e.target); })
+        .on('mouseup', 'li', function(e){ ref.ksearch_click(e.target); })
     }
 
     ul = this.ksearch_pane.__ul;
@@ -4742,7 +4772,8 @@
         $(this.gui_objects.addresslist_title).html(this.get_label('contacts'));
     }
 
-    this.select_folder(folder, '', true);
+    if (!this.env.search_id)
+      this.select_folder(folder, '', true);
 
     // load contacts remotely
     if (this.gui_objects.contactslist) {
@@ -4974,7 +5005,7 @@
   {
     var selection = this.contact_list ? this.contact_list.get_selection() : [];
 
-    // exit if no mailbox specified or if selection is empty
+    // exit if no contact specified or if selection is empty
     if (!selection.length && !this.env.cid)
       return;
 
@@ -5166,7 +5197,7 @@
 
       // find list (UL) element
       if (type == 'contactsearch')
-        ul = this.gui_objects.folderlist;
+        ul = this.gui_objects.savedsearchlist;
       else
         ul = $('ul.groups', this.get_folder_li(this.env.source,'',true));
 
@@ -5267,7 +5298,7 @@
         .html(prop.name);
 
     this.env.contactfolders[key] = this.env.contactgroups[key] = prop;
-    this.treelist.insert({ id:key, html:link, classes:['contactgroup'] }, prop.source, true);
+    this.treelist.insert({ id:key, html:link, classes:['contactgroup'] }, prop.source, 'contactgroup');
 
     this.triggerEvent('group_insert', { id:prop.id, source:prop.source, name:prop.name, li:this.treelist.get_item(key) });
   };
@@ -5549,7 +5580,7 @@
         .html(name),
       prop = { name:name, id:id };
 
-    this.treelist.insert({ id:key, html:link, classes:['contactsearch'] }, null, 'contactsearch');
+    this.savedsearchlist.insert({ id:key, html:link, classes:['contactsearch'] }, null, 'contactsearch');
     this.select_folder(key,'',true);
     this.enable_command('search-delete', true);
     this.env.search_id = id;
@@ -5575,7 +5606,7 @@
   this.remove_search_item = function(id)
   {
     var li, key = 'S'+id;
-    if (this.treelist.remove(key)) {
+    if (this.savedsearchlist.remove(key)) {
       this.triggerEvent('search_delete', { id:id, li:li });
     }
 
@@ -5595,7 +5626,13 @@
     }
 
     this.reset_qsearch();
-    this.select_folder('S'+id, '', true);
+
+    if (this.savedsearchlist) {
+      this.treelist.select('');
+      this.savedsearchlist.select('S'+id);
+    }
+    else
+      this.select_folder('S'+id, '', true);
 
     // reset vars
     this.env.current_page = 1;
@@ -5725,62 +5762,38 @@
 
     this.last_sub_rx = RegExp('['+delim+']?[^'+delim+']+$');
 
-    this.subscription_list = new rcube_list_widget(this.gui_objects.subscriptionlist,
-      {multiselect:false, draggable:true, keyboard:true, toggleselect:true});
+    this.subscription_list = new rcube_treelist_widget(this.gui_objects.subscriptionlist, {
+        selectable: true
+    });
+
     this.subscription_list
-      .addEventListener('select', function(o){ ref.subscription_select(o); })
-      .addEventListener('dragstart', function(o){ ref.drag_active = true; })
-      .addEventListener('dragend', function(o){ ref.subscription_move_folder(o); })
-      .addEventListener('initrow', function (row) {
-        row.obj.onmouseover = function() { ref.focus_subscription(row.id); };
-        row.obj.onmouseout = function() { ref.unfocus_subscription(row.id); };
-      })
-      .init()
-      .focus();
+      .addEventListener('select', function(node) { ref.subscription_select(node.id); })
+      .draggable({cancel: '#mailboxroot'})
+      .droppable({
+        // @todo: find better way, accept callback is executed for every folder
+        // on the list when dragging starts (and stops), this is slow, but
+        // I didn't find a method to check droptarget on over event
+        accept: function(node) {
+          var source = ref.env.subscriptionrows[$(node).attr('id')],
+            dest = ref.env.subscriptionrows[this.id],
+            source_name = source[0],
+            dest_name = dest[0];
 
-    $('#mailboxroot')
-      .mouseover(function(){ ref.focus_subscription(this.id); })
-      .mouseout(function(){ ref.unfocus_subscription(this.id); })
-  };
-
-  this.focus_subscription = function(id)
-  {
-    var row, folder;
-
-    if (this.drag_active && this.env.mailbox && (row = document.getElementById(id)))
-      if (this.env.subscriptionrows[id] &&
-          (folder = this.env.subscriptionrows[id][0]) !== null
-      ) {
-        if (this.check_droptarget(folder) &&
-            !this.env.subscriptionrows[this.get_folder_row_id(this.env.mailbox)][2] &&
-            folder != this.env.mailbox.replace(this.last_sub_rx, '') &&
-            !folder.startsWith(this.env.mailbox + this.env.delimiter)
-        ) {
-          this.env.dstfolder = folder;
-          $(row).addClass('droptarget');
+          return !source[2]
+            && dest_name != source_name.replace(ref.last_sub_rx, '')
+            && !dest_name.startsWith(source_name + ref.env.delimiter);
+        },
+        drop: function(e, ui) {
+          ref.subscription_move_folder(ui.draggable.attr('id'), this.id);
         }
-      }
+      });
   };
 
-  this.unfocus_subscription = function(id)
+  this.subscription_select = function(id)
   {
-    var row = $('#'+id);
+    var folder;
 
-    this.env.dstfolder = null;
-
-    if (row.length && this.env.subscriptionrows[id])
-      row.removeClass('droptarget');
-    else
-      $(this.subscription_list.frame).removeClass('droptarget');
-  };
-
-  this.subscription_select = function(list)
-  {
-    var id, folder;
-
-    if (list && (id = list.get_single_selection()) &&
-        (folder = this.env.subscriptionrows['rcmrow'+id])
-    ) {
+    if (id && id != 'mailboxroot' && (folder = this.env.subscriptionrows[id])) {
       this.env.mailbox = folder[0];
       this.show_folder(folder[0]);
       this.enable_command('delete-folder', !folder[2]);
@@ -5792,24 +5805,21 @@
     }
   };
 
-  this.subscription_move_folder = function(list)
+  this.subscription_move_folder = function(from, to)
   {
-    if (this.env.mailbox && this.env.dstfolder !== null &&
-        this.env.dstfolder != this.env.mailbox &&
-        this.env.dstfolder != this.env.mailbox.replace(this.last_sub_rx, '')
-    ) {
-      var path = this.env.mailbox.split(this.env.delimiter),
-        basename = path.pop(),
-        newname = this.env.dstfolder === '' ? basename : this.env.dstfolder + this.env.delimiter + basename;
+    var source = this.env.subscriptionrows[from][0];
+      dest = this.env.subscriptionrows[to][0];
 
-      if (newname != this.env.mailbox) {
-        this.http_post('rename-folder', {_folder_oldname: this.env.mailbox, _folder_newname: newname}, this.set_busy(true, 'foldermoving'));
-        this.subscription_list.draglayer.hide();
+    if (source && dest !== null && source != dest && dest != source.replace(this.last_sub_rx, '')) {
+      var path = source.split(this.env.delimiter),
+        basename = path.pop(),
+        newname = dest === '' ? basename : dest + this.env.delimiter + basename;
+
+      if (newname != source) {
+        this.http_post('rename-folder', {_folder_oldname: source, _folder_newname: newname},
+          this.set_busy(true, 'foldermoving'));
       }
     }
-
-    this.drag_active = false;
-    this.unfocus_subscription(this.get_folder_row_id(this.env.dstfolder));
   };
 
   // tell server to create and subscribe a new mailbox
@@ -5825,8 +5835,7 @@
       folder = this.env.subscriptionrows[id][0];
 
     if (folder && confirm(this.get_label('deletefolderconfirm'))) {
-      var lock = this.set_busy(true, 'folderdeleting');
-      this.http_post('delete-folder', {_mbox: folder}, lock);
+      this.http_post('delete-folder', {_mbox: folder}, this.set_busy(true, 'folderdeleting'));
     }
   };
 
@@ -5838,9 +5847,9 @@
 
     var row, n, tmp, tmp_name, rowid, collator,
       folders = [], list = [], slist = [],
-      tbody = this.gui_objects.subscriptionlist.tBodies[0],
-      refrow = $('tr', tbody).get(1),
-      id = 'rcmrow'+((new Date).getTime());
+      list_element = $(this.gui_objects.subscriptionlist),
+      refrow = $('li', list_element).get(1),
+      id = 'rcmli'+((new Date).getTime());
 
     if (!refrow) {
       // Refresh page if we don't have a table row to clone
@@ -5855,7 +5864,7 @@
     row.attr({id: id, 'class': class_name});
 
     // set folder name
-    row.find('td:first').html(display_name);
+    $('.name', row).html(display_name);
 
     // update subscription checkbox
     $('input[name="_subscribed[]"]', row).val(name)
@@ -5926,12 +5935,13 @@
 
     // add row to the table
     if (rowid)
-      $('#'+rowid).after(row);
+      $('#' + rowid).after(row);
     else
-      row.appendTo(tbody);
+      list_element.append(row);
 
     // update list widget
-    this.subscription_list.clear_selection();
+    this.subscription_list.select();
+
     if (!skip_init)
       this.init_subscription_list();
 
@@ -5948,11 +5958,11 @@
     if (!this.gui_objects.subscriptionlist) {
       if (this.is_framed)
         return parent.rcmail.replace_folder_row(oldfolder, newfolder, display_name, is_protected, class_name);
+
       return false;
     }
 
     var i, n, len, name, dispname, oldrow, tmprow, row, level,
-      tbody = this.gui_objects.subscriptionlist.tBodies[0],
       folders = this.env.subscriptionrows,
       id = this.get_folder_row_id(oldfolder),
       prefix_len = oldfolder.length,
@@ -5963,7 +5973,6 @@
     // no renaming, only update class_name
     if (oldfolder == newfolder) {
       $('#'+id).attr('class', class_name || '');
-      this.subscription_list.focus();
       return;
     }
 
@@ -6000,7 +6009,7 @@
           for (i=level; i<0; i++)
             dispname = '&nbsp;&nbsp;&nbsp;&nbsp;' + dispname;
         }
-        row.find('td:first').html(dispname);
+        $('.name', row).html(dispname);
         this.env.subscriptionrows[id][1] = dispname;
       }
     }
@@ -6028,8 +6037,8 @@
 
   this._remove_folder_row = function(id)
   {
-    this.subscription_list.remove_row(id.replace(/^rcmrow/, ''));
-    $('#'+id).remove();
+    this.subscription_list.remove(id.replace(/^rcmli/, ''));
+    $('#' + id).remove();
     delete this.env.subscriptionrows[id];
   };
 
@@ -6460,6 +6469,10 @@
   // mark a mailbox as selected and set environment variable
   this.select_folder = function(name, prefix, encode)
   {
+    if (this.savedsearchlist) {
+      this.savedsearchlist.select('');
+    }
+
     if (this.treelist) {
       this.treelist.select(name);
     }
@@ -7499,8 +7512,10 @@
   // post the given form to a hidden iframe
   this.async_upload_form = function(form, action, onload)
   {
-    var frame, ts = new Date().getTime(),
-      frame_name = 'rcmupload'+ts;
+    // create hidden iframe
+    var ts = new Date().getTime(),
+      frame_name = 'rcmupload' + ts,
+      frame = this.async_upload_form_frame(frame_name);
 
     // upload progress support
     if (this.env.upload_progress_name) {
@@ -7515,31 +7530,24 @@
       field.val(ts);
     }
 
-    // have to do it this way for IE
-    // otherwise the form will be posted to a new window
-    if (document.all) {
-      document.body.insertAdjacentHTML('BeforeEnd', '<iframe name="'+frame_name+'"'
-        + ' src="program/resources/blank.gif" style="width:0;height:0;visibility:hidden;"></iframe>');
-      frame = $('iframe[name="'+frame_name+'"]');
-    }
-    // for standards-compliant browsers
-    else {
-      frame = $('<iframe>').attr('name', frame_name)
-        .css({border: 'none', width: 0, height: 0, visibility: 'hidden'})
-        .appendTo(document.body);
-    }
-
-    // handle upload errors, parsing iframe content in onload
+    // handle upload errors by parsing iframe content in onload
     frame.bind('load', {ts:ts}, onload);
 
     $(form).attr({
         target: frame_name,
-        action: this.url(action, { _id:this.env.compose_id||'', _uploadid:ts }),
+        action: this.url(action, {_id: this.env.compose_id || '', _uploadid: ts, _from: this.env.action}),
         method: 'POST'})
       .attr(form.encoding ? 'encoding' : 'enctype', 'multipart/form-data')
       .submit();
 
     return frame_name;
+  };
+
+  // create iframe element for files upload
+  this.async_upload_form_frame = function(name)
+  {
+    return $('<iframe>').attr({name: name, style: 'border: none; width: 0; height: 0; visibility: hidden'})
+      .appendTo(document.body);
   };
 
   // html5 file-drop API
@@ -7590,7 +7598,7 @@
       $.ajax({
         type: 'POST',
         dataType: 'json',
-        url: ref.url(ref.env.filedrop.action||'upload', { _id:ref.env.compose_id||ref.env.cid||'', _uploadid:ts, _remote:1 }),
+        url: ref.url(ref.env.filedrop.action || 'upload', {_id: ref.env.compose_id||ref.env.cid||'', _uploadid: ts, _remote: 1, _from: ref.env.action}),
         contentType: formdata ? false : 'multipart/form-data; boundary=' + boundary,
         processData: false,
         timeout: 0, // disable default timeout set in ajaxSetup()

--
Gitblit v1.9.1