blob: 65c339982b80c6ed858e2a9e898aa96d0c2c6d07 [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package org.apache.royale.core
{
import org.apache.royale.events.IEventDispatcher;
COMPILE::SWF
{
import flash.display.Sprite;
}
COMPILE::JS
{
import org.apache.royale.events.Event;
import org.apache.royale.events.BrowserEvent;
import org.apache.royale.events.IBrowserEvent;
import org.apache.royale.events.ElementEvents;
import org.apache.royale.events.EventDispatcher;
import goog.events;
import goog.events.BrowserEvent;
import goog.events.EventTarget;
import org.apache.royale.events.utils.EventUtils;
import org.apache.royale.utils.beads.sendLookupNotifications;
import org.apache.royale.utils.beads.insertInterests;
import org.apache.royale.utils.beads.removeInterests;
}
COMPILE::SWF
public class HTMLElementWrapper extends Sprite
{
/**
* "abstract" method so we can override in JS
* @param bead The new bead.
*/
public function addBead(bead:IBead):void
{
}
}
COMPILE::JS
public class HTMLElementWrapper extends EventDispatcher implements IStrand
{
//--------------------------------------
// Static Function
//--------------------------------------
/**
* @param listener The listener object to call {goog.events.Listener}.
* @param eventObject The event object to pass to the listener.
* @return Result of listener.
*/
static public function fireListenerOverride(listener:Object, eventObject:goog.events.BrowserEvent):Boolean
{
var e:IBrowserEvent;
var nativeEvent:Object = eventObject.getBrowserEvent();
var converter:Object = converterMap[nativeEvent.constructor.name];
if (converter)
e = converter["convert"](nativeEvent);
else
e = new org.apache.royale.events.BrowserEvent();
e.wrapEvent(eventObject);
return HTMLElementWrapper.googFireListener(listener, e);
}
/**
* @royalesuppresspublicvarwarning
*/
static public var converterMap:Object = {};
/**
* Static initializer
*/
static public function installOverride():Boolean
{
HTMLElementWrapper.googFireListener = goog.events.fireListener;
goog.events.fireListener = HTMLElementWrapper.fireListenerOverride;
return true;
}
//--------------------------------------
// Static Property
//--------------------------------------
/**
* The original fireListener.
*
* @royalesuppresspublicvarwarning
*/
static public var googFireListener:Function;
/**
* The properties that triggers the static initializer.
* Note, in JS, this property has to be declared
* after the installOverride.
*
* @royalesuppresspublicvarwarning
*/
static public var installedOverride:Boolean = installOverride();
//--------------------------------------
// Property
//--------------------------------------
private var _element:WrappedHTMLElement;
public function get element():WrappedHTMLElement
{
return _element;
}
public function set element(value:WrappedHTMLElement):void
{
_element = value;
_element.royale_wrapper = this;
}
/**
* allow access from overrides
*/
protected var _model:Object;
/**
* @royaleignorecoercion Class
* @royaleignorecoercion org.apache.royale.core.IBeadModel
*/
public function get model():Object
{
if (_model == null)
{
// addbead will set _model
var m:Class = org.apache.royale.core.ValuesManager.valuesImpl.
getValue(this, 'iBeadModel') as Class;
var b:IBeadModel = new m() as IBeadModel;
addBead(b);
}
return _model;
}
/**
* @royaleignorecoercion org.apache.royale.core.IBead
*/
[Bindable("modelChanged")]
public function set model(value:Object):void
{
if (_model != value)
{
if (value is IBead)
addBead(value as IBead);
else
_model = value;
dispatchEvent(new org.apache.royale.events.Event("modelChanged"));
}
}
protected var _beads:Vector.<IBead>;
//--------------------------------------
// Function
//--------------------------------------
/**
* @param bead The new bead.
* @royaleignorecoercion org.apache.royale.core.IBeadModel
*/
public function addBead(bead:IBead):void
{
if (!_beads)
{
_beads = new Vector.<IBead>();
}
_beads.push(bead);
if (bead is IBeadModel)
{
_model = bead as IBeadModel;
}
bead.strand = this;
insertInterests(beadLookup,bead);
}
/**
* @param classOrInterface The requested bead type.
* @return The bead.
*/
public function getBeadByType(classOrInterface:Class):IBead
{
var bead:IBead, i:uint, n:uint;
if (!_beads) return null;
n = _beads.length;
for (i = 0; i < n; i++)
{
bead = _beads[i];
if (bead is classOrInterface)
{
return bead;
}
}
return null;
}
/**
* @param bead The bead to remove.
* @return The bead.
*/
public function removeBead(bead:IBead):IBead
{
var i:uint, n:uint, value:Object;
n = _beads.length;
for (i = 0; i < n; i++)
{
value = _beads[i];
if (bead === value)
{
_beads.splice(i, 1);
removeInterests(beadLookup,bead);
bead.strand = null;
return bead;
}
}
return null;
}
override public function addEventListener(type:String, handler:Function, opt_capture:Boolean = false, opt_handlerScope:Object = null):void
{
var source:Object = getActualDispatcher_(type);
goog.events.listen(source, type, handler);
}
override public function removeEventListener(type:String, handler:Function, opt_capture:Boolean = false, opt_handlerScope:Object = null):void
{
var source:Object = getActualDispatcher_(type);
goog.events.unlisten(source, type, handler);
}
private function getActualDispatcher_(type:String):Object
{
var source:Object = this;
if (ElementEvents.elementEvents[type]) {
// mouse and keyboard events also dispatch off the element.
source = this.element;
}
return source;
}
override public function hasEventListener(type:String):Boolean
{
var source:Object = this.getActualDispatcher_(type);
return goog.events.hasListener(source, type);
}
/**
* @royaleignorecoercion String
*/
override public function dispatchEvent(e:Object):Boolean
{
var eventType:String = "";
if (typeof(e) === 'string')
{
eventType = e as String;
if (e === org.apache.royale.events.Event.CHANGE)
{
e = EventUtils.createEvent(eventType, e.bubbles);
}
}
else
{
eventType = e.type;
if (ElementEvents.elementEvents[eventType])
{
e = EventUtils.createEvent(eventType, e.bubbles);
}
}
var source:Object = this.getActualDispatcher_(eventType);
if (e.bubbles) {
return dispatchBubblingEvent(source, e);
}
if (source == this)
{
return super.dispatchEvent(e);
}
return source.dispatchEvent(e);
}
/**
* @royaleignorecoercion org.apache.royale.events.IEventDispatcher
*/
public function dispatchBubblingEvent(source:Object, e:Object):Boolean
{
// build the ancestors tree without setting the actual parentEventTarget
var ancestorsTree:Array = [];
var t:IEventDispatcher = source["parent"] as IEventDispatcher;
while (t != null) {
ancestorsTree.push(t);
t = t["parent"] as IEventDispatcher;
}
return goog.events.EventTarget.dispatchEventInternal_(source, e, ancestorsTree);
}
/**
* The beadLookup keeps references to beads using their notification interests
*/
protected var beadLookup:Object = {};
/**
* Sends a notification instance.
*
* @langversion 3.0
* @playerversion Flash 10.2
* @playerversion AIR 2.6
* @productversion Royale 0.9.6
*/
public function sendNotification(notification:INotification):void{
sendLookupNotifications(beadLookup,notification);
}
/**
* Simplified method for sending notifications.
* Use when body is not significant.
*
* @langversion 3.0
* @playerversion Flash 10.2
* @playerversion AIR 2.6
* @productversion Royale 0.9.6
*/
public function notify(message:String):void{
var notification:INotification = new Notification(message);
sendNotification(notification);
}
}
}