Aleksander Machniak
2014-06-29 3cc1afa1c2f30bfebb30146795e50172947b4b5f
program/js/app.js
@@ -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) {
@@ -409,6 +412,17 @@
          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();
@@ -551,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,
@@ -615,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)
@@ -1677,7 +1692,7 @@
      case 63232: // "up", in safari keypress
      case 63233: // "down", in safari keypress
        focus_menu_item(keyCode == 38 || keyCode == 63232 ? -1 : 1);
        break;
        return rcube_event.cancel(e);
      case 9:   // tab
        if (this.focused_menu) {
@@ -3485,6 +3500,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) {
@@ -3553,26 +3574,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;
    }
@@ -3650,7 +3677,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();
@@ -4056,6 +4083,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;
@@ -4064,7 +4099,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>');
@@ -4081,10 +4116,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;
  };
@@ -4280,21 +4314,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);
    }
  };
@@ -4740,7 +4775,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) {
@@ -5164,7 +5200,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));
@@ -5265,7 +5301,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) });
  };
@@ -5547,7 +5583,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;
@@ -5573,7 +5609,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 });
    }
@@ -5593,7 +5629,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;
@@ -6458,6 +6500,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);
    }
@@ -7497,8 +7543,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) {
@@ -7513,26 +7561,12 @@
      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();
@@ -7540,6 +7574,13 @@
    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
  this.document_drag_hover = function(e, over)
  {