thomascube
2007-03-13 1c7b97e81bea919c26bfe878312c5118c02ac0a9
program/js/app.js
@@ -26,13 +26,15 @@
  this.buttons = new Object();
  this.gui_objects = new Object();
  this.commands = new Object();
  this.onloads = new Array();
  // create public reference to myself
  // create protected reference to myself
  rcube_webmail_client = this;
  this.ref = 'rcube_webmail_client';
  var ref = this;
 
  // webmail client settings
  this.dblclick_time = 600;
  this.dblclick_time = 500;
  this.message_time = 5000;
  
  this.mbox_expression = new RegExp('[^0-9a-z\-_]', 'gi');
@@ -77,13 +79,17 @@
    this.buttons[command][this.buttons[command].length] = button_prop;    
    };
  // register a specific gui object
  this.gui_object = function(name, id)
    {
    this.gui_objects[name] = id;
    };
  // execute the given script on load
  this.add_onload = function(f)
    {
      this.onloads[this.onloads.length] = f;
    };
  // initialize webmail client
  this.init = function()
@@ -101,7 +107,7 @@
    // find all registered gui objects
    for (var n in this.gui_objects)
      this.gui_objects[n] = rcube_find_object(this.gui_objects[n]);
    // tell parent window that this frame is loaded
    if (this.env.framed && parent.rcmail && parent.rcmail.set_busy)
      parent.rcmail.set_busy(false);
@@ -137,7 +143,7 @@
        // enable mail commands
        this.enable_command('list', 'checkmail', 'compose', 'add-contact', 'search', 'reset-search', true);
        
        if (this.env.action=='show')
        if (this.env.action=='show' || this.env.action=='preview')
          {
          this.enable_command('show', 'reply', 'reply-all', 'forward', 'moveto', 'delete', 'viewsource', 'print', 'load-attachment', true);
          if (this.env.next_uid)
@@ -151,8 +157,16 @@
            this.enable_command('firstmessage', true);
            }
          }
        // make preview/message frame visible
        if (this.env.action == 'preview' && this.env.framed && parent.rcmail)
          {
          this.enable_command('compose', 'add-contact', false);
          parent.rcmail.show_messageframe(true);
          parent.rcmail.mark_message('read', this.uid);
          }
        if (this.env.action=='show' && this.env.blockedobjects)
        if ((this.env.action=='show' || this.env.action=='preview') && this.env.blockedobjects)
          {
          if (this.gui_objects.remoteobjectsmsg)
            this.gui_objects.remoteobjectsmsg.style.display = 'block';
@@ -285,16 +299,26 @@
    // start keep-alive interval
    this.start_keepalive();
    // execute all foreign onload scripts
    for (var i=0; i<this.onloads.length; i++)
      {
      if (typeof(this.onloads[i]) == 'string')
        eval(this.onloads[i]);
      else if (typeof(this.onloads[i]) == 'function')
        this.onloads[i]();
      }
    };
  // start interval for keep-alive/recent_check signal
  this.start_keepalive = function()
    {
    if (this.env.keep_alive && this.task=='mail' && this.gui_objects.messagelist)
      this._int = setInterval(this.ref+'.check_for_recent()', this.env.keep_alive * 1000);
    else if (this.env.keep_alive && this.task!='login')
      this._int = setInterval(this.ref+'.send_keep_alive()', this.env.keep_alive * 1000);
    if (this.env.keep_alive && !this.env.framed && this.task=='mail' && this.gui_objects.messagelist)
      this._int = setInterval(function(){ ref.check_for_recent(); }, this.env.keep_alive * 1000);
    else if (this.env.keep_alive && !this.env.framed && this.task!='login')
      this._int = setInterval(function(){ ref.send_keep_alive(); }, this.env.keep_alive * 1000);
    }
@@ -637,7 +661,7 @@
        
      case 'load-images':
        if (this.env.uid)
          this.show_message(this.env.uid, true);
          this.show_message(this.env.uid, true, this.env.action=='preview');
        break;
      case 'load-attachment':
