[Laszlo-checkins] r14414 - in openlaszlo/trunk/WEB-INF/lps/lfc: kernel/dhtml views

max@openlaszlo.org max at openlaszlo.org
Fri Jul 31 12:41:06 PDT 2009


Author: max
Date: 2009-07-31 12:41:04 -0700 (Fri, 31 Jul 2009)
New Revision: 14414

Modified:
   openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzInputTextSprite.js
   openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzKeyboardKernel.js
   openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzSprite.js
   openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzTextSprite.js
   openlaszlo/trunk/WEB-INF/lps/lfc/views/LzInputText.lzs
Log:
Change 20090731-maxcarlson-a by maxcarlson at Bank on 2009-07-31 09:33:19 PDT
    in /Users/maxcarlson/openlaszlo/trunk-clean
    for http://svn.openlaszlo.org/openlaszlo/trunk

Summary: Redo mouse events for inputtext

Bugs Fixed: LPP-8356 - IE inputtext can not recieve first click event

Technical Reviewer: ptw
QA Reviewer: hminsky

Details: LzSprite, LzKeyboardKernel - Don't hide focused inputtexts.

LzTextSprite - Update setID()

LzInputTextSprite - Eliminate __LZinputclickdiv and use __LZclickcontainerdiv instead.  Eliminate IE-specific focus workarounds in __hideIfNotFocused().  Eliminate Firefox specific dom_breaks_focus quirk workarounds.  Handle mouse events in __setTextEvents() instead of a separate click div now that click divs are hidden.  Override setClickable() to only set the clickable property, so extra click divs aren't created.  Avoid setting _cancelfocus/blur for now.  Update setID().

LzInputText - Don't forward mouse events through inputtextevent().

Tests: See tests/lpp-8356.lzx?lzr=dhtml across browsers.  Both inputtexts are selectable with the mouse and by tabbing.  The clickable inputtext sends mouse events.



Modified: openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzInputTextSprite.js
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzInputTextSprite.js	2009-07-31 16:47:57 UTC (rev 14413)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzInputTextSprite.js	2009-07-31 19:41:04 UTC (rev 14414)
@@ -87,43 +87,35 @@
 
     if (this.quirks.fix_clickable) {
         if (this.quirks.fix_ie_clickable) {
-            this.__LZinputclickdiv = document.createElement('img');
-            this.__LZinputclickdiv.src = lz.embed.options.serverroot + LzSprite.prototype.blankimage;
-        } else {
-            this.__LZinputclickdiv = document.createElement('div');
+            this.__LZclickcontainerdiv = document.createElement('img');
+            this.__LZclickcontainerdiv.src = lz.embed.options.serverroot + LzSprite.prototype.blankimage;
+            this.__LZclickcontainerdiv.className = 'lzclickdiv';
+            this.__LZclickcontainerdiv.owner = this;
         }
-        this.__LZinputclickdiv.className = 'lzclickdiv';
-        this.__LZinputclickdiv.owner = this;
         // keep LzSprite.destroy() in sync to prevent leaks
         if (this.quirks.ie_mouse_events) {
-            this.__LZinputclickdiv.onmouseenter = this.__handlemouse; 
-            //can't get this to work - see LPP-5435. 
-            // this.__LZinputclickdiv.onmousedown = this.__handlemouse; 
+            this.__LZclickcontainerdiv.onmouseenter = this.__handlemouse; 
         } else {
-            this.__LZinputclickdiv.onmouseover = this.__handlemouse; 
+            this.__LZclickcontainerdiv.onmouseover = this.__handlemouse; 
         }
 
-    if (this.quirks.input_highlight_bug) {
-        // TODO [hqm 2009-06-09] LPP-8121 I discovered that if an
-        // input field is contained within a div which has a white
-        // background color, then it selected text will highlight with
-        // a dark blue color. The div can have zero width,
-        // Windows/Firefox only seems to look at the bgcolor of the
-        // containing div when deciding what color to use for input
-        // text highlight. So this adds an extra div, with zero width,
-        // in which the actual clickable/selectable input text element
-        // is placed.
-        var ffoxdiv = document.createElement('div');
-        ffoxdiv.style.backgroundColor = 'white';
-        ffoxdiv.style.width = '0px';
-        this.__LZclickcontainerdiv.appendChild(ffoxdiv);        
-        ffoxdiv.appendChild(this.__LZinputclickdiv);
-    } else {
-        this.__LZclickcontainerdiv.appendChild(this.__LZinputclickdiv);
-    }
-
-    }    
-
+        if (this.quirks.input_highlight_bug) {
+            // TODO [hqm 2009-06-09] LPP-8121 I discovered that if an
+            // input field is contained within a div which has a white
+            // background color, then it selected text will highlight with
+            // a dark blue color. The div can have zero width,
+            // Windows/Firefox only seems to look at the bgcolor of the
+            // containing div when deciding what color to use for input
+            // text highlight. So this adds an extra div, with zero width,
+            // in which the actual clickable/selectable input text element
+            // is placed.
+            var ffoxdiv = document.createElement('div');
+            ffoxdiv.style.backgroundColor = 'white';
+            ffoxdiv.style.width = '0px';
+            this.__LZclickcontainerdiv.appendChild(ffoxdiv);        
+            //ffoxdiv.appendChild(this.__LZinputclickdiv);
+        }
+    } 
     this.__LZdiv.appendChild(this.__LzInputDiv);
 
     //Debug.write(this.__LzInputDiv.style);
