Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2530928
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
51 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/program/js/common.js b/program/js/common.js
index 53dce8cc2..35f5a0f38 100644
--- a/program/js/common.js
+++ b/program/js/common.js
@@ -1,830 +1,719 @@
/*
+-----------------------------------------------------------------------+
| Roundcube common js library |
| |
| This file is part of the Roundcube web development suite |
| Copyright (C) 2005-2012, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
// Constants
var CONTROL_KEY = 1;
var SHIFT_KEY = 2;
var CONTROL_SHIFT_KEY = 3;
/**
* Default browser check class
* @constructor
*/
function roundcube_browser()
{
var n = navigator;
this.ver = parseFloat(n.appVersion);
this.appver = n.appVersion;
this.agent = n.userAgent;
this.agent_lc = n.userAgent.toLowerCase();
this.name = n.appName;
this.vendor = n.vendor ? n.vendor : '';
this.vendver = n.vendorSub ? parseFloat(n.vendorSub) : 0;
this.product = n.product ? n.product : '';
this.platform = String(n.platform).toLowerCase();
this.lang = (n.language) ? n.language.substring(0,2) :
(n.browserLanguage) ? n.browserLanguage.substring(0,2) :
(n.systemLanguage) ? n.systemLanguage.substring(0,2) : 'en';
this.win = (this.platform.indexOf('win') >= 0);
this.mac = (this.platform.indexOf('mac') >= 0);
this.linux = (this.platform.indexOf('linux') >= 0);
this.unix = (this.platform.indexOf('unix') >= 0);
this.dom = document.getElementById ? true : false;
this.dom2 = (document.addEventListener && document.removeEventListener);
this.ie = (document.all && !window.opera);
this.ie4 = (this.ie && !this.dom);
this.ie5 = (this.dom && this.appver.indexOf('MSIE 5')>0);
this.ie8 = (this.dom && this.appver.indexOf('MSIE 8')>0);
this.ie9 = (this.dom && this.appver.indexOf('MSIE 9')>0);
this.ie7 = (this.dom && this.appver.indexOf('MSIE 7')>0);
this.ie6 = (this.dom && !this.ie8 && !this.ie7 && this.appver.indexOf('MSIE 6')>0);
this.ns = ((this.ver < 5 && this.name == 'Netscape') || (this.ver >= 5 && this.vendor.indexOf('Netscape') >= 0));
this.chrome = (this.agent_lc.indexOf('chrome') > 0);
this.safari = (!this.chrome && (this.agent_lc.indexOf('safari') > 0 || this.agent_lc.indexOf('applewebkit') > 0));
this.konq = (this.agent_lc.indexOf('konqueror') > 0);
this.mz = (this.dom && !this.ie && !this.ns && !this.chrome && !this.safari && !this.konq && this.agent.indexOf('Mozilla') >= 0);
this.iphone = (this.safari && this.agent_lc.indexOf('iphone') > 0);
this.ipad = (this.safari && this.agent_lc.indexOf('ipad') > 0);
this.opera = window.opera ? true : false;
if (this.opera && window.RegExp)
this.vendver = (/opera(\s|\/)([0-9\.]+)/.test(this.agent_lc)) ? parseFloat(RegExp.$2) : -1;
else if (this.chrome && window.RegExp)
this.vendver = (/chrome\/([0-9\.]+)/.test(this.agent_lc)) ? parseFloat(RegExp.$1) : 0;
else if (!this.vendver && this.safari)
this.vendver = (/(safari|applewebkit)\/([0-9]+)/.test(this.agent_lc)) ? parseInt(RegExp.$2) : 0;
else if ((!this.vendver && this.mz) || this.agent.indexOf('Camino')>0)
this.vendver = (/rv:([0-9\.]+)/.test(this.agent)) ? parseFloat(RegExp.$1) : 0;
else if (this.ie && window.RegExp)
this.vendver = (/msie\s+([0-9\.]+)/.test(this.agent_lc)) ? parseFloat(RegExp.$1) : 0;
else if (this.konq && window.RegExp)
this.vendver = (/khtml\/([0-9\.]+)/.test(this.agent_lc)) ? parseFloat(RegExp.$1) : 0;
// get real language out of safari's user agent
if (this.safari && (/;\s+([a-z]{2})-[a-z]{2}\)/.test(this.agent_lc)))
this.lang = RegExp.$1;
this.mobile = this.agent_lc.match(/iphone|ipad|ipod|android|blackberry|iemobile|opera mini|opera mobi/);
this.dhtml = ((this.ie4 && this.win) || this.ie5 || this.ie6 || this.ns4 || this.mz);
this.vml = (this.win && this.ie && this.dom && !this.opera);
this.pngalpha = (this.mz || (this.opera && this.vendver >= 6) || (this.ie && this.mac && this.vendver >= 5) ||
(this.ie && this.win && this.vendver >= 5.5) || this.safari);
this.opacity = (this.mz || (this.ie && this.vendver >= 5.5 && !this.opera) || (this.safari && this.vendver >= 100));
this.cookies = n.cookieEnabled;
// test for XMLHTTP support
this.xmlhttp_test = function()
{
var activeX_test = new Function("try{var o=new ActiveXObject('Microsoft.XMLHTTP');return true;}catch(err){return false;}");
this.xmlhttp = (window.XMLHttpRequest || (window.ActiveXObject && activeX_test()));
return this.xmlhttp;
};
// set class names to html tag according to the current user agent detection
// this allows browser-specific css selectors like "html.chrome .someclass"
this.set_html_class = function()
{
var classname = ' js';
if (this.ie)
classname += ' ie ie'+parseInt(this.vendver);
else if (this.opera)
classname += ' opera';
else if (this.konq)
classname += ' konqueror';
else if (this.safari)
classname += ' chrome';
else if (this.chrome)
classname += ' chrome';
else if (this.mz)
classname += ' mozilla';
if (this.iphone)
classname += ' iphone';
else if (this.ipad)
classname += ' ipad';
else if (this.safari || this.chrome)
classname += ' webkit';
if (this.mobile)
classname += ' mobile';
if (document.documentElement)
document.documentElement.className += classname;
};
};
// static functions for DOM event handling
var rcube_event = {
/**
* returns the event target element
*/
get_target: function(e)
{
e = e || window.event;
return e && e.target ? e.target : e.srcElement;
},
/**
* returns the event key code
*/
get_keycode: function(e)
{
e = e || window.event;
return e && e.keyCode ? e.keyCode : (e && e.which ? e.which : 0);
},
/**
* returns the event key code
*/
get_button: function(e)
{
e = e || window.event;
return e && e.button !== undefined ? e.button : (e && e.which ? e.which : 0);
},
/**
* returns modifier key (constants defined at top of file)
*/
get_modifier: function(e)
{
var opcode = 0;
e = e || window.event;
if (bw.mac && e)
opcode += (e.metaKey && CONTROL_KEY) + (e.shiftKey && SHIFT_KEY);
else if (e)
opcode += (e.ctrlKey && CONTROL_KEY) + (e.shiftKey && SHIFT_KEY);
return opcode;
},
/**
* Return absolute mouse position of an event
*/
get_mouse_pos: function(e)
{
if (!e) e = window.event;
var mX = (e.pageX) ? e.pageX : e.clientX,
mY = (e.pageY) ? e.pageY : e.clientY;
if (document.body && document.all) {
mX += document.body.scrollLeft;
mY += document.body.scrollTop;
}
if (e._offset) {
mX += e._offset.left;
mY += e._offset.top;
}
return { x:mX, y:mY };
},
/**
* Add an object method as event listener to a certain element
*/
add_listener: function(p)
{
if (!p.object || !p.method) // not enough arguments
return;
if (!p.element)
p.element = document;
if (!p.object._rc_events)
p.object._rc_events = [];
var key = p.event + '*' + p.method;
if (!p.object._rc_events[key])
p.object._rc_events[key] = function(e){ return p.object[p.method](e); };
if (p.element.addEventListener)
p.element.addEventListener(p.event, p.object._rc_events[key], false);
else if (p.element.attachEvent) {
// IE allows multiple events with the same function to be applied to the same object
// forcibly detach the event, then attach
p.element.detachEvent('on'+p.event, p.object._rc_events[key]);
p.element.attachEvent('on'+p.event, p.object._rc_events[key]);
}
else
p.element['on'+p.event] = p.object._rc_events[key];
},
/**
* Remove event listener
*/
remove_listener: function(p)
{
if (!p.element)
p.element = document;
var key = p.event + '*' + p.method;
if (p.object && p.object._rc_events && p.object._rc_events[key]) {
if (p.element.removeEventListener)
p.element.removeEventListener(p.event, p.object._rc_events[key], false);
else if (p.element.detachEvent)
p.element.detachEvent('on'+p.event, p.object._rc_events[key]);
else
p.element['on'+p.event] = null;
}
},
/**
- * Prevent event propagation and bubbeling
+ * Prevent event propagation and bubbling
*/
cancel: function(evt)
{
var e = evt ? evt : window.event;
if (e.preventDefault)
e.preventDefault();
if (e.stopPropagation)
e.stopPropagation();
e.cancelBubble = true;
e.returnValue = false;
return false;
},
touchevent: function(e)
{
return { pageX:e.pageX, pageY:e.pageY, offsetX:e.pageX - e.target.offsetLeft, offsetY:e.pageY - e.target.offsetTop, target:e.target, istouch:true };
}
};
/**
* rcmail objects event interface
*/
function rcube_event_engine()
{
this._events = {};
};
rcube_event_engine.prototype = {
/**
* Setter for object event handlers
*
* @param {String} Event name
* @param {Function} Handler function
* @return Listener ID (used to remove this handler later on)
*/
addEventListener: function(evt, func, obj)
{
if (!this._events)
this._events = {};
if (!this._events[evt])
this._events[evt] = [];
this._events[evt].push({func:func, obj:obj ? obj : window});
},
/**
* Removes a specific event listener
*
* @param {String} Event name
* @param {Int} Listener ID to remove
*/
removeEventListener: function(evt, func, obj)
{
if (obj === undefined)
obj = window;
for (var h,i=0; this._events && this._events[evt] && i < this._events[evt].length; i++)
if ((h = this._events[evt][i]) && h.func == func && h.obj == obj)
this._events[evt][i] = null;
},
/**
* This will execute all registered event handlers
*
* @param {String} Event to trigger
* @param {Object} Event object/arguments
*/
triggerEvent: function(evt, e)
{
var ret, h;
if (e === undefined)
e = this;
else if (typeof e === 'object')
e.event = evt;
if (this._events && this._events[evt] && !this._event_exec) {
this._event_exec = true;
for (var i=0; i < this._events[evt].length; i++) {
if ((h = this._events[evt][i])) {
if (typeof h.func === 'function')
ret = h.func.call ? h.func.call(h.obj, e) : h.func(e);
else if (typeof h.obj[h.func] === 'function')
ret = h.obj[h.func](e);
// cancel event execution
if (ret !== undefined && !ret)
break;
}
}
if (ret && ret.event) {
try {
delete ret.event;
} catch (err) {
// IE6-7 doesn't support deleting HTMLFormElement attributes (#1488017)
$(ret).removeAttr('event');
}
}
}
this._event_exec = false;
if (e.event) {
try {
delete e.event;
} catch (err) {
// IE6-7 doesn't support deleting HTMLFormElement attributes (#1488017)
$(e).removeAttr('event');
}
}
return ret;
}
}; // end rcube_event_engine.prototype
-
-/**
- * Roundcube generic layer (floating box) class
- *
- * @constructor
- */
-function rcube_layer(id, attributes)
-{
- this.name = id;
-
- // create a new layer in the current document
- this.create = function(arg)
- {
- var l = (arg.x) ? arg.x : 0,
- t = (arg.y) ? arg.y : 0,
- w = arg.width,
- h = arg.height,
- z = arg.zindex,
- vis = arg.vis,
- parent = arg.parent,
- obj = document.createElement('DIV');
-
- obj.id = this.name;
- obj.style.position = 'absolute';
- obj.style.visibility = (vis) ? (vis==2) ? 'inherit' : 'visible' : 'hidden';
- obj.style.left = l+'px';
- obj.style.top = t+'px';
- if (w)
- obj.style.width = w.toString().match(/\%$/) ? w : w+'px';
- if (h)
- obj.style.height = h.toString().match(/\%$/) ? h : h+'px';
- if (z)
- obj.style.zIndex = z;
-
- if (parent)
- parent.appendChild(obj);
- else
- document.body.appendChild(obj);
-
- this.elm = obj;
- };
-
- // create new layer
- if (attributes != null) {
- this.create(attributes);
- this.name = this.elm.id;
- }
- else // just refer to the object
- this.elm = document.getElementById(id);
-
- if (!this.elm)
- return false;
-
-
- // ********* layer object properties *********
-
- this.css = this.elm.style;
- this.event = this.elm;
- this.width = this.elm.offsetWidth;
- this.height = this.elm.offsetHeight;
- this.x = parseInt(this.elm.offsetLeft);
- this.y = parseInt(this.elm.offsetTop);
- this.visible = (this.css.visibility=='visible' || this.css.visibility=='show' || this.css.visibility=='inherit') ? true : false;
-
-
- // ********* layer object methods *********
-
- // move the layer to a specific position
- this.move = function(x, y)
- {
- this.x = x;
- this.y = y;
- this.css.left = Math.round(this.x)+'px';
- this.css.top = Math.round(this.y)+'px';
- };
-
- // change the layers width and height
- this.resize = function(w,h)
- {
- this.css.width = w+'px';
- this.css.height = h+'px';
- this.width = w;
- this.height = h;
- };
-
- // show or hide the layer
- this.show = function(a)
- {
- if(a == 1) {
- this.css.visibility = 'visible';
- this.visible = true;
- }
- else if(a == 2) {
- this.css.visibility = 'inherit';
- this.visible = true;
- }
- else {
- this.css.visibility = 'hidden';
- this.visible = false;
- }
- };
-
- // write new content into a Layer
- this.write = function(cont)
- {
- this.elm.innerHTML = cont;
- };
-
-};
-
-
// check if input is a valid email address
// By Cal Henderson <cal@iamcal.com>
// http://code.iamcal.com/php/rfc822/
function rcube_check_email(input, inline)
{
if (input && window.RegExp) {
var qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]',
dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]',
atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+',
quoted_pair = '\\x5c[\\x00-\\x7f]',
quoted_string = '\\x22('+qtext+'|'+quoted_pair+')*\\x22',
ipv4 = '\\[(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}\\]',
ipv6 = '\\[IPv6:[0-9a-f:.]+\\]',
ip_addr = '(' + ipv4 + ')|(' + ipv6 + ')',
// Use simplified domain matching, because we need to allow Unicode characters here
// So, e-mail address should be validated also on server side after idn_to_ascii() use
//domain_literal = '\\x5b('+dtext+'|'+quoted_pair+')*\\x5d',
//sub_domain = '('+atom+'|'+domain_literal+')',
// allow punycode/unicode top-level domain
domain = '(('+ip_addr+')|(([^@\\x2e]+\\x2e)+([^\\x00-\\x40\\x5b-\\x60\\x7b-\\x7f]{2,}|xn--[a-z0-9]{2,})))',
// ICANN e-mail test (http://idn.icann.org/E-mail_test)
icann_domains = [
'\\u0645\\u062b\\u0627\\u0644\\x2e\\u0625\\u062e\\u062a\\u0628\\u0627\\u0631',
'\\u4f8b\\u5b50\\x2e\\u6d4b\\u8bd5',
'\\u4f8b\\u5b50\\x2e\\u6e2c\\u8a66',
'\\u03c0\\u03b1\\u03c1\\u03ac\\u03b4\\u03b5\\u03b9\\u03b3\\u03bc\\u03b1\\x2e\\u03b4\\u03bf\\u03ba\\u03b9\\u03bc\\u03ae',
'\\u0909\\u0926\\u093e\\u0939\\u0930\\u0923\\x2e\\u092a\\u0930\\u0940\\u0915\\u094d\\u0937\\u093e',
'\\u4f8b\\u3048\\x2e\\u30c6\\u30b9\\u30c8',
'\\uc2e4\\ub840\\x2e\\ud14c\\uc2a4\\ud2b8',
'\\u0645\\u062b\\u0627\\u0644\\x2e\\u0622\\u0632\\u0645\\u0627\\u06cc\\u0634\u06cc',
'\\u043f\\u0440\\u0438\\u043c\\u0435\\u0440\\x2e\\u0438\\u0441\\u043f\\u044b\\u0442\\u0430\\u043d\\u0438\\u0435',
'\\u0b89\\u0ba4\\u0bbe\\u0bb0\\u0ba3\\u0bae\\u0bcd\\x2e\\u0baa\\u0bb0\\u0bbf\\u0b9f\\u0bcd\\u0b9a\\u0bc8',
'\\u05d1\\u05f2\\u05b7\\u05e9\\u05e4\\u05bc\\u05d9\\u05dc\\x2e\\u05d8\\u05e2\\u05e1\\u05d8'
],
icann_addr = 'mailtest\\x40('+icann_domains.join('|')+')',
word = '('+atom+'|'+quoted_string+')',
delim = '[,;\s\n]',
local_part = word+'(\\x2e'+word+')*',
addr_spec = '(('+local_part+'\\x40'+domain+')|('+icann_addr+'))',
reg1 = inline ? new RegExp('(^|<|'+delim+')'+addr_spec+'($|>|'+delim+')', 'i') : new RegExp('^'+addr_spec+'$', 'i');
return reg1.test(input) ? true : false;
}
return false;
};
// recursively copy an object
function rcube_clone_object(obj)
{
var out = {};
for (var key in obj) {
if (obj[key] && typeof obj[key] === 'object')
out[key] = clone_object(obj[key]);
else
out[key] = obj[key];
}
return out;
};
// make a string URL safe (and compatible with PHP's rawurlencode())
function urlencode(str)
{
if (window.encodeURIComponent)
return encodeURIComponent(str).replace('*', '%2A');
return escape(str)
.replace('+', '%2B')
.replace('*', '%2A')
.replace('/', '%2F')
.replace('@', '%40');
};
// get any type of html objects by id/name
function rcube_find_object(id, d)
{
var n, f, obj, e;
if(!d) d = document;
if(d.getElementsByName && (e = d.getElementsByName(id)))
obj = e[0];
if(!obj && d.getElementById)
obj = d.getElementById(id);
if(!obj && d.all)
obj = d.all[id];
if(!obj && d.images.length)
obj = d.images[id];
if (!obj && d.forms.length) {
for (f=0; f<d.forms.length; f++) {
if(d.forms[f].name == id)
obj = d.forms[f];
else if(d.forms[f].elements[id])
obj = d.forms[f].elements[id];
}
}
if (!obj && d.layers) {
if (d.layers[id]) obj = d.layers[id];
for (n=0; !obj && n<d.layers.length; n++)
obj = rcube_find_object(id, d.layers[n].document);
}
return obj;
};
// determine whether the mouse is over the given object or not
function rcube_mouse_is_over(ev, obj)
{
var mouse = rcube_event.get_mouse_pos(ev),
pos = $(obj).offset();
return ((mouse.x >= pos.left) && (mouse.x < (pos.left + obj.offsetWidth)) &&
(mouse.y >= pos.top) && (mouse.y < (pos.top + obj.offsetHeight)));
};
// cookie functions by GoogieSpell
function setCookie(name, value, expires, path, domain, secure)
{
var curCookie = name + "=" + escape(value) +
(expires ? "; expires=" + expires.toGMTString() : "") +
(path ? "; path=" + path : "") +
(domain ? "; domain=" + domain : "") +
(secure ? "; secure" : "");
document.cookie = curCookie;
};
function getCookie(name)
{
var dc = document.cookie,
prefix = name + "=",
begin = dc.indexOf("; " + prefix);
if (begin == -1) {
begin = dc.indexOf(prefix);
if (begin != 0)
return null;
}
else {
begin += 2;
}
var end = dc.indexOf(";", begin);
if (end == -1)
end = dc.length;
return unescape(dc.substring(begin + prefix.length, end));
};
// deprecated aliases, to be removed, use rcmail.set_cookie/rcmail.get_cookie
roundcube_browser.prototype.set_cookie = setCookie;
roundcube_browser.prototype.get_cookie = getCookie;
// tiny replacement for Firebox functionality
function rcube_console()
{
this.log = function(msg)
{
var box = rcube_find_object('dbgconsole');
if (box) {
if (msg.charAt(msg.length-1)=='\n')
msg += '--------------------------------------\n';
else
msg += '\n--------------------------------------\n';
// Konqueror doesn't allow to just change the value of hidden element
if (bw.konq) {
box.innerText += msg;
box.value = box.innerText;
} else
box.value += msg;
}
};
this.reset = function()
{
var box = rcube_find_object('dbgconsole');
if (box)
box.innerText = box.value = '';
};
};
var bw = new roundcube_browser();
bw.set_html_class();
// Add escape() method to RegExp object
// http://dev.rubyonrails.org/changeset/7271
RegExp.escape = function(str)
{
return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
};
// Extend Date prototype to detect Standard timezone without DST
// from http://www.michaelapproved.com/articles/timezone-detect-and-ignore-daylight-saving-time-dst/
Date.prototype.getStdTimezoneOffset = function()
{
var m = 12,
d = new Date(null, m, 1),
tzo = d.getTimezoneOffset();
while (--m) {
d.setUTCMonth(m);
if (tzo != d.getTimezoneOffset()) {
return Math.max(tzo, d.getTimezoneOffset());
}
}
return tzo;
}
// Make getElementById() case-sensitive on IE
if (bw.ie) {
document._getElementById = document.getElementById;
document.getElementById = function(id) {
var i = 0, obj = document._getElementById(id);
if (obj && obj.id != id)
while ((obj = document.all[i]) && obj.id != id)
i++;
return obj;
}
}
// jQuery plugin to emulate HTML5 placeholder attributes on input elements
jQuery.fn.placeholder = function(text) {
return this.each(function() {
var active = false, elem = $(this);
this.title = text;
// Try HTML5 placeholder attribute first
if ('placeholder' in this) {
elem.attr('placeholder', text);
}
// Fallback to Javascript emulation of placeholder
else {
this._placeholder = text;
elem.blur(function(e) {
if ($.trim(elem.val()) == "")
elem.val(text);
elem.triggerHandler('change');
})
.focus(function(e) {
if ($.trim(elem.val()) == text)
elem.val("");
elem.triggerHandler('change');
})
.change(function(e) {
var active = elem.val() == text;
elem[(active ? 'addClass' : 'removeClass')]('placeholder').attr('spellcheck', active);
});
// Do not blur currently focused element (catch exception: #1489008)
try { active = this == document.activeElement; } catch(e) {}
if (!active)
elem.blur();
}
});
};
// This code was written by Tyler Akins and has been placed in the
// public domain. It would be nice if you left this header intact.
// Base64 code from Tyler Akins -- http://rumkin.com
var Base64 = (function () {
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
var obj = {
/**
* Encodes a string in base64
* @param {String} input The string to encode in base64.
*/
encode: function (input) {
if (typeof(window.btoa) === 'function')
return btoa(input);
var chr1, chr2, chr3, enc1, enc2, enc3, enc4, i = 0, output = '', len = input.length;
do {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2))
enc3 = enc4 = 64;
else if (isNaN(chr3))
enc4 = 64;
output = output
+ keyStr.charAt(enc1) + keyStr.charAt(enc2)
+ keyStr.charAt(enc3) + keyStr.charAt(enc4);
} while (i < len);
return output;
},
/**
* Decodes a base64 string.
* @param {String} input The string to decode.
*/
decode: function (input) {
if (typeof(window.atob) === 'function')
return atob(input);
var chr1, chr2, chr3, enc1, enc2, enc3, enc4, len, i = 0, output = '';
// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
len = input.length;
do {
enc1 = keyStr.indexOf(input.charAt(i++));
enc2 = keyStr.indexOf(input.charAt(i++));
enc3 = keyStr.indexOf(input.charAt(i++));
enc4 = keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64)
output = output + String.fromCharCode(chr2);
if (enc4 != 64)
output = output + String.fromCharCode(chr3);
} while (i < len);
return output;
}
};
return obj;
})();
diff --git a/skins/classic/functions.js b/skins/classic/functions.js
index 1dcaa1586..5dd332ab7 100644
--- a/skins/classic/functions.js
+++ b/skins/classic/functions.js
@@ -1,884 +1,992 @@
/**
* Roundcube functions for default skin interface
*/
/**
* Settings
*/
function rcube_init_settings_tabs()
{
var el, cl, container = $('#tabsbar'),
last_tab = $('span:last', container),
tab = '#settingstabdefault',
action = window.rcmail && rcmail.env.action ? rcmail.env.action : null;
// move About tab to the end
if (last_tab && last_tab.attr('id') != 'settingstababout' && (el = $('#settingstababout'))) {
cl = el.clone(true);
el.remove();
last_tab.after(cl);
}
// get selected tab
if (action)
tab = '#settingstab' + (action == 'preferences' ? 'default' : (action.indexOf('identity')>0 ? 'identities' : action.replace(/\./g, '')));
$(tab).addClass('tablink-selected');
$('a', tab).removeAttr('onclick').click(function() { return false; });
}
// Fieldsets-to-tabs converter
// Warning: don't place "caller" <script> inside page element (id)
function rcube_init_tabs(id, current)
{
var content = $('#'+id),
fs = content.children('fieldset');
if (!fs.length)
return;
current = current ? current : 0;
// first hide not selected tabs
fs.each(function(idx) { if (idx != current) $(this).hide(); });
// create tabs container
var tabs = $('<div>').addClass('tabsbar').appendTo(content);
// convert fildsets into tabs
fs.each(function(idx) {
var tab, a, elm = $(this), legend = elm.children('legend');
// create a tab
a = $('<a>').text(legend.text()).attr('href', '#');
tab = $('<span>').attr({'id': 'tab'+idx, 'class': 'tablink'})
.click(function() { rcube_show_tab(id, idx); return false })
// remove legend
legend.remove();
// style fieldset
elm.addClass('tabbed');
// style selected tab
if (idx == current)
tab.addClass('tablink-selected');
// add the tab to container
tab.append(a).appendTo(tabs);
});
}
function rcube_show_tab(id, index)
{
var fs = $('#'+id).children('fieldset');
fs.each(function(idx) {
// Show/hide fieldset (tab content)
$(this)[index==idx ? 'show' : 'hide']();
// Select/unselect tab
$('#tab'+idx).toggleClass('tablink-selected', idx==index);
});
}
/**
* Mail UI
*/
function rcube_mail_ui()
{
this.popups = {
markmenu: {id:'markmessagemenu'},
replyallmenu: {id:'replyallmenu'},
forwardmenu: {id:'forwardmenu', editable:1},
searchmenu: {id:'searchmenu', editable:1},
messagemenu: {id:'messagemenu'},
attachmentmenu: {id:'attachmentmenu'},
listmenu: {id:'listmenu', editable:1},
dragmessagemenu:{id:'dragmessagemenu', sticky:1},
groupmenu: {id:'groupoptionsmenu', above:1},
mailboxmenu: {id:'mailboxoptionsmenu', above:1},
composemenu: {id:'composeoptionsmenu', editable:1, overlap:1},
spellmenu: {id:'spellmenu'},
// toggle: #1486823, #1486930
uploadmenu: {id:'attachment-form', editable:1, above:1, toggle:!bw.ie&&!bw.linux },
uploadform: {id:'upload-form', editable:1, toggle:!bw.ie&&!bw.linux }
};
var obj;
for (var k in this.popups) {
obj = $('#'+this.popups[k].id)
if (obj.length)
this.popups[k].obj = obj;
else {
delete this.popups[k];
}
}
}
rcube_mail_ui.prototype = {
show_popup: function(popup, show, config)
{
var obj;
// auto-register menu object
if (!this.popups[popup] && (obj = $('#'+popup)) && obj.length)
this.popups[popup] = $.extend(config, {id: popup, obj: obj});
if (typeof this[popup] == 'function')
return this[popup](show);
else
return this.show_popupmenu(popup, show);
},
show_popupmenu: function(popup, show)
{
var obj = this.popups[popup].obj,
above = this.popups[popup].above,
ref = $(this.popups[popup].link ? this.popups[popup].link : rcube_find_object(popup+'link'));
if (typeof show == 'undefined')
show = obj.is(':visible') ? false : true;
else if (this.popups[popup].toggle && show && this.popups[popup].obj.is(':visible') )
show = false;
if (show && ref.length) {
var parent = ref.parent(),
win = $(window),
pos = parent.hasClass('dropbutton') ? parent.offset() : ref.offset();
if (!above && pos.top + ref.height() + obj.height() > win.height())
above = true;
if (pos.left + obj.width() > win.width())
pos.left = win.width() - obj.width() - 30;
obj.css({ left:pos.left, top:(pos.top + (above ? -obj.height() : ref.height())) });
}
obj[show?'show':'hide']();
if (bw.ie6 && this.popups[popup].overlap) {
$('select').css('visibility', show?'hidden':'inherit');
$('select', obj).css('visibility', 'inherit');
}
},
dragmessagemenu: function(show)
{
this.popups.dragmessagemenu.obj[show?'show':'hide']();
},
forwardmenu: function(show)
{
$("input[name='forwardtype'][value="+(rcmail.env.forward_attachment ? 1 : 0)+"]", this.popups.forwardmenu.obj)
.prop('checked', true);
this.show_popupmenu('forwardmenu', show);
},
uploadmenu: function(show)
{
if (typeof show == 'object') // called as event handler
show = false;
// clear upload form
if (!show) {
try { $('#attachment-form form')[0].reset(); }
catch(e){} // ignore errors
}
this.show_popupmenu('uploadmenu', show);
if (!document.all && this.popups.uploadmenu.obj.is(':visible'))
$('#attachment-form input[type=file]').click();
},
searchmenu: function(show)
{
var obj = this.popups.searchmenu.obj,
ref = rcube_find_object('searchmenulink');
if (typeof show == 'undefined')
show = obj.is(':visible') ? false : true;
if (show && ref) {
var pos = $(ref).offset();
obj.css({left:pos.left, top:(pos.top + ref.offsetHeight + 2)});
if (rcmail.env.search_mods) {
var n, all,
list = $('input:checkbox[name="s_mods[]"]', obj),
mbox = rcmail.env.mailbox,
mods = rcmail.env.search_mods;
if (rcmail.env.task == 'mail') {
mods = mods[mbox] ? mods[mbox] : mods['*'];
all = 'text';
}
else {
all = '*';
}
if (mods[all])
list.map(function() {
this.checked = true;
this.disabled = this.value != all;
});
else {
list.prop('disabled', false).prop('checked', false);
for (n in mods)
$('#s_mod_' + n).prop('checked', true);
}
}
}
obj[show?'show':'hide']();
},
set_searchmod: function(elem)
{
var all, m, task = rcmail.env.task,
mods = rcmail.env.search_mods,
mbox = rcmail.env.mailbox;
if (!mods)
mods = {};
if (task == 'mail') {
if (!mods[mbox])
mods[mbox] = rcube_clone_object(mods['*']);
m = mods[mbox];
all = 'text';
}
else { //addressbook
m = mods;
all = '*';
}
if (!elem.checked)
delete(m[elem.value]);
else
m[elem.value] = 1;
// mark all fields
if (elem.value != all)
return;
$('input:checkbox[name="s_mods[]"]').map(function() {
if (this == elem)
return;
this.checked = true;
if (elem.checked) {
this.disabled = true;
delete m[this.value];
}
else {
this.disabled = false;
m[this.value] = 1;
}
});
},
listmenu: function(show)
{
var obj = this.popups.listmenu.obj,
ref = rcube_find_object('listmenulink');
if (typeof show == 'undefined')
show = obj.is(':visible') ? false : true;
if (show && ref) {
var pos = $(ref).offset(),
menuwidth = obj.width(),
pagewidth = $(document).width();
if (pagewidth - pos.left < menuwidth && pos.left > menuwidth)
pos.left = pos.left - menuwidth;
obj.css({ left:pos.left, top:(pos.top + ref.offsetHeight + 2)});
// set form values
$('input[name="sort_col"][value="'+rcmail.env.sort_col+'"]').prop('checked', true);
$('input[name="sort_ord"][value="DESC"]').prop('checked', rcmail.env.sort_order == 'DESC');
$('input[name="sort_ord"][value="ASC"]').prop('checked', rcmail.env.sort_order != 'DESC');
$('input[name="view"][value="thread"]').prop('checked', rcmail.env.threading ? true : false);
$('input[name="view"][value="list"]').prop('checked', rcmail.env.threading ? false : true);
// set checkboxes
$('input[name="list_col[]"]').each(function() {
$(this).prop('checked', jQuery.inArray(this.value, rcmail.env.coltypes) != -1);
});
}
obj[show?'show':'hide']();
if (show) {
var maxheight=0;
$('#listmenu fieldset').each(function() {
var height = $(this).height();
if (height > maxheight) {
maxheight = height;
}
});
$('#listmenu fieldset').css("min-height", maxheight+"px")
// IE6 complains if you set this attribute using either method:
//$('#listmenu fieldset').css({'height':'auto !important'});
//$('#listmenu fieldset').css("height","auto !important");
.height(maxheight);
};
},
open_listmenu: function()
{
this.listmenu();
},
save_listmenu: function()
{
this.listmenu();
var sort = $('input[name="sort_col"]:checked').val(),
ord = $('input[name="sort_ord"]:checked').val(),
thread = $('input[name="view"]:checked').val(),
cols = $('input[name="list_col[]"]:checked')
.map(function(){ return this.value; }).get();
rcmail.set_list_options(cols, sort, ord, thread == 'thread' ? 1 : 0);
},
spellmenu: function(show)
{
var link, li,
lang = rcmail.spellcheck_lang(),
menu = this.popups.spellmenu.obj,
ul = $('ul', menu);
if (!ul.length) {
ul = $('<ul>');
for (i in rcmail.env.spell_langs) {
li = $('<li>');
link = $('<a href="#"></a>').text(rcmail.env.spell_langs[i])
.addClass('active').data('lang', i)
.click(function() {
rcmail.spellcheck_lang_set($(this).data('lang'));
});
link.appendTo(li);
li.appendTo(ul);
}
ul.appendTo(menu);
}
// select current language
$('li', ul).each(function() {
var el = $('a', this);
if (el.data('lang') == lang)
el.addClass('selected');
else if (el.hasClass('selected'))
el.removeClass('selected');
});
this.show_popupmenu('spellmenu', show);
},
show_attachmentmenu: function(elem)
{
var id = elem.parentNode.id.replace(/^attach/, '');
$('#attachmenuopen').unbind('click').attr('onclick', '').click(function(e) {
return rcmail.command('open-attachment', id, this);
});
$('#attachmenudownload').unbind('click').attr('onclick', '').click(function() {
rcmail.command('download-attachment', id, this);
});
this.popups.attachmentmenu.link = elem;
rcmail.command('menu-open', {menu: 'attachmentmenu', id: id});
},
menu_open: function(p)
{
if (p && p.props && p.props.menu == 'attachmentmenu')
this.show_popup('attachmentmenu');
else
this.open_listmenu();
},
menu_save: function(prop)
{
this.save_listmenu();
},
body_mouseup: function(evt, p)
{
var i, target = rcube_event.get_target(evt);
for (i in this.popups) {
if (this.popups[i].obj.is(':visible') && target != rcube_find_object(i+'link')
&& !this.popups[i].toggle
&& (!this.popups[i].editable || !this.target_overlaps(target, this.popups[i].id))
&& (!this.popups[i].sticky || !rcube_mouse_is_over(evt, rcube_find_object(this.popups[i].id)))
) {
window.setTimeout('rcmail_ui.show_popup("'+i+'",false);', 50);
}
}
},
target_overlaps: function (target, elementid)
{
var element = rcube_find_object(elementid);
while (target.parentNode) {
if (target.parentNode == element)
return true;
target = target.parentNode;
}
return false;
},
body_keydown: function(evt, p)
{
if (rcube_event.get_keycode(evt) == 27) {
for (var k in this.popups) {
if (this.popups[k].obj.is(':visible'))
this.show_popup(k, false);
}
}
},
switch_preview_pane: function(elem)
{
var uid, prev_frm = $('#mailpreviewframe');
if (elem.checked) {
rcmail.env.contentframe = 'messagecontframe';
if (mailviewsplit.layer) {
mailviewsplit.resize();
mailviewsplit.layer.elm.style.display = '';
}
else
mailviewsplit.init();
if (bw.opera) {
$('#messagelistcontainer').css({height: ''});
}
prev_frm.show();
if (uid = rcmail.message_list.get_single_selection())
rcmail.show_message(uid, false, true);
}
else {
prev_frm.hide();
if (bw.ie6 || bw.ie7) {
var fr = document.getElementById('mailcontframe');
fr.style.bottom = 0;
fr.style.height = parseInt(fr.parentNode.offsetHeight)+'px';
}
else {
$('#mailcontframe').css({height: 'auto', bottom: 0});
if (bw.opera)
$('#messagelistcontainer').css({height: 'auto'});
}
if (mailviewsplit.layer)
mailviewsplit.layer.elm.style.display = 'none';
rcmail.env.contentframe = null;
rcmail.show_contentframe(false);
}
rcmail.command('save-pref', {name: 'preview_pane', value: (elem.checked?1:0)});
},
/* Message composing */
init_compose_form: function()
{
var f, v, field, fields = ['cc', 'bcc', 'replyto', 'followupto'],
div = document.getElementById('compose-div'),
headers_div = document.getElementById('compose-headers-div');
// Show input elements with non-empty value
for (f=0; f<fields.length; f++) {
v = fields[f]; field = $('#_'+v);
if (field.length) {
field.on('change', {v:v}, function(e) { if (this.value) rcmail_ui.show_header_form(e.data.v); });
if (field.val() != '')
rcmail_ui.show_header_form(v);
}
}
// prevent from form data loss when pressing ESC key in IE
if (bw.ie) {
var form = rcube_find_object('form');
form.onkeydown = function (e) {
if (rcube_event.get_keycode(e) == 27)
rcube_event.cancel(e);
};
}
$(window).resize(function() {
rcmail_ui.resize_compose_body();
});
$('#compose-container').resize(function() {
rcmail_ui.resize_compose_body();
});
div.style.top = (parseInt(headers_div.offsetHeight, 10) + 3) + 'px';
$(window).resize();
// fixes contacts-table position when there's more than one addressbook
$('#contacts-table').css('top', $('#directorylist').height() + 24 + 'px');
// contacts search submit
$('#quicksearchbox').keydown(function(e) {
if (rcube_event.get_keycode(e) == 13)
rcmail.command('search');
});
},
resize_compose_body: function()
{
var div = $('#compose-div .boxlistcontent'),
w = div.width() - 2, h = div.height(),
x = bw.ie || bw.opera ? 4 : 0;
$('#compose-body_tbl').width((w+3)+'px').height('');
$('#compose-body_ifr').width((w+3)+'px').height((h-54)+'px');
$('#compose-body').width((w-x)+'px').height(h+'px');
$('#googie_edit_layer').height(h+'px');
},
resize_compose_body_ev: function()
{
window.setTimeout(function(){rcmail_ui.resize_compose_body();}, 100);
},
show_header_form: function(id)
{
var row, s,
link = document.getElementById(id + '-link');
if ((s = this.next_sibling(link)))
s.style.display = 'none';
else if ((s = this.prev_sibling(link)))
s.style.display = 'none';
link.style.display = 'none';
if ((row = document.getElementById('compose-' + id))) {
var div = document.getElementById('compose-div'),
headers_div = document.getElementById('compose-headers-div');
$(row).show();
div.style.top = (parseInt(headers_div.offsetHeight, 10) + 3) + 'px';
this.resize_compose_body();
}
return false;
},
hide_header_form: function(id)
{
var row, ns,
link = document.getElementById(id + '-link'),
parent = link.parentNode,
links = parent.getElementsByTagName('a');
link.style.display = '';
for (var i=0; i<links.length; i++)
if (links[i].style.display != 'none')
for (var j=i+1; j<links.length; j++)
if (links[j].style.display != 'none')
if ((ns = this.next_sibling(links[i]))) {
ns.style.display = '';
break;
}
document.getElementById('_' + id).value = '';
if ((row = document.getElementById('compose-' + id))) {
var div = document.getElementById('compose-div'),
headers_div = document.getElementById('compose-headers-div');
row.style.display = 'none';
div.style.top = (parseInt(headers_div.offsetHeight, 10) + 1) + 'px';
this.resize_compose_body();
}
return false;
},
next_sibling: function(elm)
{
var ns = elm.nextSibling;
while (ns && ns.nodeType == 3)
ns = ns.nextSibling;
return ns;
},
prev_sibling: function(elm)
{
var ps = elm.previousSibling;
while (ps && ps.nodeType == 3)
ps = ps.previousSibling;
return ps;
},
enable_command: function(p)
{
if (p.command == 'reply-list') {
var label = rcmail.gettext(p.status ? 'replylist' : 'replyall');
$('a.button.replyAll').attr('title', label);
}
}
};
/**
- * Scroller
+ * Roundcube generic layer (floating box) class
+ *
+ * @constructor
*/
+function rcube_layer(id, attributes)
+{
+ this.name = id;
+
+ // create a new layer in the current document
+ this.create = function(arg)
+ {
+ var l = (arg.x) ? arg.x : 0,
+ t = (arg.y) ? arg.y : 0,
+ w = arg.width,
+ h = arg.height,
+ z = arg.zindex,
+ vis = arg.vis,
+ parent = arg.parent,
+ obj = document.createElement('DIV');
+
+ obj.id = this.name;
+ obj.style.position = 'absolute';
+ obj.style.visibility = (vis) ? (vis==2) ? 'inherit' : 'visible' : 'hidden';
+ obj.style.left = l+'px';
+ obj.style.top = t+'px';
+ if (w)
+ obj.style.width = w.toString().match(/\%$/) ? w : w+'px';
+ if (h)
+ obj.style.height = h.toString().match(/\%$/) ? h : h+'px';
+ if (z)
+ obj.style.zIndex = z;
+
+ if (parent)
+ parent.appendChild(obj);
+ else
+ document.body.appendChild(obj);
+
+ this.elm = obj;
+ };
+
+ // create new layer
+ if (attributes != null) {
+ this.create(attributes);
+ this.name = this.elm.id;
+ }
+ else // just refer to the object
+ this.elm = document.getElementById(id);
+
+ if (!this.elm)
+ return false;
+
+
+ // ********* layer object properties *********
+
+ this.css = this.elm.style;
+ this.event = this.elm;
+ this.width = this.elm.offsetWidth;
+ this.height = this.elm.offsetHeight;
+ this.x = parseInt(this.elm.offsetLeft);
+ this.y = parseInt(this.elm.offsetTop);
+ this.visible = (this.css.visibility=='visible' || this.css.visibility=='show' || this.css.visibility=='inherit') ? true : false;
+
+
+ // ********* layer object methods *********
+
+ // move the layer to a specific position
+ this.move = function(x, y)
+ {
+ this.x = x;
+ this.y = y;
+ this.css.left = Math.round(this.x)+'px';
+ this.css.top = Math.round(this.y)+'px';
+ };
+ // change the layers width and height
+ this.resize = function(w,h)
+ {
+ this.css.width = w+'px';
+ this.css.height = h+'px';
+ this.width = w;
+ this.height = h;
+ };
+
+ // show or hide the layer
+ this.show = function(a)
+ {
+ if(a == 1) {
+ this.css.visibility = 'visible';
+ this.visible = true;
+ }
+ else if(a == 2) {
+ this.css.visibility = 'inherit';
+ this.visible = true;
+ }
+ else {
+ this.css.visibility = 'hidden';
+ this.visible = false;
+ }
+ };
+
+ // write new content into a Layer
+ this.write = function(cont)
+ {
+ this.elm.innerHTML = cont;
+ };
+
+};
+
+/**
+ * Scroller
+ */
function rcmail_scroller(list, top, bottom)
{
var ref = this;
this.list = $(list);
this.top = $(top);
this.bottom = $(bottom);
this.step_size = 6;
this.step_time = 20;
this.delay = 500;
this.top
.mouseenter(function() { ref.ts = window.setTimeout(function() { ref.scroll('down'); }, ref.delay); })
.mouseout(function() { if (ref.ts) window.clearTimeout(ref.ts); });
this.bottom
.mouseenter(function() { ref.ts = window.setTimeout(function() { ref.scroll('up'); }, ref.delay); })
.mouseout(function() { if (ref.ts) window.clearTimeout(ref.ts); });
this.scroll = function(dir)
{
var ref = this, size = this.step_size;
if (!rcmail.drag_active)
return;
if (dir == 'down')
size *= -1;
this.list.get(0).scrollTop += size;
this.ts = window.setTimeout(function() { ref.scroll(dir); }, this.step_time);
};
};
// Events handling in iframes (eg. preview pane)
function iframe_events()
{
// this==iframe
try {
var doc = this.contentDocument ? this.contentDocument : this.contentWindow ? this.contentWindow.document : null;
rcube_event.add_listener({ element: doc, object:rcmail_ui, method:'body_mouseup', event:'mouseup' });
}
catch (e) {
// catch possible "Permission denied" error in IE
};
};
// Abbreviate mailbox names to fit width of the container
function rcube_render_mailboxlist()
{
var list = $('#mailboxlist > li a, #mailboxlist ul:visible > li a');
// it's too slow with really big number of folders, especially on IE
if (list.length > (bw.ie ? 25 : 100))
return;
list.each(function(){
var elem = $(this),
text = elem.data('text');
if (!text) {
text = elem.text().replace(/\s+\(.+$/, '');
elem.data('text', text);
}
if (text.length < 6)
return;
var abbrev = fit_string_to_size(text, elem, elem.width() - elem.children('span.unreadcount').width());
if (abbrev != text)
elem.attr('title', text);
elem.contents().filter(function(){ return (this.nodeType == 3); }).get(0).data = abbrev;
});
};
// inspired by https://gist.github.com/24261/7fdb113f1e26111bd78c0c6fe515f6c0bf418af5
function fit_string_to_size(str, elem, len)
{
var w, span, result = str, ellip = '...';
if (!rcmail.env.tmp_span) {
// it should be appended to elem to use the same css style
// but for performance reasons we'll append it to body (once)
span = $('<b>').css({visibility: 'hidden', padding: '0px'})
.appendTo($('body', document)).get(0);
rcmail.env.tmp_span = span;
}
else {
span = rcmail.env.tmp_span;
}
span.innerHTML = result;
// on first run, check if string fits into the length already.
w = span.offsetWidth;
if (w > len) {
var cut = Math.max(1, Math.floor(str.length * ((w - len) / w) / 2)),
mid = Math.floor(str.length / 2),
offLeft = mid,
offRight = mid;
while (true) {
offLeft = mid - cut;
offRight = mid + cut;
span.innerHTML = str.substring(0,offLeft) + ellip + str.substring(offRight);
// break loop if string fits size
if (offLeft < 3 || span.offsetWidth)
break;
cut++;
}
// build resulting string
result = str.substring(0,offLeft) + ellip + str.substring(offRight);
}
return result;
};
function update_quota(data)
{
percent_indicator(rcmail.gui_objects.quotadisplay, data);
};
// percent (quota) indicator
function percent_indicator(obj, data)
{
if (!data || !obj)
return false;
var limit_high = 80,
limit_mid = 55,
width = data.width ? data.width : rcmail.env.indicator_width ? rcmail.env.indicator_width : 100,
height = data.height ? data.height : rcmail.env.indicator_height ? rcmail.env.indicator_height : 14,
quota = data.percent ? Math.abs(parseInt(data.percent)) : 0,
quota_width = parseInt(quota / 100 * width),
pos = $(obj).position();
// workarounds for Opera and Webkit bugs
pos.top = Math.max(0, pos.top);
pos.left = Math.max(0, pos.left);
rcmail.env.indicator_width = width;
rcmail.env.indicator_height = height;
// overlimit
if (quota_width > width) {
quota_width = width;
quota = 100;
}
if (data.title)
data.title = rcmail.get_label('quota') + ': ' + data.title;
// main div
var main = $('<div>');
main.css({position: 'absolute', top: pos.top, left: pos.left,
width: width + 'px', height: height + 'px', zIndex: 100, lineHeight: height + 'px'})
.attr('title', data.title).addClass('quota_text').html(quota + '%');
// used bar
var bar1 = $('<div>');
bar1.css({position: 'absolute', top: pos.top + 1, left: pos.left + 1,
width: quota_width + 'px', height: height + 'px', zIndex: 99});
// background
var bar2 = $('<div>');
bar2.css({position: 'absolute', top: pos.top + 1, left: pos.left + 1,
width: width + 'px', height: height + 'px', zIndex: 98})
.addClass('quota_bg');
if (quota >= limit_high) {
main.addClass(' quota_text_high');
bar1.addClass('quota_high');
}
else if(quota >= limit_mid) {
main.addClass(' quota_text_mid');
bar1.addClass('quota_mid');
}
else {
main.addClass(' quota_text_low');
bar1.addClass('quota_low');
}
// replace quota image
$(obj).html('').append(bar1).append(bar2).append(main);
// update #quotaimg title
$('#quotaimg').attr('title', data.title);
};
// Optional parameters used by TinyMCE
var rcmail_editor_settings = {
skin : "default", // "default", "o2k7"
skin_variant : "" // "", "silver", "black"
};
var rcmail_ui;
function rcube_init_mail_ui()
{
rcmail_ui = new rcube_mail_ui();
rcube_event.add_listener({ object:rcmail_ui, method:'body_mouseup', event:'mouseup' });
rcube_event.add_listener({ object:rcmail_ui, method:'body_keydown', event:'keydown' });
if (rcmail.env.quota_content)
update_quota(rcmail.env.quota_content);
rcmail.addEventListener('setquota', update_quota);
$('iframe').load(iframe_events)
.contents().mouseup(function(e){rcmail_ui.body_mouseup(e)});
if (rcmail.env.task == 'mail') {
rcmail.addEventListener('enable-command', 'enable_command', rcmail_ui);
rcmail.addEventListener('menu-open', 'menu_open', rcmail_ui);
rcmail.addEventListener('menu-save', 'menu_save', rcmail_ui);
rcmail.addEventListener('aftersend-attachment', 'uploadmenu', rcmail_ui);
rcmail.addEventListener('aftertoggle-editor', 'resize_compose_body_ev', rcmail_ui);
rcmail.gui_object('message_dragmenu', 'dragmessagemenu');
if (rcmail.gui_objects.mailboxlist) {
rcmail.addEventListener('responseaftermark', rcube_render_mailboxlist);
rcmail.addEventListener('responseaftergetunread', rcube_render_mailboxlist);
rcmail.addEventListener('responseaftercheck-recent', rcube_render_mailboxlist);
rcmail.addEventListener('aftercollapse-folder', rcube_render_mailboxlist);
new rcmail_scroller('#mailboxlist-content', '#mailboxlist-title', '#mailboxlist-footer');
}
if (rcmail.env.action == 'compose')
rcmail_ui.init_compose_form();
else if (rcmail.env.action == 'show' || rcmail.env.action == 'preview')
// add menu link for each attachment
$('#attachment-list > li[id^="attach"]').each(function() {
$(this).append($('<a class="drop">').click(function() { rcmail_ui.show_attachmentmenu(this); }));
});
}
else if (rcmail.env.task == 'addressbook') {
rcmail.addEventListener('afterupload-photo', function(){ rcmail_ui.show_popup('uploadform', false); });
if (rcmail.gui_objects.folderlist)
new rcmail_scroller('#directorylist-content', '#directorylist-title', '#directorylist-footer');
}
else if (rcmail.env.task == 'settings') {
if (rcmail.gui_objects.subscriptionlist)
new rcmail_scroller('#folderlist-content', '#folderlist-title', '#folderlist-footer');
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Feb 3, 2:16 PM (17 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
427286
Default Alt Text
(51 KB)
Attached To
Mode
R3 roundcubemail
Attached
Detach File
Event Timeline
Log In to Comment