Aleksander Machniak
2015-01-13 a109d19a77f017bad2e8b5bc830dc244b0e29ffb
program/js/app.js
@@ -58,7 +58,6 @@
    request_timeout: 180,  // seconds
    draft_autosave: 0,     // seconds
    comm_path: './',
    blankpage: 'program/resources/blank.gif',
    recipients_separator: ',',
    recipients_delimiter: ', ',
    popup_width: 1150,
@@ -162,6 +161,9 @@
      this.goto_url('error', '_code=0x199');
      return;
    }
    if (!this.env.blankpage)
      this.env.blankpage = this.assets_path('program/resources/blank.gif');
    // find all registered gui containers
    for (n in this.gui_containers)
@@ -556,7 +558,7 @@
    // show message
    if (this.pending_message)
      this.display_message(this.pending_message[0], this.pending_message[1], this.pending_message[2]);
      this.display_message.apply(this, this.pending_message);
    // init treelist widget
    if (this.gui_objects.folderlist && window.rcube_treelist_widget) {
@@ -572,6 +574,7 @@
      this.treelist
        .addEventListener('collapse', function(node) { ref.folder_collapsed(node) })
        .addEventListener('expand', function(node) { ref.folder_collapsed(node) })
        .addEventListener('beforeselect', function(node) { return !ref.busy; })
        .addEventListener('select', function(node) { ref.triggerEvent('selectfolder', { folder:node.id, prefix:'rcmli' }) });
    }
@@ -630,8 +633,9 @@
    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)
    if (this.busy && !(command == 'reset-search' && this.last_command == 'search'))
    // do nothing if interface is locked by another command
    // with exception for searching reset and menu
    if (this.busy && !(command == 'reset-search' && this.last_command == 'search') && !command.match(/^menu-/))
      return false;
    // let the browser handle this click (shift/ctrl usually opens the link in a new window/tab)
@@ -1212,7 +1216,8 @@
      // reset quicksearch
      case 'reset-search':
        var n, s = this.env.search_request || this.env.qsearch;
        var n, s = this.env.search_request || this.env.qsearch,
            ss = this.gui_objects.qsearchbox && this.gui_objects.qsearchbox.value != '';
        this.reset_qsearch();
        this.select_all_mode = false;
@@ -1221,7 +1226,7 @@
          if (this.contact_list)
            this.list_contacts_clear();
        }
        else if (s && this.env.mailbox) {
        else if (s && ss && this.env.mailbox) {
          this.list_mailbox(this.env.mailbox, 1);
        }
        else if (s && this.task == 'addressbook') {
@@ -1405,8 +1410,10 @@
    if (task == 'mail')
      url += '&_mbox=INBOX';
    else if (task == 'logout' && !this.env.server_error)
    else if (task == 'logout' && !this.env.server_error) {
      url += '&_token=' + this.env.request_token;
      this.clear_compose_data();
    }
    this.redirect(url);
  };
@@ -1416,7 +1423,10 @@
    if (!url)
      url = this.env.comm_path;
    return url.replace(/_task=[a-z0-9_-]+/i, '_task='+task);
    if (url.match(/[?&]_task=[a-zA-Z0-9_-]+/))
        return url.replace(/_task=[a-zA-Z0-9_-]+/, '_task=' + task);
    else
        return url.replace(/\?.*$/, '') + '?_task=' + task;
  };
  this.reload = function(delay)
@@ -2027,7 +2037,7 @@
    }
    if (flags.forwarded) {
      status_class += ' forwarded';
      status_label += this.get_label('replied') + ' ';
      status_label += this.get_label('forwarded') + ' ';
    }
    // update selection
@@ -2251,7 +2261,7 @@
      if (preview && this.message_list && this.message_list.rows[id] && this.message_list.rows[id].unread && this.env.preview_pane_mark_read > 0) {
        this.preview_read_timer = setTimeout(function() {
          ref.set_unread_message(id, ref.env.mailbox);
          ref.http_post('mark', {_uid: id, _flag: 'read', _quiet: 1});
          ref.http_post('mark', {_uid: id, _flag: 'read', _mbox: ref.env.mailbox, _quiet: 1});
        }, this.env.preview_pane_mark_read * 1000);
      }
    }