@@ -208,7 +200,8 @@
 // called from the scope of __LZinputclickdiv
 LzInputTextSprite.prototype.__handlemouse = function(e) {
     var sprite = this.owner;
-    if (sprite.selectable != true) return;
+    // make sure we have a sprite and view
+    if (! sprite || ! sprite.owner || sprite.selectable != true) return;
     if (sprite.__fix_inputtext_with_parent_resource) {
         //if (!e) e = window.event;
         //Debug.warn(e.type);
@@ -284,37 +277,21 @@
         //this.__LZdiv.onselectstart = null;
         this.__LZdiv.onselectstart = null;
     }
-
 }
 
 LzInputTextSprite.prototype.__hideIfNotFocused = function(eventname, target) {
     var lzinppr = LzInputTextSprite.prototype;
     if (lzinppr.__lastshown == null) return;
     var quirks = LzSprite.prototype.quirks;
-    if (quirks.fix_ie_clickable) {
-        if (eventname == 'onmousemove') {
-            // track mouse position for inputtext when global clickable is false
-            if (lzinppr.__globalclickable == false && lzinppr.__focusedSprite && target) {
-                if (target.owner != lzinppr.__focusedSprite) {
-                    LzMouseKernel.setGlobalClickable(true);
-                } else {
-                    LzMouseKernel.setGlobalClickable(false);
-                }
+    if (quirks.textgrabsinputtextfocus) {
+        var s = window.event;
+        if (s && s.srcElement && s.srcElement.owner && s.srcElement.owner instanceof LzTextSprite) {
+            //Debug.write('text intercepting focus', eventname, s.owner instanceof LzTextSprite);
+            if (eventname == 'onmousedown') {
+                lzinppr.__lastshown.gotFocus();
             }
             return;
-        } else if (eventname != null && lzinppr.__globalclickable == true) {
-            LzMouseKernel.setGlobalClickable(false);
         }
-        if (quirks.textgrabsinputtextfocus) {
-            var s = window.event;
-            if (s && s.srcElement && s.srcElement.owner && s.srcElement.owner instanceof LzTextSprite) {
-                //Debug.write('text intercepting focus', eventname, s.owner instanceof LzTextSprite);
-                if (eventname == 'onmousedown') {
-                    lzinppr.__lastshown.gotFocus();
-                }
-                return;
-            }
-        }
     }
     if (lzinppr.__focusedSprite != lzinppr.__lastshown) {
         lzinppr.__lastshown.__hide();
@@ -370,9 +347,6 @@
 
 // called by the LFC focus manager
 LzInputTextSprite.prototype.gotBlur = function() {
-    if (this.quirks.dom_breaks_focus) {
-        this._cancelfocus = this._cancelblur = false;
-    }
     if (LzInputTextSprite.prototype.__focusedSprite != this) return;
     //Debug.write('blur', this.uid, LzKeyboardKernel.__cancelKeys);
     this.deselect();
@@ -380,9 +354,6 @@
 
 // called by the LFC focus manager
 LzInputTextSprite.prototype.gotFocus = function() {
-    if (this.quirks.dom_breaks_focus) {
-        this._cancelfocus = this._cancelblur = false;
-    }
     if (LzInputTextSprite.prototype.__focusedSprite == this) return;
     //Debug.write('focus', this.uid, LzKeyboardKernel.__cancelKeys);
     this.select();
@@ -410,14 +381,19 @@
     var div = this.__LzInputDiv;
     var f = c ? this.__textEvent : null;
     div.onblur = f;
-    div.onmousedown = f;
+    div.onfocus = f;
     if (this.quirks.ie_mouse_events) {
+        div.ondrag = f;
+        div.ondblclick = f;
+        div.onmouseenter = f;
         div.onmouseleave = f;
     } else {
+        div.onmouseover = f;
         div.onmouseout = f;
     }
     div.onmousemove = f;
-    div.onfocus = f;
+    div.onmousedown = f;
+    div.onmouseup = f;
     div.onclick = f;
     div.onkeyup = f;
     div.onkeydown = f;
@@ -561,19 +537,35 @@
 
     LzMouseKernel.__sendMouseMove(evt);
 
+    // rename ie-specific events to be compatible
+    if (quirks.ie_mouse_events) {
+        if (eventname == 'onmouseenter') {
+            eventname = 'onmouseover';
+        } else if (eventname == 'onmouseleave') {
+            eventname = 'onmouseout';
+        } else if (eventname == 'ondblclick') {
+            // Send artificial events to mimic other browsers
+            if (sprite.clickable) {
+                sprite.__mouseEvent('onmousedown', true);
+                sprite.__mouseEvent('onmouseup', true);
+                sprite.__mouseEvent('onclick', true);
+            }
+            return false;
+        } else if (eventname == 'ondrag') {
+            // ignore these
+            return false;
+        }
+    }
+
     if (quirks.autoscroll_textarea) {
       // Keep track of left button state for autoscrolling (LPP-8277)
       if (eventname == 'onmousedown') {
           sprite.dragging = true;
-      }
-      else if (eventname == 'onmouseup' || eventname == 'onmouseout') {
+      } else if (eventname == 'onmouseup' || eventname == 'onmouseout') {
           sprite.dragging = false;
       }
     }
 
-    if (quirks.ie_mouse_events && eventname == 'onmouseleave') {
-        eventname = 'onmouseout';
-    }
     if (sprite.__shown != true) {
         // this only happens when tabbing in from outside the app
         if (eventname == 'onfocus') {
@@ -584,11 +576,10 @@
             LzInputTextSprite.prototype.__lastfocus = sprite;
             LzKeyboardKernel.setKeyboardControl(true);
         }
-        return; 
+        if (eventname != 'onblur') return; 
     } else if (sprite.__shown == false) {
         return;
     }
-    var nextFocus = null;
     if (eventname == 'onfocus' || eventname == 'onmousedown') {
         if (eventname == 'onfocus') {
             LzMouseKernel.setGlobalClickable(false);
@@ -610,36 +601,11 @@
             sprite.select();
             return;
         }
-        // check if __hide() was called
-        var shown = sprite.__shown;
         sprite.__hide();
-        if (quirks.dom_breaks_focus && (shown && ! sprite.__shown)) {
-            // workaround for Firefox bug (LPP-7786):
-            // DOM operations (appendChild, removeChild) on blurring element
-            // breaks the focus in Firefox, so we need to re-focus the
-            // element later again
-            var fsprite = LzInputTextSprite.prototype.__focusedSprite;
-            nextFocus = fsprite && fsprite.__LzInputDiv;
-        }
         if (sprite._cancelblur) {
             sprite._cancelblur = false;
-            if (nextFocus) {
-                // re-initiate focus
-                nextFocus.focus();
-            }
             return;
         }
-    } else if (eventname == 'onmouseout') {
-      // Only re-enable clickable if the mouse actually leaves our
-      // bounding box (i.e., not just because it enters another sprite
-      // that overlaps us)
-//       if ($debug) {
-//         var m = sprite.getMouse(null);
-//         Debug.info("%w: 0 <= %d < %d; 0 <= %d < %d", sprite, m.x, sprite.width, m.y, sprite.height);
-//       }
-      if (! sprite.__isMouseOver()) {
-        sprite.__hide();
-      }
     } else if (eventname == 'onmousemove') {
         if (quirks.autoscroll_textarea && sprite.dragging) {
             // Simulate mouse scrolling naer the top and bottom (LPP-8277)
@@ -748,20 +714,32 @@
                 d.scrollTop = d.scrollHeight - d.clientHeight + 20;
             }
         } else {
-            if (eventname == 'onmousedown') {
-                view.inputtextevent(eventname);
-                // also send an artifial 'onfocus' event
-                eventname = 'onfocus';
+            if (eventname == 'onmousedown' || eventname == 'onmouseup' || eventname == 'onmouseover' || eventname == 'onmouseout' || eventname == 'onclick') {
+                sprite.__mouseEvent(evt);
+                // prevent bubbling
+                evt.cancelBubble = true;
+
+                if (eventname == 'onmouseout') {
+                    // Only re-enable clickable if the mouse actually leaves our
+                    // bounding box (i.e., not just because it enters another sprite
+                    // that overlaps us)
+                    //       if ($debug) {
+                    //         var m = sprite.getMouse(null);
+                    //         Debug.info("%w: 0 <= %d < %d; 0 <= %d < %d", sprite, m.x, sprite.width, m.y, sprite.height);
+                    //       }
+                    if (! sprite.__isMouseOver()) {
+                        sprite.__hide();
+                    }
+                }
+                return;
             }
             view.inputtextevent(eventname);
         }
     }
+}
 
-    if (nextFocus) {
-        // re-initiate focus, see above
-        // do this late to preserve correct event order
-        nextFocus.focus();
-    }
+LzInputTextSprite.prototype.setClickable = function ( val ){
+    this.clickable = val;
 }
 
 LzInputTextSprite.prototype.setEnabled = function ( val ){
@@ -778,7 +756,7 @@
 }
 
 LzInputTextSprite.prototype.select = function (){
-    this._cancelblur = true;
+    //this._cancelblur = true;
     this.__show();
     // Setting focus can generate an error in IE7/dhtml (LPP-6142)
     try {
@@ -1045,7 +1023,7 @@
 }
 
 LzInputTextSprite.prototype.deselect = function (){
-    this._cancelfocus = true;
+    //this._cancelfocus = true;
     this.__hide();
     if (this.__LzInputDiv && this.__LzInputDiv.blur) this.__LzInputDiv.blur();
     if (window['LzKeyboardKernel']) LzKeyboardKernel.__cancelKeys = true;
@@ -1095,7 +1073,6 @@
     var nw = LzTextSprite.prototype.setWidth.call(this, w);
     if (this.quirks.fix_clickable && nw != null) {
         this.__LZclickcontainerdiv.style.width = nw;
-        this.__LZinputclickdiv.style.width = nw;
     }   
 }
 
@@ -1105,7 +1082,6 @@
     var nh = LzTextSprite.prototype.setHeight.call(this, h);
     if (this.quirks.fix_clickable && nh != null) {
         this.__LZclickcontainerdiv.style.height = nh;
-        this.__LZinputclickdiv.style.height = nh;
     }
 }   
 
@@ -1151,8 +1127,3 @@
         }
     }
 }
-
-LzInputTextSprite.prototype.setID = function(id){
-    if (!this.__LZdiv.id) this.__LZdiv.id = 'inputtextsprite' + id;
-    if (!this.__LZclickcontainerdiv.id) this.__LZclickcontainerdiv.id = 'click' + id;
-}

Modified: openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzKeyboardKernel.js
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzKeyboardKernel.js	2009-07-31 16:47:57 UTC (rev 14413)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzKeyboardKernel.js	2009-07-31 19:41:04 UTC (rev 14414)
@@ -178,11 +178,6 @@
             //console.log('setKeyboardControl' + dhtmlKeyboardControl);
             handler = LzKeyboardKernel.__keyboardEvent;
         }
-        var lzinputproto = LzInputTextSprite.prototype;
-        if (lzinputproto.__focusedSprite) {
-            // hide any focused inputtexts
-            lzinputproto.__hideIfNotFocused();
-        }
         // can't use lz.embed.attachEventHandler because we need to cancel events selectively
         if (LzSprite.prototype.quirks.keyboardlistentotop) {
             var doc = window.top.document;

Modified: openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzSprite.js
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzSprite.js	2009-07-31 16:47:57 UTC (rev 14413)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzSprite.js	2009-07-31 19:41:04 UTC (rev 14414)
@@ -552,7 +552,7 @@
     ,scrollbar_width: 15
     ,inputtext_strips_newlines: false
     ,swf8_contextmenu: true
-    ,dom_breaks_focus: false
+    //,dom_breaks_focus: false // no longer needed
     ,inputtext_anonymous_div: false
     ,clipped_scrollbar_causes_display_turd: false
     ,hasmetakey: false
@@ -1333,10 +1333,6 @@
                 rootdiv.onmouseover();
             }
         }
-        var lzinputproto = window['LzInputTextSprite'] && LzInputTextSprite.prototype;
-        if (lzinputproto && lzinputproto.__lastshown != null) {
-            lzinputproto.__hideIfNotFocused();
-        }
     }
 
     //Debug.write('__mouseEvent', eventname, this.owner);