@@ -646,10 +670,12 @@
        // open attachment in frame if it's of a supported mimetype
        if (this.env.uid && props.mimetype && find_in_array(props.mimetype, this.mimetypes)>=0)
          {
          this.attachment_win = window.open(this.env.comm_path+'&_action=get'+url+'&_frame=1', 'rcubemailattachment');
          if (props.mimetype == 'text/html')
            qstring += '&_safe=1';
          this.attachment_win = window.open(this.env.comm_path+'&_action=get&'+qstring+'&_frame=1', 'rcubemailattachment');
          if (this.attachment_win)
            {
            setTimeout(this.ref+'.attachment_win.focus()', 10);
            setTimeout(function(){ ref.attachment_win.focus(); }, 10);
            break;
            }
          }
@@ -667,17 +693,17 @@
      case 'nextmessage':
        if (this.env.next_uid)
          this.show_message(this.env.next_uid);
          this.show_message(this.env.next_uid, false, this.env.action=='preview');
        break;
     case 'lastmessage':
      case 'lastmessage':
        if (this.env.last_uid)
          this.show_message(this.env.last_uid);
        break;
      case 'previousmessage':
        if (this.env.prev_uid)
          this.show_message(this.env.prev_uid);
          this.show_message(this.env.prev_uid, false, this.env.action=='preview');
        break;
      case 'firstmessage':
@@ -826,19 +852,19 @@
        var uid;
        if (uid = this.get_single_uid())
          {
          this.printwin = window.open(this.env.comm_path+'&_action=print&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)+(this.env.safemode ? '&_safe=1' : ''));
          ref.printwin = window.open(this.env.comm_path+'&_action=print&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)+(this.env.safemode ? '&_safe=1' : ''));
          if (this.printwin)
            setTimeout(this.ref+'.printwin.focus()', 20);
            setTimeout(function(){ ref.printwin.focus(); }, 20);
          }
        break;
      case 'viewsource':
        var uid;
        if (uid = this.get_single_uid())
          {
          this.sourcewin = window.open(this.env.comm_path+'&_action=viewsource&_uid='+this.env.uid+'&_mbox='+urlencode(this.env.mailbox));
          {
          ref.sourcewin = window.open(this.env.comm_path+'&_action=viewsource&_uid='+this.env.uid+'&_mbox='+urlencode(this.env.mailbox));
          if (this.sourcewin)
            setTimeout(this.ref+'.sourcewin.focus()', 20);
            setTimeout(function(){ ref.sourcewin.focus(); }, 20);
          }
        break;
@@ -960,7 +986,7 @@
    // set timer for requests
    if (a && this.env.request_timeout)
      this.request_timer = setTimeout(this.ref+'.request_timed_out()', this.env.request_timeout * 1000);
      this.request_timer = setTimeout(function(){ ref.request_timed_out(); }, this.env.request_timeout * 1000);
    };
@@ -1052,6 +1078,9 @@
  this.msglist_select = function(list)
    {
    if (this.preview_timer)
      clearTimeout(this.preview_timer);
    var selected = list.selection.length==1;
    if (this.env.mailbox == this.env.drafts_mailbox)
      {
@@ -1063,16 +1092,25 @@
      this.enable_command('show', 'reply', 'reply-all', 'forward', 'print', selected);
      this.enable_command('delete', 'moveto', list.selection.length>0 ? true : false);
      }
   };
    // start timer for message preview (wait for double click)
    if (selected && this.env.contentframe)
      this.preview_timer = setTimeout(function(){ ref.msglist_get_preview(); }, this.dblclick_time + 10);
    else if (this.env.contentframe)
      this.show_messageframe(false);
    };
  this.msglist_dbl_click = function(list)
    {
      if (this.preview_timer)
        clearTimeout(this.preview_timer);
    var uid = list.get_single_selection();
    if (uid && this.env.mailbox == this.env.drafts_mailbox)
      this.goto_url('compose', '_draft_uid='+uid+'&_mbox='+urlencode(this.env.mailbox), true);
    else if (uid)
      this.show_message(uid);
      this.show_message(uid, false, false);
    };
@@ -1085,6 +1123,15 @@
    };
  this.msglist_get_preview = function()
  {
    var uid = this.get_single_uid();
    if (uid && this.env.contentframe)
      this.show_message(uid, false, true);
    else if (this.env.contentframe)
      this.show_messageframe(false);
  };
  /*********************************************************/
  /*********     (message) list functionality      *********/
