[Laszlo-checkins] r13948 - openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml

bargull@openlaszlo.org bargull at openlaszlo.org
Mon May 18 14:38:34 PDT 2009


Author: bargull
Date: 2009-05-18 14:38:27 -0700 (Mon, 18 May 2009)
New Revision: 13948

Modified:
   openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzContextMenuKernel.lzs
   openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzMouseKernel.js
   openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzSprite.js
Log:
Change 20090518-bargull-iCv by bargull at dell--p4--2-53 on 2009-05-18 22:35:24
    in /home/Admin/src/svn/openlaszlo/trunk
    for http://svn.openlaszlo.org/openlaszlo/trunk

Summary: DHTML: contextmenu part one

New Features:

Bugs Fixed: LPP-8201 (DHTML: hidden contextmenu item shows separator), LPP-8202 (DHTML: possible to change an active contextmenu), LPP-8203 (DHTML: contextmenu isn't displayed after mouse left application), LPP-8204 (DHTML: browser contextmenu is displayed)

Technical Reviewer: max
QA Reviewer: henry
Doc Reviewer: (pending)

Documentation:

Release Notes:

Details:
LzContextMenuKernel:
- remove listeners to onmousedown, onmouseup, onclick from anchor-elements, this didn't work in Firefox. Instead add handlers to lzcontextmenu-div
- only show contextmenu if "showbuiltins" isn't set
- remove ignore-arg from __hide(), no longer needed
- Move contextmenu-div into separate method and store reference to the div, so you don't need to use getElementById() over and over again
- only select contextmenu item on left button click

LzSprite:
- for onmouseout, it's "toElement", not "fromElement"..
- Handle contextmenu for keyboard activation (see "onmouseover" handler for root-sprite's div)
- handle "onmousemove" first, because it's processed often


LPP-8201: Add separator after checking for double contextmenu items (LzContextMenuKernel#__show())
LPP-8202: Remove implementation of LzContextMenuKernel#addItem(..), #clearItems(). It was added for LPP-6749, but the right fix is to call the contextmenu delegate before displaying the contextmenu (see above). Now you can also remove the "send" parameter from "__show(..)".
LPP-8203: In LzSprite#__mouseEvent(..), call the "onmouseover" event-handler from the root-sprite's div, if the mouse entered the application.
LPP-8204: Fixed by the handlers added to the lzcontextmenu-div (see above) and the updated keyboard activation code to handle the contextmenu-div
    

Tests:
see bugreports



Modified: openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzContextMenuKernel.lzs
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzContextMenuKernel.lzs	2009-05-18 21:23:02 UTC (rev 13947)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzContextMenuKernel.lzs	2009-05-18 21:38:27 UTC (rev 13948)
@@ -16,7 +16,6 @@
 
 function LzContextMenuKernel (newowner:LzContextMenu) {
     this.owner = newowner;
-
 }
 
 var owner:LzContextMenu = null;
@@ -43,10 +42,7 @@
   * @access private
   */
 function addItem (item) {
-    if (LzMouseKernel.__showncontextmenu === this) {
-        this.__hide();
-        this.__show(false);
-    }
+    // nothing to do
 }
 
 /**
@@ -71,23 +67,44 @@
   * @access private
   */
 function clearItems () {
-    if (LzMouseKernel.__showncontextmenu === this) {
-        this.__hide();
-        this.__show(false);
-    }
+    // nothing to do
 }
 
 /** @access private */
-function __show (send=true) {
-    var s = document.getElementById('lzcontextmenu')
+static var lzcontextmenu = null;
+
+/** @access private */
+static function __create () {
+    var s = document.getElementById('lzcontextmenu');
     if (! s) {
         s = document.createElement('div');
         lz.embed.__setAttr(s, 'id', 'lzcontextmenu');
         lz.embed.__setAttr(s, 'style', 'display: none');
+        var stopevent = function (e) {
+            if (e) {
+                e.preventDefault();
+                e.stopPropagation();
+            } else {
+                e = window.event;
+                e.returnValue = false;
+                e.cancelBubble = true;
+            }
+            return false;
+        }
+        s.onmousedown = stopevent;
+        s.onmouseup = stopevent;
+        s.onclick = stopevent;
         document.body.appendChild(s);
+
+        LzContextMenuKernel.lzcontextmenu = s;
     }
+    return s;
+}
+
+/** @access private */
+function __show () {
     var owner = this.owner;
-    if (send && this.__sentshowevent == false) {
+    if (this.__sentshowevent == false) {
         // Avoid sending onmenuopen events more than once - see LPP-8189
         this.__sentshowevent = true;
         var del = this._delegate;
@@ -100,67 +117,60 @@
     var items = owner.getItems();
     var _items = {};
     for (var i = 0; i < items.length; i++) {
-        var cm = items[i].kernel;
-        var v = cm.cmenuitem;
-        if (v.visible != true) continue; 
-        if (v.separatorBefore) o += '<div class="separator"></div>';
-
+        var v = items[i].kernel.cmenuitem;
         var caption = v.caption;
         // Don't display the same item twice (matches swf behavior)
-        if (caption in _items) continue;
+        if (v.visible != true || caption in _items) {
+            continue; 
+        }
         // Mark as displayed
         _items[caption] = true;
         shownItems += 1;
 
-        o += '<a href="" onclick="LzContextMenuKernel.prototype.__cancelevent();return false;" onmousedown="LzContextMenuKernel.prototype.__cancelevent();return false;" ';
+        if (v.separatorBefore) {
+            o += '<div class="separator"></div>';
+        }
+
         if (v.enabled) {
-            o += 'onmouseup="LzMouseKernel.__showncontextmenu.__select(' + i + ');return false;"';
+            o += '<a href="" onmouseup="LzMouseKernel.__showncontextmenu.__select(arguments[0],' + i + ');">';
         } else {
-            o += 'onmouseup="LzContextMenuKernel.prototype.__cancelevent();return false;" class="disabled"';
+            o += '<a href="" class="disabled">';
         }
-        o += '>' + caption + '</a>';
+        o += caption + '</a>';
     }
 
     LzMouseKernel.__showncontextmenu = this;
 
+    var s = LzContextMenuKernel.lzcontextmenu || LzContextMenuKernel.__create();
     s.innerHTML = o;
-    if (send) {
-        s.style.left = LzMouseKernel.__x + 'px';
-        s.style.top = LzMouseKernel.__y + 'px';
-    }
+    s.style.left = LzMouseKernel.__x + 'px';
+    s.style.top = LzMouseKernel.__y + 'px';
 
-    // Only show menu if there are any visible items
-    if (shownItems) {
+    // Only show menu if there are any visible items and builtin items are hidden
+    if (shownItems && ! this.showbuiltins) {
         s.style.display = 'block';
     }
 }
 
-/** Cancels event bubbling for Safari and IE
-    @access private */
-function __cancelevent() {
-    var e = window.event;
-    if (e) {
-        e.cancelBubble = true;
+/** @access private */
+function __hide () {
+    var s = LzContextMenuKernel.lzcontextmenu;
+    if (s) {
+        s.style.display = 'none';
     }
-    return false;
-}
-
-/** @access private */
-function __hide (ignore) {
-    var s = document.getElementById('lzcontextmenu')
-    if (! s) return;
-    s.style.display = 'none';
     this.__sentshowevent = false;
     LzMouseKernel.__showncontextmenu = null;
 }
 
 /** @access private */
-function __select (i) {
-    this.__hide();
-    this.__cancelevent();
-    var items = this.owner.getItems();
-    if (items[i]) items[i].kernel.__select();
-    return false;
+function __select (e, i) {
+    e = e || window.event;
+    var leftbutton = (LzSprite.prototype.quirks.ie_mouse_events ? 1 : 0);
+    if (e.button == leftbutton) {
+        this.__hide();
+        var items = this.owner.getItems();
+        if (items[i]) items[i].kernel.__select();
+    }
 }
 
 }; // End of LzContextMenuKernel

Modified: openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzMouseKernel.js
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzMouseKernel.js	2009-05-18 21:23:02 UTC (rev 13947)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzMouseKernel.js	2009-05-18 21:38:27 UTC (rev 13948)
@@ -189,17 +189,21 @@
         //Debug.error('setGlobalClickable', isclickable, LzInputTextSprite.prototype.__lastfocus, LzInputTextSprite.prototype.__focusedSprite, LzInputTextSprite.prototype.__lastshown);
         if (! isclickable) {
             // reset any inputtexts that are showing so they don't disappear - see LPP-7190
-            if (LzInputTextSprite.prototype.__lastshown) {
-                LzInputTextSprite.prototype.__lastshown.__hide();
-                LzInputTextSprite.prototype.__lastshown = null;
+            var lzinputproto = LzInputTextSprite.prototype;
+            var lastshown = lzinputproto.__lastshown;
+            if (lastshown) {
+                lastshown.__hide();
+                lzinputproto.__lastshown = null;
             }
-            if (LzInputTextSprite.prototype.__focusedSprite) {
-                LzInputTextSprite.prototype.__focusedSprite.deselect();
-                LzInputTextSprite.prototype.__focusedSprite = null;
+            var focused = lzinputproto.__focusedSprite;
+            if (focused) {
+                focused.deselect();
+                lzinputproto.__focusedSprite = null;
             }
-            if (LzInputTextSprite.prototype.__lastfocus) {
-                LzInputTextSprite.prototype.__lastfocus.deselect();
-                LzInputTextSprite.prototype.__lastfocus = null;
+            var lastfocus = lzinputproto.__lastfocus;
+            if (lastfocus) {
+                lastfocus.deselect();
+                lzinputproto.__lastfocus = null;
             }
         }
         var el = document.getElementById('lzcanvasclickdiv');

Modified: openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzSprite.js
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzSprite.js	2009-05-18 21:23:02 UTC (rev 13947)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzSprite.js	2009-05-18 21:38:27 UTC (rev 13948)
@@ -96,7 +96,7 @@
         }
 
         if (this.quirks.activate_on_mouseover) {
-            // Mouse detection for activiation/deactivation of keyboard events
+            // Mouse detection for activation/deactivation of keyboard/mouse events
             div.mouseisover = false;
             div.onmouseover = function(e) {
                 if (LzSprite.prototype.quirks.focus_on_mouseover) {
@@ -110,7 +110,7 @@
             div.onmouseout = function(e) {
                 if (! e) {
                     e = window.event;
-                    var el = e.fromElement;
+                    var el = e.toElement;
                 } else {
                     var el = e.relatedTarget;
                 }
@@ -126,7 +126,18 @@
                         return;
                     }
                 }
-                if (el && el.owner && el.className.indexOf('lz') == 0) {
+                var mousein = false;
+                if (el) {
+                    var cm = LzContextMenuKernel.lzcontextmenu;
+                    if (el.owner && el.className.indexOf('lz') == 0) {
+                        // lzdiv, lzclickdiv, etc.
+                        mousein = true;
+                    } else if (cm && (el === cm || el.parentNode === cm)) {
+                        // context-menu resp. context-menu item
+                        mousein = true;
+                    }
+                }
+                if (mousein) {
                     if (quirks.fix_ie_clickable) {
                         LzInputTextSprite.prototype.__setglobalclickable(true);
                     }
@@ -1172,20 +1183,20 @@
 
     LzMouseKernel.__sendMouseMove(e);
 
-    if (window['LzInputTextSprite'] && eventname == 'onmouseover' && LzInputTextSprite.prototype.__lastshown != null) LzInputTextSprite.prototype.__hideIfNotFocused();
-
     if (e.button == 2 && eventname != 'oncontextmenu') return;
-    if (eventname == 'onmousedown') {
+    if (eventname == 'onmousemove') {
+        return;   
+    } else if (eventname == 'onmousedown') {
         // cancel mousedown event bubbling...
         e.cancelBubble = true;
         this.__mouseisdown = true;
-        if (window['LzMouseKernel']) {
-            LzMouseKernel.__lastMouseDown = this;
-        }
+        LzMouseKernel.__lastMouseDown = this;
+
     } else if (eventname == 'onmouseup') {
         e.cancelBubble = false;
         // only send the event if this is same sprite the mouse button went down on
-        if (window['LzMouseKernel'] && LzMouseKernel.__lastMouseDown == this) {
+        if (LzMouseKernel.__lastMouseDown === this) {
+            LzMouseKernel.__lastMouseDown = null;
             if (this.quirks.ie_mouse_events) {
                 // Must be done for onmouseupoutside to work
                 if (this.__isMouseOver()) {
@@ -1200,12 +1211,22 @@
         }
     } else if (eventname == 'onmouseupoutside') {
         this.__mouseisdown = false;
-    } else if (eventname == 'onmousemove') {
-        return;
+    } else if (eventname == 'onmouseover') {
+        if (this.quirks.activate_on_mouseover) {
+            var rootdiv = LzSprite.__rootSprite.__LZdiv;
+            if (! rootdiv.mouseisover) {
+                // enable keyboard/mouse events
+                rootdiv.onmouseover();
+            }
+        }
+        var lzinputproto = window['LzInputTextSprite'] && LzInputTextSprite.prototype;
+        if (lzinputproto && lzinputproto.__lastshown != null) {
+            lzinputproto.__hideIfNotFocused();
+        }
     }
 
     //Debug.write('__mouseEvent', eventname, this.owner);
-    if (this.owner.mouseevent && LzMouseKernel && LzMouseKernel['__sendEvent']) {
+    if (this.owner.mouseevent) {
         // send dragin/out events if the mouse is currently down
         if (LzMouseKernel.__lastMouseDown) {
             if (eventname == 'onmouseover' || eventname == 'onmouseout') {
@@ -1216,7 +1237,7 @@
                     }
                 } else {
                     // only send mouseover/out if the mouse went down on this sprite
-                    if (LzMouseKernel.__lastMouseDown == this) {
+                    if (LzMouseKernel.__lastMouseDown === this) {
                         LzMouseKernel.__sendEvent(eventname, this.owner);
                     }
                 }
@@ -1235,8 +1256,8 @@
     return p.x >= 0 && p.y >= 0 && p.x <= this.width && p.y <= this.height;
 }
 
-// called by LzMouseKernel when mouse goes up on another sprite
 /**
+  * Called by LzMouseKernel when mouse goes up on another sprite
   * @access private
   */
 LzSprite.prototype.__globalmouseup = function ( e ){



More information about the Laszlo-checkins mailing list