@@ -3426,6 +3436,7 @@
          this.get_label('restoremessage'),
          [{
            text: this.get_label('restore'),
            'class': 'mainaction',
            click: function(){
              ref.restore_compose_form(key, html_mode);
              ref.remove_compose_data(key);  // remove old copy
@@ -3435,6 +3446,7 @@
          },
          {
            text: this.get_label('delete'),
            'class': 'delete',
            click: function(){
              ref.remove_compose_data(key);
              $(this).dialog('close');
@@ -3687,7 +3699,7 @@
      $(this).dialog('close');
    };
    this.show_popup_dialog(html, this.gettext('newresponse'), buttons);
    this.show_popup_dialog(html, this.gettext('newresponse'), buttons, {button_classes: ['mainaction']});
    $('#ffresponsetext').val(text);
    $('#ffresponsename').select();
@@ -3769,14 +3781,13 @@
  this.set_draft_id = function(id)
  {
    var rc;
    if (id && id != this.env.draft_id) {
      if (rc = this.opener()) {
        // refresh the drafts folder in opener window
        if (rc.env.task == 'mail' && rc.env.action == '' && rc.env.mailbox == this.env.drafts_mailbox)
          rc.command('checkmail');
      }
      var filter = {task: 'mail', action: ''},
        rc = this.opener(false, filter) || this.opener(true, filter);
      // refresh the drafts folder in the opener window
      if (rc && rc.env.mailbox == this.env.drafts_mailbox)
        rc.command('checkmail');
      this.env.draft_id = id;
      $("input[name='_draft_saveid']").val(id);
@@ -4762,6 +4773,9 @@
    if (!src)
      src = this.env.source;
    if (refresh)
      group = this.env.group;
    if (page && this.current_page == page && src == this.env.source && group == this.env.group)
      return false;
@@ -5173,6 +5187,7 @@
    this.show_popup_dialog(content, this.get_label('newgroup'),
      [{
        text: this.get_label('save'),
        'class': 'mainaction',
        click: function() {
          var name;
@@ -5200,6 +5215,7 @@
    this.show_popup_dialog(content, this.get_label('grouprename'),
      [{
        text: this.get_label('save'),
        'class': 'mainaction',
        click: function() {
          var name;
@@ -5563,6 +5579,7 @@
    this.show_popup_dialog(content, this.get_label('searchsave'),
      [{
        text: this.get_label('save'),
        'class': 'mainaction',
        click: function() {
          var name;
@@ -5781,6 +5798,9 @@
        // 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) {
          if (!$(node).is('.mailbox'))
            return false;
          var source_folder = ref.folder_id2name($(node).attr('id')),
            dest_folder = ref.folder_id2name(this.id),
            source = ref.env.subscriptionrows[source_folder],
@@ -5801,7 +5821,7 @@
  this.folder_id2name = function(id)
  {
    return ref.html_identifier_decode(id.replace(/^rcmli/, ''));
    return id ? ref.html_identifier_decode(id.replace(/^rcmli/, '')) : null;
  };
  this.subscription_select = function(id)
@@ -6347,7 +6367,7 @@
  };
  // display a system message, list of types in common.css (below #message definition)
  this.display_message = function(msg, type, timeout)
  this.display_message = function(msg, type, timeout, key)
  {
    // pass command to parent window
    if (this.is_framed())
@@ -6356,18 +6376,34 @@
    if (!this.gui_objects.message) {
      // save message in order to display after page loaded
      if (type != 'loading')
        this.pending_message = [msg, type, timeout];
        this.pending_message = [msg, type, timeout, key];
      return 1;
    }
    type = type ? type : 'notice';
    if (!type)
      type = 'notice';
    var key = this.html_identifier(msg),
      date = new Date(),
    if (!key)
      key = this.html_identifier(msg);
    var date = new Date(),
      id = type + date.getTime();
    if (!timeout)
      timeout = this.message_time * (type == 'error' || type == 'warning' ? 2 : 1);
    if (!timeout) {
      switch (type) {
        case 'error':
        case 'warning':
          timeout = this.message_time * 2;
          break;
        case 'uploading':
          timeout = 0;
          break;
        default:
          timeout = this.message_time;
      }
    }
    if (type == 'loading') {
      key = 'loading';
@@ -6400,7 +6436,7 @@
    if (type == 'loading') {
      this.messages[key].labels = [{'id': id, 'msg': msg}];
    }
    else {
    else if (type != 'uploading') {
      obj.click(function() { return ref.hide_message(obj); })
        .attr('role', 'alert');
    }
@@ -6409,6 +6445,7 @@
    if (timeout > 0)
      setTimeout(function() { ref.hide_message(id, type != 'loading'); }, timeout);
    return id;
  };
@@ -6487,6 +6524,35 @@
    this.messages = {};
  };
  // display uploading message with progress indicator
  // data should contain: name, total, current, percent, text
  this.display_progress = function(data)
  {
    if (!data || !data.name)
      return;
    var msg = this.messages['progress' + data.name];
    if (!data.label)
      data.label = this.get_label('uploadingmany');
    if (!msg) {
      if (!data.percent || data.percent < 100)
        this.display_message(data.label, 'uploading', 0, 'progress' + data.name);
      return;
    }
    if (!data.total || data.percent >= 100) {
      this.hide_message(msg.obj);
      return;
    }
    if (data.text)
      data.label += ' ' + data.text;
    msg.obj.text(data.label);
  };
  // open a jquery UI dialog with the given content
  this.show_popup_dialog = function(content, title, buttons, options)
  {
@@ -6502,14 +6568,16 @@
    else
      popup.html(content);
    popup.dialog($.extend({
    options = $.extend({
        title: title,
        buttons: buttons,
        modal: true,
        resizable: true,
        width: 500,
        close: function(event, ui) { $(this).remove(); }
      }, options || {}));
      }, options || {});
    popup.dialog(options);
    // resize and center popup
    var win = $(window), w = win.width(), h = win.height(),
@@ -6518,6 +6586,11 @@
    popup.dialog('option', {
      height: Math.min(h - 40, height + 75 + (buttons ? 50 : 0)),
      width: Math.min(w - 20, width + 36)
    });
    // assign special classes to dialog buttons
    $.each(options.button_classes || [], function(i, v) {
      if (v) $($('.ui-dialog-buttonpane button.ui-button', popup.parent()).get(i)).addClass(v);
    });
    return popup;
@@ -6656,7 +6729,7 @@
  this.set_quota = function(content)
  {
    if (this.gui_objects.quotadisplay && content && content.type == 'text')
      $(this.gui_objects.quotadisplay).html(content.percent+'%').attr('title', content.title);
      $(this.gui_objects.quotadisplay).text((content.percent||0) + '%').attr('title', content.title);
    this.triggerEvent('setquota', content);
    this.env.quota_content = content;
@@ -7823,12 +7896,24 @@
  };
  // get window.opener.rcmail if available
  this.opener = function()
  this.opener = function(deep, filter)
  {
    var i, win = window.opener;
    // catch Error: Permission denied to access property rcmail
    try {
      if (window.opener && !opener.closed && opener.rcmail)
        return opener.rcmail;
      if (win && !win.closed) {
        // try parent of the opener window, e.g. preview frame
        if (deep && (!win.rcmail || win.rcmail.env.framed) && win.parent && win.parent.rcmail)
          win = win.parent;
        if (win.rcmail && filter)
          for (i in filter)
            if (win.rcmail.env[i] != filter[i])
              return;
        return win.rcmail;
      }
    }
    catch (e) {}
  };
@@ -7982,7 +8067,7 @@
    img.onload = function() { ref.env.browser_capabilities.tif = 1; };
    img.onerror = function() { ref.env.browser_capabilities.tif = 0; };
    img.src = 'program/resources/blank.tif';
    img.src = this.assets_path('program/resources/blank.tif');
  };
  this.pdf_support_check = function()
@@ -7995,7 +8080,7 @@
    if (plugin && plugin.enabledPlugin)
        return 1;
    if (window.ActiveXObject) {
    if ('ActiveXObject' in window) {
      try {
        if (plugin = new ActiveXObject("AcroPDF.PDF"))
          return 1;
@@ -8028,7 +8113,7 @@
    if (plugin && plugin.enabledPlugin)
        return 1;
    if (window.ActiveXObject) {
    if ('ActiveXObject' in window) {
      try {
        if (plugin = new ActiveXObject("ShockwaveFlash.ShockwaveFlash"))
          return 1;
@@ -8037,6 +8122,15 @@
    }
    return 0;
  };
  this.assets_path = function(path)
  {
    if (this.env.assets_path && !path.startsWith(this.env.assets_path)) {
      path = this.env.assets_path + path;
    }
    return path;
  };
  // Cookie setter
@@ -8103,7 +8197,7 @@
  if (!elem.title) {
    var $elem = $(elem);
    if ($elem.width() + (indent || 0) * 15 > $elem.parent().width())
      elem.title = $elem.text();
      elem.title = rcube_webmail.subject_text(elem);
  }
};
@@ -8120,10 +8214,17 @@
    tmp.remove();
    if (w + $('span.branch', $elem).width() * 15 > $elem.width())
      elem.title = txt;
      elem.title = rcube_webmail.subject_text(elem);
  }
};
rcube_webmail.subject_text = function(elem)
{
  var t = $(elem).clone();
  t.find('.skip-on-drag').remove();
  return t.text();
};
rcube_webmail.prototype.get_cookie = getCookie;
// copy event engine prototype