@@ -1092,11 +1139,12 @@
  // when user doble-clicks on a row
  this.show_message = function(id, safe)
  this.show_message = function(id, safe, preview)
    {
    var add_url = '';
    var action = preview ? 'preview': 'show';
    var target = window;
    if (this.env.contentframe && window.frames && window.frames[this.env.contentframe])
    if (preview && this.env.contentframe && window.frames && window.frames[this.env.contentframe])
      {
      target = window.frames[this.env.contentframe];
      add_url = '&_framed=1';
@@ -1107,11 +1155,31 @@
    if (id)
      {
      this.set_busy(true, 'loading');
      target.location.href = this.env.comm_path+'&_action=show&_uid='+id+'&_mbox='+urlencode(this.env.mailbox)+add_url;
      var url = '&_action='+action+'&_uid='+id+'&_mbox='+urlencode(this.env.mailbox)+add_url;
      if (action == 'preview' && String(target.location.href).indexOf(url) >= 0)
        this.show_messageframe(true);
      else
        {
        this.set_busy(true, 'loading');
        target.location.href = this.env.comm_path+url;
        }
      }
    };
  this.show_messageframe = function(show)
    {
    var frm;
    if (this.env.contentframe && (frm = rcube_find_object(this.env.contentframe)))
      {
      if (window.frames[this.env.contentframe] && !show)
        window.frames[this.env.contentframe].location.href = 'program/blank.gif';
      frm.style.display = show ? 'block' : 'none';
      }
    if (!show && this.busy)
      this.set_busy(false);
    };
  // list a specific page
@@ -1158,7 +1226,9 @@
      page = 1;
      add_url += '&_refresh=1';
      this.env.current_page = page;
      this.message_list.clear_selection();
      if (this.message_list)
        this.message_list.clear_selection();
      this.show_messageframe(false);
      }
    
    // also send search request to get the right messages
@@ -1267,25 +1337,8 @@
        return;
      }
    var a_uids = new Array();
    if (this.env.uid)
      a_uids[a_uids.length] = this.env.uid;
    else
      {
      var selection = this.message_list.get_selection();
      var id;
      for (var n=0; n<selection.length; n++)
        {
        id = selection[n];
        a_uids[a_uids.length] = id;
        this.message_list.remove_row(id);
        }
      this.message_list.select_next();
      }
    var lock = false;
    var add_url = '&_target_mbox='+urlencode(mbox)+'&_from='+(this.env.action ? this.env.action : '');
    // show wait message
    if (this.env.action=='show')
