1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Synacor, Inc. 5 * 6 * The contents of this file are subject to the Common Public Attribution License Version 1.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: https://www.zimbra.com/license 9 * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15 10 * have been added to cover use of software over a computer network and provide for limited attribution 11 * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B. 12 * 13 * Software distributed under the License is distributed on an "AS IS" basis, 14 * WITHOUT WARRANTY OF ANY KIND, either express or implied. 15 * See the License for the specific language governing rights and limitations under the License. 16 * The Original Code is Zimbra Open Source Web Client. 17 * The Initial Developer of the Original Code is Zimbra, Inc. All rights to the Original Code were 18 * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015. 19 * 20 * All portions of the code are Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 25 /** 26 * 27 * 28 * @private 29 */ 30 DwtUiEvent = function(init) { 31 if (arguments.length == 0) return; 32 DwtEvent.call(this, true); 33 this.reset(); 34 } 35 36 DwtUiEvent.prototype = new DwtEvent; 37 DwtUiEvent.prototype.constructor = DwtUiEvent; 38 39 DwtUiEvent.prototype.isDwtUiEvent = true; 40 DwtUiEvent.prototype.toString = function() { return "DwtUiEvent"; } 41 42 DwtUiEvent.prototype.reset = 43 function() { 44 this.dwtObj = null 45 this.altKey = false; 46 this.ctrlKey = false; 47 this.metaKey = false; 48 this.shiftKey = false; 49 this.target = null; 50 this.type = null; 51 this.docX = -1; 52 this.docY = -1; 53 this.elementX = -1; 54 this.elementY = -1; 55 this.ersatz = false; // True means this event was manufactured 56 this._stopPropagation = false; 57 this._returnValue = true; 58 this._dontCallPreventDefault = false; // True means to allow the the (unusual) situation in Firefox where we 59 // want the event handler to return false without calling preventDefault(). 60 } 61 62 /** 63 * Pass caller's "this" as 'target' if using IE and the ev may have come from another window. The target 64 * will be used to get to the window that generated the event, so the event can be found. 65 */ 66 DwtUiEvent.getEvent = 67 function(ev, target) { 68 ev = ev || window.event; 69 if (ev) { return ev; } 70 71 // get event from iframe in IE; see http://www.outofhanwell.com/blog/index.php?cat=25 72 if (target) { 73 DBG.println(AjxDebug.DBG3, "getEvent: Checking other window for event"); 74 var pw = (target.ownerDocument || target.document || target).parentWindow; 75 return pw ? pw.event : null; 76 } 77 } 78 79 /** 80 * Returns the target element of the event. 81 * 82 * @param ev [Event] DHTML event 83 * @param useRelatedTarget [boolean]* if true, return element that was related to this event; 84 * for a MOUSEOVER or MOUSEOUT event, that's the element 85 * moved from/to. 86 */ 87 DwtUiEvent.getTarget = 88 function(ev, useRelatedTarget) { 89 ev = DwtUiEvent.getEvent(ev); 90 if (!ev) { return null; } 91 if (!useRelatedTarget) { 92 if (ev.target) { 93 // if text node (like on Safari) return parent 94 return (ev.target.nodeType == 3) ? ev.target.parentNode : ev.target; 95 } else if (ev.srcElement) { // IE 96 return ev.srcElement; 97 } 98 } else { 99 if (ev.relatedTarget) { 100 return ev.relatedTarget; 101 } else if (ev.toElement) { // IE 102 return ev.toElement; 103 } else if (ev.fromElement) { // IE 104 return ev.fromElement; 105 } 106 } 107 return null; 108 } 109 110 /** 111 * Returns the first element with a value for the given property, working its way up the element chain. 112 * 113 * @param ev [Event] DHTML event 114 * @param prop [string] the name of a property 115 * @param useRelatedTarget [boolean]* if true, return element that was related to this event; 116 * @param value [string]* expected value of given property 117 */ 118 DwtUiEvent.getTargetWithProp = 119 function(ev, prop, useRelatedTarget, value) { 120 var htmlEl = DwtUiEvent.getTarget(ev, useRelatedTarget); 121 while (htmlEl) { 122 var elValue = Dwt.getAttr(htmlEl, prop); 123 if (elValue != null && elValue !== "" && (!value || (elValue == value))) { 124 return htmlEl; 125 } 126 htmlEl = htmlEl.parentNode; 127 } 128 return null; 129 } 130 131 /** 132 * Returns the first element with the given class name, working its way up the element chain. 133 * 134 * @param ev [Event] DHTML event 135 * @param className [string] the requested class name 136 * @param useRelatedTarget [boolean]* if true, return element that was related to this event; 137 */ 138 DwtUiEvent.getTargetWithClass = 139 function(ev, className, useRelatedTarget) { 140 var htmlEl = DwtUiEvent.getTarget(ev, useRelatedTarget); 141 while (htmlEl && htmlEl.nodeType === 1) { 142 if (Dwt.hasClass(htmlEl, className)) { 143 return htmlEl; 144 } 145 htmlEl = htmlEl.parentNode; 146 } 147 return null; 148 } 149 150 /** 151 * Returns the first element with values for all of the given properties, working its way up the element chain. 152 * 153 * @param ev [Event] DHTML event 154 * @param props [array] a list of property names (strings) 155 */ 156 DwtUiEvent.getTargetWithProps = 157 function(ev, props) { 158 var htmlEl = DwtUiEvent.getTarget(ev); 159 while (htmlEl) { 160 var okay = true; 161 for (var i in props) { 162 var val = Dwt.getAttr(htmlEl, props[i]); 163 if (val == null || val === "") { 164 htmlEl = htmlEl.parentNode; 165 okay = false; 166 break; 167 } 168 } 169 if (okay) 170 return htmlEl; 171 } 172 return null; 173 } 174 175 DwtUiEvent.copy = 176 function(dest, src) { 177 dest.altKey = src.altKey; 178 dest.ctrlKey = src.ctrlKey; 179 dest.metaKey = src.metaKey; 180 dest.shiftKey = src.shiftKey; 181 dest.target = src.target; 182 dest.type = src.type; 183 dest.dwtObj = src.dwtObj; 184 dest.docX = src.docX; 185 dest.docY = src.docY; 186 dest.elementX = src.elementX; 187 dest.elementY = src.elementY; 188 dest.ersatz = src.ersatz; 189 dest._stopPropagation = src._stopPropagation; 190 dest._returnValue = src._returnValue; 191 } 192 193 /** 194 * Copies properties from the native DHTML event to this DWT event object. The target 195 * control can be optionally fetched by providing true as the second argument. 196 * 197 * @param ev [Event] DHTML event 198 * @param obj [DwtControl|true] if true, the target object will be fetched; otherwise 199 * used to set target object if present 200 */ 201 DwtUiEvent.prototype.setFromDhtmlEvent = 202 function(ev, obj) { 203 ev = DwtUiEvent.getEvent(ev); 204 if (!ev) { return; } 205 this.altKey = ev.altKey; 206 this.ctrlKey = ev.ctrlKey; 207 this.metaKey = ev.metaKey; 208 this.shiftKey = ev.shiftKey; 209 this.type = ev.type; 210 this.target = DwtUiEvent.getTarget(ev); 211 this.dwtObj = (obj === true) ? DwtControl.getTargetControl(ev) : obj; 212 213 // Compute document coordinates 214 if (ev.pageX != null) { 215 this.docX = ev.pageX; 216 this.docY = ev.pageY; 217 } else if (ev.clientX != null) { 218 this.docX = ev.clientX + document.body.scrollLeft - document.body.clientLeft; 219 this.docY = ev.clientY + document.body.scrollTop - document.body.clientTop; 220 if (document.body.parentElement) { 221 var bodParent = document.body.parentElement; 222 this.docX += bodParent.scrollLeft - bodParent.clientLeft; 223 this.docY += bodParent.scrollTop - bodParent.clientTop; 224 } 225 } 226 // Compute Element coordinates 227 if (ev.offsetX != null) { 228 this.elementX = ev.offsetX; 229 this.elementY = ev.offsetY; 230 } else if (!AjxEnv.isWebKitBased && ev.layerX != null) { 231 this.elementX = ev.layerX; 232 this.elementY = ev.layerY; 233 } else { // fail hard for others 234 this.elementX = Dwt.DEFAULT; 235 this.elementY = Dwt.DEFAULT; 236 } 237 238 this.ersatz = false; 239 return ev; 240 } 241 242 DwtUiEvent.prototype.setToDhtmlEvent = 243 function(ev) { 244 DwtUiEvent.setBehaviour(ev, this._stopPropagation, this._returnValue, this._dontCallPreventDefault); 245 } 246 247 DwtUiEvent.setBehaviour = 248 function(ev, stopPropagation, allowDefault, dontCallPreventDefault) { 249 var dhtmlEv = DwtUiEvent.getEvent(ev); 250 DwtUiEvent.setDhtmlBehaviour(dhtmlEv, stopPropagation, allowDefault, dontCallPreventDefault); 251 }; 252 253 DwtUiEvent.setDhtmlBehaviour = 254 function(dhtmlEv, stopPropagation, allowDefault, dontCallPreventDefault) { 255 256 dhtmlEv = DwtUiEvent.getEvent(dhtmlEv); 257 if (!dhtmlEv) { return; } 258 259 // stopPropagation is referring to the function found in Mozilla's event object 260 if (dhtmlEv.stopPropagation != null) { 261 if (stopPropagation) 262 dhtmlEv.stopPropagation(); 263 if (!allowDefault && !dontCallPreventDefault) 264 dhtmlEv.preventDefault(); 265 } else { 266 // IE only.. 267 dhtmlEv.returnValue = allowDefault; 268 dhtmlEv.cancelBubble = stopPropagation; 269 } 270 }; 271 272 /** 273 * @deprecated 274 * Use DwtControl.getTargetControl() instead. 275 * 276 * Returns a control (DWT object) based on the event, by finding the event target and using 277 * its reference to a DWT object in the element's "dwtObj" expando property. 278 * 279 * @param ev [Event] DHTML event 280 * @param useRelatedTarget [boolean]* if true, return element that was related to this event; 281 */ 282 DwtUiEvent.getDwtObjFromEvent = 283 function(ev, useRelatedTarget) { 284 var htmlEl = DwtUiEvent.getTargetWithProp(ev, "dwtObj", useRelatedTarget); 285 return htmlEl ? Dwt.getObjectFromElement(htmlEl) : null; 286 }; 287 288 /** 289 * @deprecated 290 * Instead, do something like this: 291 * var htmlEl = DwtUiEvent.getTargetWithProp(ev, "myProp"); 292 * var obj = DwtControl.findControl(htmlEl); 293 * 294 * Returns a control (DWT object) based on the event, by finding the event target with the 295 * given property and using its reference to a DWT object. 296 * 297 * @param ev [Event] DHTML event 298 * @param useRelatedTarget [boolean]* if true, return element that was related to this event; 299 */ 300 DwtUiEvent.getDwtObjWithProp = 301 function(ev, prop) { 302 var htmlEl = DwtUiEvent.getTargetWithProps(ev, ["dwtObj", prop]); 303 return htmlEl ? Dwt.getObjectFromElement(htmlEl) : null; 304 }; 305