/**
* v.1.2 changes
*
* - switched the js engine singleton -> class (for more changes info read the js file)
* - SWF_ID property added
* - js methods rewritten
*
* v.1.1 changes
*
* - increase in performance for setters using multithreading (setTimeout hack)
* - method setWidth() renamed to setSWFWidth
* - method getWidth() renamed to getSWFWidth
* - method setHeight() renamed to setSWFHeight
* - method getHeight() renamed to getSWFHeight
* - SWFSizeEvent now passes six more properties
*/
package com.chargedweb.swfsize
{
import flash.errors.IllegalOperationError;
import flash.events.EventDispatcher;
import flash.events.TimerEvent;
import flash.external.ExternalInterface;
import flash.utils.Timer;
/**
* SWFSize class gives you the ability to:
* <ul>
* <li>control the swf's container metrics;</li>
* <li>gather browser's window metrics & position;</li>
* <li>control the browser's native scrollbars.</li>
* </ul>
* @example The following code initializes the SWFSize and when the <code>SWFSizeEvent.INIT</code> is dispatched
* retrieves browser's window coordinates and metrics:
* <listing version="3.0">
* // import the SWFSize api
* import com.chargedweb.swfsize.SWFSize;
* import com.chargedweb.swfsize.SWFSizeEvent;
*
* // initialize SWFSize
* SWFSize.SWF_ID = stage.loaderInfo.parameters.swfsizeId;
* var swfSizer:SWFSize = SWFSize.getInstance();
* swfSizer.addEventListener(SWFSizeEvent.INIT, onSWFSizeInit);
*
* function onSWFSizeInit(event:SWFSizeEvent):void<br>
* {
* // your code logic goes here
* // eg: retrieve window coordinates and metrics on init
* trace(event.topY, event.bottomY, event.leftX, event.rightX);
* trace(swfSizer.windowWidth, swfSizer.windowHeight);
* }
* </listing>
*
* @see SWFSizeEvent
*/
public class SWFSize extends EventDispatcher
{
/**
* The swf id defined in the html code; you habe to define it first;
* from your application
*/
public static var SWF_ID:String;
private static var METHOD_INIT:String = "SWFSizePool.getItemById('%id%').init";
private static var METHOD_SET_SCROLL_X:String = "SWFSizePool.getItemById('%id%').setScrollX";
private static var METHOD_SET_SCROLL_Y:String = "SWFSizePool.getItemById('%id%').setScrollY";
private static var METHOD_GET_SCROLL_X:String = "SWFSizePool.getItemById('%id%').getScrollX";
private static var METHOD_GET_SCROLL_Y:String = "SWFSizePool.getItemById('%id%').getScrollY";
private static var METHOD_SET_SWF_WIDTH:String = "SWFSizePool.getItemById('%id%').setSWFWidth";
private static var METHOD_SET_SWF_HEIGHT:String = "SWFSizePool.getItemById('%id%').setSWFHeight";
private static var METHOD_GET_SWF_WIDTH:String = "SWFSizePool.getItemById('%id%').getSWFWidth";
private static var METHOD_GET_SWF_HEIGHT:String = "SWFSizePool.getItemById('%id%').geSWFtHeight";
private static var METHOD_GET_WINDOW_WIDTH:String = "SWFSizePool.getItemById('%id%').getWindowWidth";
private static var METHOD_GET_WINDOW_HEIGHT:String = "SWFSizePool.getItemById('%id%').getWindowHeight";
private static var METHOD_GET_LEFT_X:String = "SWFSizePool.getItemById('%id%').getLeftX";
private static var METHOD_GET_RIGHT_X:String = "SWFSizePool.getItemById('%id%').getRightX";
private static var METHOD_GET_TOP_Y:String = "SWFSizePool.getItemById('%id%').getTopY";
private static var METHOD_GET_BOTTOM_Y:String = "SWFSizePool.getItemById('%id%').getBottomY";
private static const TYPE_ABSOLUTE:String = "px";
private static const TYPE_RELATIVE:String = "%";
private static var INSTANCE:SWFSize = null;
private var _topY:Number = 0;
private var _botY:Number = 0;
private var _leftX:Number = 0;
private var _rightX:Number = 0;
private var _scrollX:Number = 0;
private var _scrollY:Number = 0;
private var _swfWidth:Object = {value: 0, absolute: true};
private var _swfHeight:Object = {value: 0, absolute: true};
private var _windowWidth:Number = 0;
private var _windowHeight:Number = 0;
private var valueType:String;
private var available:Boolean = ExternalInterface.available;
private var initTimer:Timer = new Timer(50);
private var initResult:int = 0;
private var JSRawResult:String;
/**
* @throws IllegalOperationError The class cannot be instantiated.
*/
public function SWFSize(key:SWFSizeKey = null)
{
super();
if(!key || !(key is SWFSizeKey)) throw new IllegalOperationError('SWFSize cannot be instantiated.');
}
/**
* Singleton construction
* @return SWFSize
*/
public static function getInstance():SWFSize
{
if (!INSTANCE) INSTANCE = new SWFSize(new SWFSizeKey()); INSTANCE.init();
return INSTANCE;
}
/**
* Fits the swf's width value to browser's available width
* @param always:Boolean if set to true makes the swf's width property elastic @default false
* @return nothing
*/
public function autoSizeWidth(always:Boolean = false):void
{
if(always)
setSWFWidth(100, false);
else
setSWFWidth(windowWidth, true);
}
/**
* Fits the swf's height value to browser's available height
* @param always:Boolean if set to true makes the swf's height property elastic @default false
* @return nothing
*/
public function autoSizeHeight(always:Boolean = false):void
{
if(always)
setSWFHeight(100, false);
else
setSWFHeight(windowHeight, true);
}
/**
* Fits the swf's width and height values to browser available width and height
* @param always:Boolean if set to true makes the swf's width and height properties elastic @default false
* @return nothing
*/
public function autoSize(always:Boolean = false):void
{
if (available)
{
if (always)
{
setSWFWidth(100, false);
setSWFHeight(100, false);
}else {
setSWFWidth(windowWidth, true);
setSWFHeight(windowHeight, true);
}
}
}
/**
* Sets the width property of the swf container
* @param value:Number new width value
* @param absolute:Boolean whether the value is absolute or relative (%) @default true
* @return nothing
*/
public function setSWFWidth(value:Number, absolute:Boolean = true):void
{
valueType = (absolute) ? TYPE_ABSOLUTE : TYPE_RELATIVE;
if (available) callJSMethod(METHOD_SET_SWF_WIDTH, value, valueType);
}
/**
* Returns the current width value of the swf container
* @return Object { value:Number, absolute:Boolean };
*/
public function getSWFWidth():Object
{
return _swfWidth;
}
/**
* Sets the height property of the swf container
* @param value:Number new height value
* @param absolute:Boolean whether the value is absolute or relative (%) @default true
* @return nothing
*/
public function setSWFHeight(value:Number, absolute:Boolean = true):void
{
valueType = (absolute) ? TYPE_ABSOLUTE : TYPE_RELATIVE;
if (available) callJSMethod(METHOD_SET_SWF_HEIGHT, value, valueType);
}
/**
* Returns the current height value of the swf container
* @return Object { value:Number, absolute:Boolean };
*/
public function getSWFHeight():Object
{
return _swfHeight;
}
/**
* Returns the current available browser window width
* @return Number
*/
public function get windowWidth():Number
{
return _windowWidth;
}
/**
* Returns the current available browser window height
* @return Number
*/
public function get windowHeight():Number
{
return _windowHeight;
}
/**
* Returns the current leftX coordinate i.e. the relative x '0' coordinate of the browser
* @return Number current leftX coordinate
*/
public function get leftX():Number
{
return _leftX;
}
/**
* Returns the current rightX coordinate i.e. equals to leftX + windowWidth
* @return Number current rightX coordinate
*/
public function get rightX():Number
{
return _rightX;
}
/**
* Returns the current topY coordinate i.e. the relative y '0' coordinate of the browser
* @return Number current topY coordinate
*/
public function get topY():Number
{
return _topY;
}
/**
* Returns the current bottomY coordinate i.e. equals to topY + windowHeight
* @return Number current bottomY coordinate
*/
public function get bottomY():Number
{
return _botY;
}
/**
* {set/get} Scrolls the window to the X-axis to a specified value of pixels
* @param value:Number amount of pixels to scroll horizontally
* @return Number the current horizontal scroll amount
*/
public function set scrollX(value:Number):void
{
if (available) callJSMethod(METHOD_SET_SCROLL_X, value);
}
public function get scrollX():Number
{
return _scrollX;
}
/**
* {set/get} Scrolls the window to the Y-axis to a specified value of pixels
* @param value:Number amount of pixels to scroll vertically
* @return Number the current vertical scroll amount
*/
public function set scrollY(value:Number):void
{
if (available) callJSMethod(METHOD_SET_SCROLL_Y, value);
}
public function get scrollY():Number
{
return _scrollY;
}
/**
* @private Initializes the callbacks
* @return nothing
*/
private function init():void
{
if (!SWF_ID) throw new Error("SWF_ID not defined !");
if (available)
{
METHOD_INIT = METHOD_INIT.replace("%id%", SWF_ID);
METHOD_SET_SCROLL_X = METHOD_SET_SCROLL_X.replace("%id%", SWF_ID);
METHOD_SET_SCROLL_Y = METHOD_SET_SCROLL_Y.replace("%id%", SWF_ID);
METHOD_GET_SCROLL_X = METHOD_GET_SCROLL_X.replace("%id%", SWF_ID);
METHOD_GET_SCROLL_Y = METHOD_GET_SCROLL_Y.replace("%id%", SWF_ID);
METHOD_SET_SWF_WIDTH = METHOD_SET_SWF_WIDTH.replace("%id%", SWF_ID);
METHOD_SET_SWF_HEIGHT = METHOD_SET_SWF_HEIGHT.replace("%id%", SWF_ID);
METHOD_GET_SWF_WIDTH = METHOD_GET_SWF_WIDTH.replace("%id%", SWF_ID);
METHOD_GET_SWF_HEIGHT = METHOD_GET_SWF_HEIGHT.replace("%id%", SWF_ID);
METHOD_GET_WINDOW_WIDTH = METHOD_GET_WINDOW_WIDTH.replace("%id%", SWF_ID);
METHOD_GET_WINDOW_HEIGHT = METHOD_GET_WINDOW_HEIGHT.replace("%id%", SWF_ID);
METHOD_GET_LEFT_X = METHOD_GET_LEFT_X.replace("%id%", SWF_ID);
METHOD_GET_RIGHT_X = METHOD_GET_RIGHT_X.replace("%id%", SWF_ID);
METHOD_GET_TOP_Y = METHOD_GET_TOP_Y.replace("%id%", SWF_ID);
METHOD_GET_BOTTOM_Y = METHOD_GET_BOTTOM_Y.replace("%id%", SWF_ID);
ExternalInterface.addCallback("onWindowInit", onWindowInitHandler);
ExternalInterface.addCallback("onWindowScroll", onWindowScrollHandler);
ExternalInterface.addCallback("onWindowResize", onWindowResizeHandler);
if (initResult == 0)
{
initTimer.addEventListener(TimerEvent.TIMER, onInitTimerHandler);
initTimer.start();
}
}
}
/**
* @private Forces the initialization of the SWFSize js lib {opera hack}; i HATE opera;
* @param event:TimerEvent
*/
private function onInitTimerHandler(event:TimerEvent):void
{
initResult = int(String(ExternalInterface.call(METHOD_INIT)));
if (initResult == 1)
{
initTimer.stop();
initTimer.removeEventListener(TimerEvent.TIMER, onInitTimerHandler);
initTimer = null;
}
}
/**
* @private On window init handler
* @param event:String passed params
*/
private function onWindowInitHandler(event:String):void
{
parseEventData(event);
dispatchEvent(new SWFSizeEvent(SWFSizeEvent.INIT,
_leftX,
_rightX,
_topY,
_botY,
_windowWidth,
_windowHeight,
_swfWidth,
_swfHeight,
_scrollX,
_scrollY));
}
/**
* @private On window scroll handler
* @param event:String passed params
*/
private function onWindowScrollHandler(event:String):void
{
parseEventData(event);
dispatchEvent(new SWFSizeEvent(SWFSizeEvent.SCROLL,
_leftX,
_rightX,
_topY,
_botY,
_windowWidth,
_windowHeight,
_swfWidth,
_swfHeight,
_scrollX,
_scrollY));
}
/**
* @private On window resize handler
* @param event:String passed params
*/
private function onWindowResizeHandler(event:String):void
{
parseEventData(event);
dispatchEvent(new SWFSizeEvent(SWFSizeEvent.RESIZE,
_leftX,
_rightX,
_topY,
_botY,
_windowWidth,
_windowHeight,
_swfWidth,
_swfHeight,
_scrollX,
_scrollY));
}
/**
* @private Parses the event data
* @param event:String js event data
* @return nothing
*/
private function parseEventData(event:String):void
{
var eventData:Array = event.split(",");
_topY = Number(eventData[0]);
_botY = Number(eventData[1]);
_leftX = Number(eventData[2]);
_rightX = Number(eventData[3]);
_windowWidth = Number(eventData[4]);
_windowHeight = Number(eventData[5]);
_swfWidth = toSWFMetrics(eventData[6]);
_swfHeight = toSWFMetrics(eventData[7]);
_scrollX = Number(eventData[8]);
_scrollY = Number(eventData[9]);
}
/**
* @private Converts a value to a swf metrics object
* @param value:String value to convert
* @return Object swf metrics object
*/
private function toSWFMetrics(value:String):Object
{
var result:Object = {};
result.value = Number(value.split(TYPE_RELATIVE).join(""));
result.absolute = (value.indexOf(TYPE_RELATIVE) < 0);
return result;
}
/**
* @private Call js method using multithreading
* @param jsMethod:String js method name to be called
* @param ...params:* params to apply to the called js method
*/
private function callJSMethod(jsMethod:String, ...params):void
{
var n:int = params.length;
var jsCall:String = "%method%(%params%)";
var jsParams:String = "";
for(var i:int = 0; i < n; i++) jsParams += (i == n-1) ? "'"+params[i]+"'" : "'"+params[i]+"',";
jsCall = jsCall.replace("%method%", jsMethod);
jsCall = jsCall.replace("%params%", jsParams);
if(available) ExternalInterface.call("setTimeout", jsCall, 0);
}
}
}
internal class SWFSizeKey { };