@@ -1293,71 +1346,40 @@
      lock = true;
      this.set_busy(true, 'movingmessage');
      }
    else
      this.show_messageframe(false);
    // send request to server
    this.http_request('moveto', '_uid='+a_uids.join(',')+'&_mbox='+urlencode(this.env.mailbox)+'&_target_mbox='+urlencode(mbox)+'&_from='+(this.env.action ? this.env.action : ''), lock);
    this._with_selected_messages('moveto', lock, add_url);
    };
  this.permanently_remove_messages = function()
    {
    // exit if no mailbox specified or if selection is empty
    if (!this.env.uid)
      {
      if (!this.message_list || !this.message_list.get_selection().length)
        return;
      }
    var a_uids = new Array();
    if (this.env.uid)
      a_uids[a_uids.length] = this.env.uid;
    else
      {
      var selection = this.message_list.get_selection();
      var id;
      for (var n=0; n<selection.length; n++)
        {
        id = selection[n];
        a_uids[a_uids.length] = id;
        this.message_list.remove_row(id);
        }
      this.message_list.select_next();
      }
    // send request to server
    this.http_request('delete', '_uid='+a_uids.join(',')+'&_mbox='+urlencode(this.env.mailbox)+'&_from='+(this.env.action ? this.env.action : ''));
  }
  // delete selected messages from the current mailbox
  this.delete_messages = function()
    {
    var selection = this.message_list ? this.message_list.get_selection() : new Array();
    // exit if no mailbox specified or if selection is empty
    if (!this.env.uid)
      {
      if (!this.message_list || !this.message_list.get_selection().length)
    if (!this.env.uid && !selection.length)
        return;
      }
    // if there is a trash mailbox defined and we're not currently in it:
    if (this.env.trash_mailbox && String(this.env.mailbox).toLowerCase()!=String(this.env.trash_mailbox).toLowerCase())
    if (this.env.trash_mailbox && String(this.env.mailbox).toLowerCase() != String(this.env.trash_mailbox).toLowerCase())
      {
      // if shift was pressed delete it immediately
      if (this.message_list.shiftkey)
      if (this.message_list && this.message_list.shiftkey)
        {
        if (confirm(this.get_label('deletemessagesconfirm')))
          this.permanently_remove_messages();
        }
      else
        this.move_messages(this.env.trash_mailbox);
      }
    // if there is a trash mailbox defined but we *are* in it:
    else if (this.env.trash_mailbox && String(this.env.mailbox).toLowerCase() == String(this.env.trash_mailbox).toLowerCase())
      this.permanently_remove_messages();
    // if there isn't a defined trash mailbox and the config is set to flag for deletion
    else if (!this.env.trash_mailbox && this.env.flag_for_deletion)
      {
      flag = 'delete';
      this.mark_message(flag);
      this.mark_message('delete');
      if(this.env.action=="show")
        this.command('nextmessage','',this);
      else if (selection.length == 1)
@@ -1369,25 +1391,71 @@
  };
  // set a specific flag to one or more messages
  this.mark_message = function(flag, uid)
  // delete the selected messages permanently
  this.permanently_remove_messages = function()
    {
    // exit if no mailbox specified or if selection is empty
    if (!this.env.uid && (!this.message_list || !this.message_list.get_selection().length))
      return;
    this.show_messageframe(false);
    this._with_selected_messages('delete', false, '&_from='+(this.env.action ? this.env.action : ''));
    };
  // Send a specifc request with UIDs of all selected messages
  // @private
  this._with_selected_messages = function(action, lock, add_url)
    {
    var a_uids = new Array();
    var selection = this.message_list.get_selection();
    if (uid)
      a_uids[0] = uid;
    else if (this.env.uid)
      a_uids[0] = this.env.uid;
    if (this.env.uid)
      a_uids[a_uids.length] = this.env.uid;
    else
      {
      var selection = this.message_list.get_selection();
      var id;
      for (var n=0; n<selection.length; n++)
        {
        id = selection[n];
        a_uids[a_uids.length] = id;
        this.message_list.remove_row(id);
        }
      this.message_list.select_next();
      }
    // also send search request to get the right messages
    if (this.env.search_request)
      add_url += '&_search='+this.env.search_request;
    // send request to server
    this.http_request(action, '_uid='+a_uids.join(',')+'&_mbox='+urlencode(this.env.mailbox)+add_url, lock);
    };
  // set a specific flag to one or more messages
  this.mark_message = function(flag, uid)
    {
    var a_uids = new Array();
    var selection = this.message_list ? this.message_list.get_selection() : new Array();
    if (uid)
      a_uids[0] = uid;
    else if (this.env.uid)
      a_uids[0] = this.env.uid;
    else if (this.message_list)
      {
      for (var id, n=0; n<selection.length; n++)
        {
        id = selection[n];
        if ((flag=='read' && this.message_list.rows[id].unread) || (flag=='unread' && !this.message_list.rows[id].unread)
            || (flag=='delete' && !this.message_list.rows[id].deleted) || (flag=='undelete' && this.message_list.rows[id].deleted))
          a_uids[a_uids.length] = id;
        }
      }
    // nothing to do
    if (!a_uids.length)
      return;
      
    switch (flag)
      {
@@ -1453,7 +1521,8 @@
      return false;
    var rows = this.message_list.rows;
    if (a_uids.length==1) {
    if (a_uids.length==1)
    {
      if (rows[a_uids[0]] && rows[a_uids[0]].classname.indexOf('deleted') < 0)
        this.flag_as_deleted(a_uids);
      else
@@ -1463,10 +1532,12 @@
    }
    
    var all_deleted = true;
    for (var i=0; i<a_uids.length; i++) {
    for (var i=0; i<a_uids.length; i++)
    {
      uid = a_uids[i];
      if (rows[uid]) {
        if (rows[uid].classname.indexOf('deleted')<0) {
        if (rows[uid].classname.indexOf('deleted')<0)
        {
          all_deleted = false;
          break;
        }
@@ -1491,12 +1562,14 @@
    var icn_src;
    var rows = this.message_list.rows;
      
    for (var i=0; i<a_uids.length; i++) {
    for (var i=0; i<a_uids.length; i++)
    {
      uid = a_uids[i];
      if (rows[uid]) {
        rows[uid].deleted = false;
        
        if (rows[uid].classname.indexOf('deleted') > 0) {
        if (rows[uid].classname.indexOf('deleted') > 0)
        {
          rows[uid].classname = rows[uid].classname.replace(/\s*deleted/, '');
          this.set_classname(rows[uid].obj, 'deleted', false);
        }
@@ -1523,7 +1596,8 @@
      return false;
    var rows = this.message_list.rows;
    for (var i=0; i<a_uids.length; i++) {
    for (var i=0; i<a_uids.length; i++)
    {
      uid = a_uids[i];
      if (rows[uid]) {
        rows[uid].deleted = true;
@@ -1616,7 +1690,7 @@
  this.auto_save_start = function()
    {
    if (this.env.draft_autosave)
      this.save_timer = self.setTimeout(this.ref+'.command("savedraft")', this.env.draft_autosave * 1000);
      this.save_timer = self.setTimeout(function(){ ref.command("savedraft"); }, this.env.draft_autosave * 1000);
    };
@@ -1665,50 +1739,54 @@
      if (this.env.identity && this.env.signatures && this.env.signatures[this.env.identity])
        {
        sig = this.env.signatures[this.env.identity]['text'];
        if (sig.indexOf('--')!=0)
          sig = '--\n'+sig;
        if (sig.indexOf('-- ')!=0)
          sig = '-- \n'+sig;
        p = message.lastIndexOf(sig);
        if (p>=0)
          message = message.substring(0, p-1) + message.substring(p+sig.length, message.length);
        }
      // add the new signature string
      if (this.env.signatures && this.env.signatures[id])
        {
        sig = this.env.signatures[id]['text'];
        if (sig.indexOf('--')!=0)
          sig = '--\n'+sig;
        if (this.env.signatures[id]['is_html'])
          {
          sig = this.env.signatures[id]['plain_text'];
          }
        if (sig.indexOf('-- ')!=0)
          sig = '-- \n'+sig;
        message += '\n'+sig;
        }
      }
    else
      {
        var eid = tinyMCE.getEditorId('_message');
        // editor is a TinyMCE_Control object
        var editor = tinyMCE.getInstanceById(eid);
        var msgDoc = editor.getDoc();
        var msgBody = msgDoc.body;
      var eid = tinyMCE.getEditorId('_message');
      // editor is a TinyMCE_Control object
      var editor = tinyMCE.getInstanceById(eid);
      var msgDoc = editor.getDoc();
      var msgBody = msgDoc.body;
        if (this.env.signatures && this.env.signatures[id])
      if (this.env.signatures && this.env.signatures[id])
        {
        // Append the signature as a span within the body
        var sigElem = msgDoc.getElementById("_rc_sig");
        if (!sigElem)
          {
          // Append the signature as a span within the body
          var sigElem = msgDoc.getElementById("_rc_sig");
          if (!sigElem)
            {
            sigElem = msgDoc.createElement("span");
            sigElem.setAttribute("id", "_rc_sig");
            msgBody.appendChild(sigElem);
            }
          if (this.env.signatures[id]['is_html'])
            {
            sigElem.innerHTML = this.env.signatures[id]['text'];
            }
          else
            {
            sigElem.innerHTML = '<pre>' + this.env.signatures[id]['text'] + '</pre>';
            }
          sigElem = msgDoc.createElement("span");
          sigElem.setAttribute("id", "_rc_sig");
          msgBody.appendChild(sigElem);
          }
        if (this.env.signatures[id]['is_html'])
          {
          sigElem.innerHTML = this.env.signatures[id]['text'];
          }
        else
          {
          sigElem.innerHTML = '<pre>' + this.env.signatures[id]['text'] + '</pre>';
          }
        }
      }
    if (input_message)
@@ -1963,7 +2041,7 @@
      }
    // start timer
    this.ksearch_timer = setTimeout(this.ref+'.ksearch_get_results()', 200);
    this.ksearch_timer = setTimeout(function(){ ref.ksearch_get_results(); }, 200);
    this.ksearch_input = obj;
    
    return true;
@@ -2511,6 +2589,7 @@
        form.elements['_folder_name'].value = ''; 
      }
    this.sort_subscription_list();
    };
@@ -2657,6 +2736,32 @@
      }
    
    return new_row;
    };
  // sort subscription folder list
  this.sort_subscription_list = function()
    {
    var index = new Array();
    var tbody = this.gui_objects.subscriptionlist.tBodies[0];
    var swapped = false;
    for (var i = 0; i<(tbody.childNodes.length-1); i++)
      if (this.env.subscriptionrows[tbody.childNodes[i].id]!=null)
        index.push(i);
    for (i = 0; i<(index.length-1); i++)
      {
      if (this.env.subscriptionrows[tbody.childNodes[index[i]].id][0]>
          this.env.subscriptionrows[tbody.childNodes[index[i+1]].id][0])
        {
        var swap = tbody.replaceChild(tbody.childNodes[index[i]], tbody.childNodes[index[i+1]]);
        if (typeof(tbody.childNodes[index[i]]) != 'undefined')
          tbody.insertBefore(swap, tbody.childNodes[index[i]])
        else
          tbody.appendChild(swap);
        swapped = true;
        }
      }
    if (swapped)
      this.sort_subscription_list();
    };
@@ -2827,7 +2932,7 @@
      this.gui_objects.message.onmousedown = function(){ this._rcube.hide_message(); return true; };
    
    if (!hold)
      this.message_timer = setTimeout(this.ref+'.hide_message()', this.message_time);
      this.message_timer = setTimeout(function(){ ref.hide_message(); }, this.message_time);
    };
@@ -2966,10 +3071,14 @@
    };
  // replace content of quota display
   this.set_quota = function(text)
   this.set_quota = function()
     {
     if (this.gui_objects.quotadisplay)
       this.gui_objects.quotadisplay.innerHTML = text;
     if (this.gui_objects.quotadisplay &&
         this.gui_objects.quotadisplay.attributes.getNamedItem('display') &&
         this.gui_objects.quotadisplay.attributes.getNamedItem('id'))
       this.http_request('quotadisplay', '_display='+
         this.gui_objects.quotadisplay.attributes.getNamedItem('display').nodeValue+
         '&_id='+this.gui_objects.quotadisplay.attributes.getNamedItem('id').nodeValue, false);
     };
@@ -3102,7 +3211,7 @@
  this.http_request = function(action, querystring, lock)
    {
    var request_obj = this.get_request_obj();
    querystring += '&_remote=1';
    querystring += (querystring ? '&' : '') + '_remote=1';
    
    // add timestamp to request url to avoid cacheing problems in Safari
    if (bw.safari)
@@ -3151,11 +3260,13 @@
      case 'moveto':
        if (this.env.action=='show')
          this.command('list');
        else if (this.message_list)
          this.message_list.init();
        break;
      case 'list':
        if (this.env.messagecount)
          this.enable_command('purge', (this.env.mailbox==this.env.trash_mailbox));
          this.enable_command('purge', (this.env.mailbox==this.env.trash_mailbox || this.env.mailbox==this.env.junk_mailbox));
      case 'expunge':
        this.enable_command('select-all', 'select-none', 'expunge', this.env.messagecount ? true : false);