From 4910b0666edeeebb18ac9682cb898dba8f22962a Mon Sep 17 00:00:00 2001
From: Thomas Bruederli <thomas@roundcube.net>
Date: Thu, 15 Aug 2013 02:57:11 -0400
Subject: [PATCH] Distinguish mobile/tablet/touch devices

---
 program/js/common.js |  142 ++++++----------------------------------------
 1 files changed, 20 insertions(+), 122 deletions(-)

diff --git a/program/js/common.js b/program/js/common.js
index 2d8d9e1..afaf916 100644
--- a/program/js/common.js
+++ b/program/js/common.js
@@ -62,7 +62,7 @@
   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.iphone = (this.safari && (this.agent_lc.indexOf('iphone') > 0 || this.agent_lc.indexOf('ipod') > 0));
   this.ipad = (this.safari && this.agent_lc.indexOf('ipad') > 0);
   this.opera = window.opera ? true : false;
 
@@ -83,7 +83,9 @@
   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.tablet = /ipad|android|xoom|sch-i800|playbook|tablet|kindle/i.test(this.agent_lc);
+  this.mobile = /iphone|ipod|blackberry|iemobile|opera mini|opera mobi|mobile/i.test(this.agent_lc);
+  this.touch = this.mobile || this.tablet;
   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) ||
@@ -127,6 +129,8 @@
 
     if (this.mobile)
       classname += ' mobile';
+    if (this.tablet)
+      classname += ' tablet';
 
     if (document.documentElement)
       document.documentElement.className += classname;
@@ -251,7 +255,7 @@
 },
 
 /**
- * Prevent event propagation and bubbeling
+ * Prevent event propagation and bubbling
  */
 cancel: function(evt)
 {
@@ -298,8 +302,7 @@
   if (!this._events[evt])
     this._events[evt] = [];
 
-  var e = {func:func, obj:obj ? obj : window};
-  this._events[evt][this._events[evt].length] = e;
+  this._events[evt].push({func:func, obj:obj ? obj : window});
 },
 
 /**
@@ -372,117 +375,6 @@
 };  // 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/
@@ -494,7 +386,9 @@
       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',
-      ip_addr = '\\[*(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}\\]*',
+      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',
@@ -535,7 +429,7 @@
 
   for (var key in obj) {
     if (obj[key] && typeof obj[key] === 'object')
-      out[key] = clone_object(obj[key]);
+      out[key] = rcube_clone_object(obj[key]);
     else
       out[key] = obj[key];
   }
@@ -715,13 +609,15 @@
 // jQuery plugin to emulate HTML5 placeholder attributes on input elements
 jQuery.fn.placeholder = function(text) {
   return this.each(function() {
-    var elem = $(this);
+    var active = false, elem = $(this);
     this.title = text;
 
+    // Try HTML5 placeholder attribute first
     if ('placeholder' in this) {
-      elem.attr('placeholder', text);  // Try HTML5 placeholder attribute first
+      elem.attr('placeholder', text);
     }
-    else {  // Fallback to Javascript emulation of placeholder
+    // Fallback to Javascript emulation of placeholder
+    else {
       this._placeholder = text;
       elem.blur(function(e) {
         if ($.trim(elem.val()) == "")
@@ -738,7 +634,9 @@
         elem[(active ? 'addClass' : 'removeClass')]('placeholder').attr('spellcheck', active);
       });
 
-      if (this != document.activeElement) // Do not blur currently focused element
+      // Do not blur currently focused element (catch exception: #1489008)
+      try { active = this == document.activeElement; } catch(e) {}
+      if (!active)
         elem.blur();
     }
   });

--
Gitblit v1.9.1