@@ -2663,7 +2659,7 @@
 
 LzSprite.prototype.setID = function(id){
     if (!this._id) this._id = id;
-    if (!this.__LZdiv.id) this.__LZdiv.id = 'sprite' + id;
+    if (!this.__LZdiv.id) this.__LZdiv.id = this._dbg_typename + id;
     if (!this.__LZclickcontainerdiv.id) this.__LZclickcontainerdiv.id = 'click' + id;
     if (this.__LZcontextcontainerdiv && ! this.__LZcontextcontainerdiv.id) this.__LZcontextcontainerdiv.id = this.__LZcontextcontainerdiv.id = 'context' + id;
 }

Modified: openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzTextSprite.js
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzTextSprite.js	2009-07-31 16:47:57 UTC (rev 14413)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzTextSprite.js	2009-07-31 19:41:04 UTC (rev 14414)
@@ -816,9 +816,4 @@
     }
 }
 
-LzTextSprite.prototype.setID = function(id){
-    if (!this.__LZdiv.id) this.__LZdiv.id = 'textsprite' + id;
-    if (!this.__LZclickcontainerdiv.id) this.__LZclickcontainerdiv.id = 'click' + id;
 }
-
-}

Modified: openlaszlo/trunk/WEB-INF/lps/lfc/views/LzInputText.lzs
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/views/LzInputText.lzs	2009-07-31 16:47:57 UTC (rev 14413)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/views/LzInputText.lzs	2009-07-31 19:41:04 UTC (rev 14414)
@@ -165,10 +165,6 @@
     isprite.gotBlur();
 }
 
-if ($dhtml) {
-private static const __LZinputmouse = {onclick: true, onmousedown: true, onmouseout: true};
-}
-
 /** @access private 
  * Receive input text events from sprite: onblur, onfocus, onchange
  * Additionally for dhtml: onmousedown, onmouseout, onclick
@@ -199,17 +195,6 @@
             lz.Focus.clearFocus();
         }
     } else {
-        if ($dhtml) {
-            if (LzInputText.__LZinputmouse[eventname]) {
-                // must use lz.ModeManager to propagate mouse-events
-                // TODO: [20081031 anba] I don't know why the dhtml-kernel sends
-                // mouse-events through inputtextevent(). This code wasn't
-                // even executed when I ran simple testcases. Maybe it's just
-                // redundant now and we can remove it..
-                lz.ModeManager.handleMouseEvent(this, eventname);
-                return;
-            }
-        }
         if ($debug) {
             Debug.warn("unhandled inputtextevent='%s' in %#w", eventname, this);
         }



More information about the Laszlo-checkins mailing list