/*----------------------------------------------------------------------------- Copyright (C) 2006 Menko Kroeske This file is part of Flamingo MapComponents. Flamingo MapComponents is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -----------------------------------------------------------------------------*/ /** @component Flamingo Framework * This class is the framework of Flamingo MapComponents. * It provides several methods to load, manage and control the (map)components. * A configuration file determines which components have to be loaded and how they interact with eachother. * @file flamingo.as (sourcefile) * @file flamingo.fla (sourcefile) * @file flamingo.swf (compiled framework, needed for publication on internet) * @file flamingo.xml (configurationfile for framework, needed for publication on internet) * @configstyle .tooltip Fontstyle for tooltips */ /* * Changes oct 2008 * In method raiseEvent * added: * ExternalInterface.call("dispatchEventJS",event_to_fire, arguments); * Author:Linda Vels,IDgis bv */ import flash.external.ExternalInterface; import flash.filters.DropShadowFilter; class Flamingo { private var version:String = "3.1.0 RC1"; //reference to main movie from which this class is loaded //at the main movie the components are loaded at 'moviedepth'-- ;moviedepth starts by 10000 //at the main movie a cursor movie is loaded at depth 50005 //at the main movie a tooltip movie can be loaded at depth 50004 //at the main movie an error movie can be loaded at depth 50003 //at the main movie a tracer movie can be loaded at depth 50002 //at the main movie a border movie can be loaded at depth 50001 //at the main movie a lock movie can be loaded at depth 50000 private var mFlamingo:MovieClip; //repository for storing custom information of every loaded component (per component id) private var components:Object; //repository for storing default information per component url private var components_per_url:Object; // //repository for storing xmls private var xmlpool:Object; //repository for storing configs private var configpool:Object; //default language setting //default tooltip delay //depth of first component private var moviedepth:Number; //filename of configfile private var useexternalinterface:Boolean; private var tooltipdelay:Number = 500; private var lang:String = "en"; private var width:String = "100%"; private var height:String = "100%"; private var tiptext:String; private var maxheight:Number; private var minheight:Number; private var maxwidth:Number; private var minwidth:Number; private var nocache:String; private var languages:String = "en"; private var resizeid:Number; private var backgroundcolor:Number; private var backgroundalpha:Number = 100; private var tooltipcolor:Number; private var tooltipshadow:Boolean; private var tooltipbordercolor:Number; private var bordercolor:Number; private var borderwidth:Number; private var borderalpha:Number = 100; private var flamingoid:String = ""; private var configs:Array; private var loading:Boolean; private var uniqueid:Number; private var rooturl:String; private var allowstrangers:Boolean; private var configloaded:Boolean; private var theloadlist:Array; private var isloadingcomponent:Boolean; private var callbacktype:String; private var nrconfigs:Number; //Flamingo class constructor //@param mc MovieClip public function Flamingo(mc:MovieClip) { //save base url of flamingo.swf var url = mc._url.split("?")[0]; if (url.indexOf("\\", 0)<0) { var a_url = url.split("/"); } else { var a_url = url.split("\\"); } a_url.pop(); this.rooturl = a_url.join("/"); // make it possible to communicate from a html page with flamingo through the callFlamingo function //ExternalInterface.addCallback("call", this, callMethod); ExternalInterface.addCallback("callMethod", this, callMethod); ExternalInterface.addCallback("setProperty", this, setProperty); ExternalInterface.addCallback("getProperty", this, getProperty); ExternalInterface.addCallback("call", this, callMethod); ExternalInterface.addCallback("set", this, setProperty); ExternalInterface.addCallback("get", this, getProperty); this.xmlpool = new Object(); this.configpool = new Object(); this.components = new Object(); this.components_per_url = new Object(); //add the flamingo object to the components list and components per url list this.components.flamingo = new Object(); this.components.flamingo.target = mc._target; this.components.flamingo.url = "flamingo"; this.components.flamingo.type = "flamingo"; // // //keep a reference to the movie this.mFlamingo = mc; //listener for Stage resize-event var flamingo:Object = this; var stageListener:Object = new Object(); stageListener.onResize = function() { clearInterval(flamingo.resizeid); flamingo.resizeid = setInterval(flamingo, "resize", 500); //flamingo.resize() }; //do some tricks with the Stage //Stage.showMenu = false; Stage.addListener(stageListener); Stage.scaleMode = "noScale"; Stage.align = "TL"; //add custom context menu var cm:ContextMenu = new ContextMenu(); cm.hideBuiltInItems(); cm.customItems.push(new ContextMenuItem("About Flamingo MapComponents "+this.version+"...", about)); _root.menu = cm; // //var keyListener:Object = new Object(); //keyListener.onKeyDown = function() { // 55 is key code for 7 //if (Key.getCode() == 116) { //flamingo.loadConfig(flamingo.configfile); //} //}; //Key.addListener(keyListener); //finally load default flamingo.xml //create movie for cursors this.init(); } private function init() { this.mFlamingo.strings = new Object(); this.mFlamingo.cursors = new Object(); this.mFlamingo.guides = new Object(); this.mFlamingo.styles = new TextField.StyleSheet(); this.mFlamingo.createEmptyMovieClip("flamingoCursors", 50005); this.mFlamingo.createEmptyMovieClip("flamingoBorder", 50001); this.useexternalinterface = true; this.moviedepth = 10000; this.tooltipdelay = 500; this.loading = false; this.lang = "en"; this.width = "100%"; this.height = "100%"; this.maxheight = undefined; this.minheight = undefined; this.maxwidth = undefined; this.minwidth = undefined; this.nocache = ""; this.languages = "en"; this.backgroundcolor = undefined; this.backgroundalpha = 100; this.tooltipcolor = 0xffffff; this.tooltipshadow = true; this.tooltipbordercolor = 0xcccccc; this.bordercolor = undefined; this.borderwidth = undefined; this.borderalpha = 100; this.flamingoid = ""; this.mFlamingo.width = "100%"; this.mFlamingo.height = "100%"; this.uniqueid = 1; this.configloaded = false; this.theloadlist = new Array(); this.isloadingcomponent = false; this.callbacktype = "id"; this.nrconfigs = 0; //------------------------------ //load default xml var thisObj = this; var xml:XML = new XML(); xml.ignoreWhite = true; xml.onLoad = function(success:Boolean) { if (success) { if (this.firstChild.nodeName.toLowerCase() == "flamingo") { thisObj.parseConfigXML(this); } } //get arguments at mFlamingo if (thisObj.mFlamingo.lang != undefined) { thisObj.lang = thisObj.mFlamingo.lang; delete thisObj.mFlamingo.lang; } if (thisObj.mFlamingo.config != undefined) { thisObj.loadConfig(thisObj.mFlamingo.config); delete thisObj.mFlamingo.config; } }; xml.load(this.correctUrl("flamingo.xml")); this.raiseEvent(this, "onInit"); } /** * Opens the internet page of flamingo-mc. */ public function about():Void { getURL("http://flamingo.gbo-provincies.nl", "_blank"); } /** * Resizes the application and fires the 'onResize' event. * This function is triggered by a resize of the stage. */ public function resize():Void { //the dimensions (__width and __height) are stored at the flamingo movie clearInterval(this.resizeid); var mFlamingo = this.getComponent("flamingo"); var h:Number = this.getAbs(mFlamingo.height, Stage.height-1); var w:Number = this.getAbs(mFlamingo.width, Stage.width-1); if (mFlamingo.minheight>0) { h = Math.max(mFlamingo.minheight, h); } if (mFlamingo.maxheight>0) { h = Math.min(mFlamingo.maxheight, h); } if (mFlamingo.maxwidth>0) { w = Math.min(mFlamingo.maxwidth, w); } if (mFlamingo.minwidth>0) { w = Math.max(mFlamingo.minwidth, w); } mFlamingo.__height = h; mFlamingo.__width = w; //log if (mFlamingo.mError != undefined) { mFlamingo.mError._x = (Stage.width/2); mFlamingo.mError._y = (Stage.height/2); } // mFlamingo.clear(); mFlamingo.beginFill(this.backgroundcolor, this.backgroundalpha); mFlamingo.moveTo(0, 0); mFlamingo.lineTo(mFlamingo.__width, 0); mFlamingo.lineTo(mFlamingo.__width, mFlamingo.__height); mFlamingo.lineTo(0, mFlamingo.__height); mFlamingo.lineTo(0, 0); mFlamingo.endFill(); mFlamingo.flamingoBorder.clear(); mFlamingo.flamingoBorder.lineStyle(this.borderwidth, this.bordercolor, this.borderalpha); mFlamingo.flamingoBorder.moveTo(0, 0); mFlamingo.flamingoBorder.lineTo(mFlamingo.__width, 0); mFlamingo.flamingoBorder.lineTo(mFlamingo.__width, mFlamingo.__height); mFlamingo.flamingoBorder.lineTo(0, mFlamingo.__height); mFlamingo.flamingoBorder.lineTo(0, 0); this.raiseEvent(this, "onResize", mFlamingo); //this.components.flamingo.broadcastMessage("onResize"); } /** * Checks if a configuration file is being loaded. * @return Boolean True if flamingo is busy loading a configuration. */ public function isLoading():Boolean { return (this.loading); } /** * Removes all loaded components and initilizes Flamingo for a fresh start. */ public function clear():Void { for (var id in this.components) { if (id != "flamingo") { this.killComponent(id); } } //refresh (remove) all old listeners AsBroadcaster.initialize(this.components["flamingo"]); this.init(); } /** * loads a xml-file in flamingo for later use. * @param file:String Filename */ public function loadXMLPool(file:String) { if (file == undefined) { //no file entered, quit return; } if (this.xmlpool[file] != undefined) { //file is already downloaded or is being downloaded, so quit return; } this.xmlpool[file] = new XML(); this.xmlpool[file].ignoreWhite = true; var flamingo = this; this.xmlpool[file].onLoad = function(success:Boolean) { if (success) { flamingo.raiseEvent(flamingo, "onLoadXMLPool", file); } else { flamingo.raiseEvent(flamingo, "onError", "LoadXMLPool", "Error opening '"+file+"'..."); flamingo.showError("Error: Flamingo.LoadXMLPool", "Error opening '"+file+"'..."); delete flamingo.xmlpool[file]; } }; this.xmlpool[file].load(getNocacheName(file, "second")); } /** * Removes a loaded xml-file from flamingo. * @param file:String [optional] Filename which will be removed. If omitted all files are removed. */ public function clearXMLPool(file:String) { // a clear is being performed with a delay // in the mean time other functions can still make use of the xml _global['setTimeout'](this, '_clearXMLPool', 2000, file); } private function _clearXMLPool(file:String) { if (file == undefined) { for (var id in this.xmlpool) { delete this.xmlpool[id]; } delete this.xmlpool; this.xmlpool = new Object(); } else { delete this.xmlpool[file]; } } /** * Gets a xml or a part from a xml from a loaded xml-file. * @param file:String Filename from which the xml will be retreived. * @param id:String [optional] Id of a node which will be retreived. If omitted the complete xml will be returned. */ public function getXMLfromPool(file:String, id:String):String { if (this.xmlpool[file] == undefined) { return; } if (id == undefined or id.length == 0) { return this.xmlpool[file].toString(); } else { var node = findNodeById(this.xmlpool[file].firstChild, id); this.addNameSpaces(node); return node.toString(); } } private function addNameSpaces(node:XMLNode) { if (node.getNamespaceForPrefix(node.prefix) != null) { node.attributes["xmlns:"+node.prefix] = node.getNamespaceForPrefix(node.prefix); } var childnodes = node.childNodes; for (var i = 0; i0) { var xml = flamingo.findNodeById(this.firstChild, id); flamingo.addComponent(xml, targetid); } else { flamingo.parseConfigXML(this); } } else { flamingo.raiseEvent(flamingo, "onError", "processConfig", "Error opening '"+file+"'..."); flamingo.showError("Error: Flamingo.processConfig", "Error opening '"+file+"'..."); flamingo.loading = false; flamingo.processConfig(); } }; this.configpool[file].load(getNocacheName(file, "second")); } else { //config already loaded if (id.length>0) { var xml = this.findNodeById(this.configpool[file].firstChild, id); flamingo.addComponent(xml, targetid); } else { //parse complete config this.parseConfigXML(this.configpool[file]); } } } else { this.raiseEvent(this, "onConfig", ""); if (id.length>0) { var xml = this.findNodeById(xml.firstChild, id); flamingo.addComponent(xml, targetid); } else { //parse complete config this.parseConfigXML(xml); } } } /** * Returns a filename with a unique argument so the application is forced to get this file fresh from a server. * @param filename:String Filename. * @param nocache:String [optional] reconized values: second, minute, hour, day, month, year * @return String Filename with a postfix. */ public function getNocacheName(filename:String, nocache:String):String { if (nocache == undefined) { nocache = "second"; } if (nocache.length == 0) { return filename; } if (_root._url.substr(0, 5).toLowerCase() == "file:") { return filename; } else { var postfix = ""; if (filename.indexOf("?")>0){ postfix="&"; }else{ postfix="?"; } var d:Date = new Date(); switch (nocache.toLowerCase()) { case "second" : postfix += "noCache="+d.getTime(); break; case "minute" : postfix += "noCache="+d.getFullYear()+"-"+d.getMonth()+"-"+d.getDate()+"-"+d.getHours()+"-"+d.getMinutes(); break; case "hour" : postfix += "noCache="+d.getFullYear()+"-"+d.getMonth()+"-"+d.getDate()+"-"+d.getHours(); break; case "day" : postfix += "noCache="+d.getFullYear()+"-"+d.getMonth()+"-"+d.getDate(); break; case "month" : postfix += "noCache="+d.getFullYear()+"-"+d.getMonth(); break; case "year" : postfix += "noCache="+d.getFullYear(); break; default : postfix += "noCache="+d.getTime(); } return filename+postfix; } } /** @tag * Each configuration file starts with the 'flamingo' node. This node is a good place to define the namespaces for the componentnodes. * @hierarchy root-node * @example * * ... * child tags * ... * * @attr tooltipdelay (defaultvalue "500") Time in milliseconds (1000 = 1 second) between showing a tooltip and moving the mouse over a component. * @attr lang (defaultvalue "en") The language of the application. * @attr languages (defaultvalue "en") Comma seperated list of 'lang' abbreviations. e.g. languages="en,nl,de" Flamingo will load these language strings. By default only english strings are loaded. When languages="" flamingo will load all available language strings. * @attr minwidth The minimum width of the application in pixels. * @attr maxwidth The maximum width of the application in pixels. * @attr maxheight The maximum height of the application in pixels. * @attr minheight The minimum height of the application in pixels. * @attr width (defaultvalue "100%") The width of the application. By default the application fills the available space of the flamingo.swf. This space is controled in the html page. * @attr height (defaultvalue "100%") The height of the application. By default the application fills the available space of the flamingo.swf. This space is controled in the html page. * @attr useexternalinterface (defaultvalue "true") If set to "true" flamingo will pass all events to the browser. And with javascript you can talk with Flamingo. * @attr bordercolor Color of a border arround the application in a hexadecimal notation. e.g. bordercolor="#00ff33" * @attr borderwidth Width of the border in pixels. If set to "0" (meaning 'hairline') or greater Flamingo will draw a border. * @attr borderalpha (defaultvalue "100") Transparency of border. Default is "100" meaning opaque. * @attr backgroundcolor Color of the backgound in hexadecimal notation. If set, Flamingo will have a background, otherwhise Flamingo's background is transparent. * @attr backgroundalpha (defaultvalue "100") Transparency of background if backgroundcolor is set. * @attr clear True or false. True: all existing components will be removed from the application. * @attr tooltipbordercolor (defaultvalue "#CCCCCC") Color of a border arround a tooltip in a hexadecimal notation. e.g. color="#00ff33" * @attr tooltipcolor (defaultvalue "#FFFFFF") Color of the background of a tooltip in a hexadecimal notation. e.g. color="#00ff33" * @attr tooltipshadow (defaultvalue "true") True or false. * @attr callbacktype (defaultvalue "id") The names of the events are composed as follows: [componenttype]_[eventname] e.g. Map_onMouseMove However if callbacktype = "id" , names of events are composed as follows: [componentid]_[eventname] e.g. myMap_onMouseMove * @attr allowstrangers (defaultvalue "false") True or false. False: only components with id's already loaded will load. True: all components load. For the first configuration allowstrangers is always true. */ private function parseConfigXML(xml:Object):Void { //parses the ini-xml var mFlamingo = this.getComponent("flamingo"); if (xml.firstChild.nodeName.toLowerCase() == "flamingo") { //defaults //retreive and convert the attributes for (var attr in xml.firstChild.attributes) { var val:String = xml.firstChild.attributes[attr]; switch (attr.toLowerCase()) { case "allowstrangers" : if (val.toLowerCase() == "true") { this.allowstrangers = true; } else { this.allowstrangers = false; } break; case "clear" : if (val.toLowerCase() == "true") { this.clear(); } break; case "callbacktype" : this.callbacktype = val.toLowerCase(); break; case "id" : this.flamingoid = val; break; case "bordercolor" : if (val.charAt(0) == "#") { this.bordercolor = Number("0x"+val.substring(1, val.length)); } else { this.bordercolor = Number(val); } break; case "backgroundcolor" : if (val.charAt(0) == "#") { this.backgroundcolor = Number("0x"+val.substring(1, val.length)); } else { this.backgroundcolor = Number(val); } break; case "tooltipbordercolor" : if (val.charAt(0) == "#") { this.tooltipbordercolor = Number("0x"+val.substring(1, val.length)); } else { this.tooltipbordercolor = Number(val); } break; case "tooltipcolor" : if (val.charAt(0) == "#") { this.tooltipcolor = Number("0x"+val.substring(1, val.length)); } else { this.tooltipcolor = Number(val); } break; case "borderwidth" : this.borderwidth = Number(val); break; case "borderalpha" : this.borderalpha = Number(val); break; case "backgroundalpha" : this.backgroundalpha = Number(val); break; case "nocache" : this.nocache = val; break; case "tooltipdelay" : this.tooltipdelay = Number(val); break; case "lang" : this.lang = val; break; case "languages" : this.languages = val; break; case "maxwidth" : mFlamingo.maxwidth = Number(val); break; case "minwidth" : mFlamingo.minwidth = Number(val); break; case "maxheight" : mFlamingo.maxheight = Number(val); break; case "minheight" : mFlamingo.minheight = Number(val); break; case "width" : mFlamingo.width = val; break; case "height" : mFlamingo.height = val; break; case "tooltipshadow" : if (val.toLowerCase() == "true") { this.tooltipshadow = true; } else { this.tooltipshadow = false; } break; case "useexternalinterface" : if (val.toLowerCase() == "true") { this.useexternalinterface = true; } else { this.useexternalinterface = false; } break; } } //gathered enough information for a proper resize this.resize(); var nodes = xml.firstChild.childNodes; var count = nodes.length; for (var i:Number = 0; i tag..."); this.showError("Error: Flamingo.parseConfigXML", "Please start xml with the tag..."); this.doneLoading(); } } public function addComponents(xml:Object):Void { if (typeof (xml) == "string") { xml = new XML(String(xml)).firstChild; } var xnode:Array = xml.childNodes; if (xnode.length>0) { for (var i:Number = 0; i add new movie //create e new movieclip var mc:MovieClip = this.mFlamingo.createEmptyMovieClip(targetid, this.moviedepth--); mc._visible = false; this.loadComponent(xml, mc, targetid); } else { //id already exists in componentslist > movie exists or is being loaded var type = xml.localName; if (type.indexOf(".", 0)>=0) { var a:Array = type.split("."); type = a.pop(); } //load component into existing component when type's are the same if (type == this.components[targetid].type) { var mc = getComponent(targetid); if (target == "") { //movieclip is being loaded this.components[targetid].xmls.push(xml); this.doneLoading(); } else { this.loadComponent(xml, mc, targetid); } } else { //id exists, but the config xml is a xml for another type of component this.raiseEvent(this, "onError", "addComponent", "The id '"+targetid+"' is already in use..."); this.showError("Error: Flamingo.addComponent", "The id '"+targetid+"' is already in use..."); this.doneLoading(); return; } } } /** * Loads a component and register it at the flamingo framework. This function should be used by components which can load other components. * A component has always a prefix. * @param xml:Object Xml-node describing the component. * @param mc:Movieclip movieclip at which the component will be loaded * @param targetid:String Id at which the component will be registered. */ public function loadComponent(xml:Object, mc:MovieClip, targetid:String):Void { //rule1: a component has a prefix and an id //rule2: a component can register only once, double ids are not allowed if (xml == undefined) { return; } if (mc == undefined) { return; } if (targetid == undefined) { return; } // if (xml instanceof XML) { xml = xml.firstChild; } if (xml.prefix.length == 0) { return; } // url= fmc/MyComponent type=MyComponent // url=fmc/Bundle type=MyComponent var file = xml.localName; var type = xml.localName; if (type.indexOf(".", 0)>=0) { var a:Array = type.split("."); type = a.pop(); file = a.join("."); } if (this.components[targetid].target != undefined and this.components[targetid].type != type) { this.raiseEvent(this, "onError", "loadComponent", "The id '"+targetid+"' is already in use..."); this.showError("Error: Flamingo.loadComponent", "The id '"+targetid+"' is already in use..."); this.doneLoading(); return; } if (this.components[targetid].target != undefined) { mc = eval(this.components[targetid].target); } if (this.components[targetid].type == type and mc.setConfig != undefined) { //component already exists and it can be configurated this.components[targetid].xmls.push(xml); mc.setConfig(xml); this.doneLoading(); //this.loadNextComponent(); } else { var url:String = this.correctUrl(xml.namespaceURI+"/"+file); if (url.length == 0) { return; } //component new or existing component has no setConfig, so treat as new component //add a reference for a component to the components object //save xml, target, url and parent in components object //if a component is loaded, its target should be known and registered > see loadComponent_source if (this.components[targetid] == undefined) { this.components[targetid] = new Object(); } this.components[targetid].target = ""; this.components[targetid].url = url; this.components[targetid].loaded = false; this.components[targetid].loader = new MovieClipLoader(); this.components[targetid].type = type; this.components[targetid].xmls = new Array(); this.components[targetid].xmls.push(xml); //climb in the tree and search a good parent //find component parent //component parent is the first parent movie that is registered in components //can be differ from the flash _parent!! var parentmc:MovieClip = mc._parent; while (parentmc != undefined) { if (parentmc._target == this.components.flamingo.target) { this.components[targetid].parent = "flamingo"; break; } if (this.components[parentmc._name].target != undefined) { this.components[targetid].parent = parentmc._name; break; } parentmc = parentmc._parent; } //this.loadComponent_defaults(url); this.loadComponent_source(url, targetid, mc); //get custom language, style and cursor definitions //this.theloadlist.push({url:url, targetid:targetid, mc:mc}); //this.loadNextComponent(); //this.loadComponent_defaults(url, targetid, mc); } } private function loadComponent_defaults(url:String) { //load xml belonging to the component and retreive strings,styles and cursors //load defaults once per component if (this.components_per_url[url] == undefined) { this.components_per_url[url] = new Object(); this.components_per_url[url].xml = new XML(); this.components_per_url[url].xml.ignoreWhite = true; this.components_per_url[url].xml.load(getNocacheName(url+".xml", this.nocache)); } } private function loadComponent_source(url:String, id:String, mc:MovieClip) { //load the actually component movie var thisObj = this; //var mcLoader:MovieClipLoader = new MovieClipLoader(); var mcLoader:MovieClipLoader = this.components[id].loader; var lLoader:Object = new Object(); //lLoader.onLoadProgress = function(mc:MovieClip, bytesLoaded:Number, bytesTotal:Number) { //thisObj.components[id].progress = "..."+Math.round(bytesLoaded/bytesTotal*100)+"%"; //}; lLoader.onLoadComplete = function(mc:MovieClip) { //At this point we can set variables of a movieclip but scripts of the clip are not yet executed yet //So we can set basic flamingo properties and store them at the movieclip itself //retreive the basic attributes from the xml and store them at the componentmovie //thisObj.parseComponentXML(thisObj.components[id].xml, mc); //thisObj.parseGuide(thisObj.components[id].xml, mc); // tell flamingo where this component can be found thisObj.components[id].target = mc._target; //thisObj.components.flamingo.broadcastMessage("onLoadComponent", thisObj, mc); }; lLoader.onLoadInit = function(mc:MovieClip) { thisObj.components[id].loaded = true; delete thisObj.components[id].loader; thisObj.raiseEvent(thisObj, "onLoadComponent", mc); thisObj.doneLoading(); //thisObj.isloadingcomponent = false; //thisObj.loadNextComponent(); }; lLoader.onLoadError = function(mc:MovieClip, error:String, httpStatus:Number) { this.raiseEvent(this, "onError", "loadComponent_source", url+".swf\n"+error); thisObj.showError("Error: Flamingo.loadComponent_source", url+".swf\n"+error); thisObj.doneLoading(); delete thisObj.components[id].componentloader; //thisObj.isloadingcomponent = false; //thisObj.loadNextComponent(); }; mcLoader.addListener(lLoader); mcLoader.loadClip(getNocacheName(url+".swf", this.nocache), mc); } private function doneLoading():Void { //trace("----------------------------------------"); // this function is called after a component is loaded var nrloaded:Number = 0; var nrtotal:Number = 0; for (var id in this.components) { if (id != "flamingo") { //trace(id+this.components[id].target+","+this.components[id].init); if (this.components[id].loaded != undefined) { nrtotal++; if (this.components[id].loaded) { nrloaded++; } } } } var p = Math.round(nrloaded/nrtotal*100); this.raiseEvent(this, "onConfigProgress", nrloaded, nrtotal, (this.nrconfigs-configs.length), this.nrconfigs); //trace(nrloaded +"=="+nrtotal) if (nrloaded == nrtotal) { this.loading = false; this.configloaded = true; this.processConfig(); //_global['setTimeout'](this, 'processConfig', 100); } } /** @tag <{component}> * The Flamingo Framework will parse these (default) attributes for each component in the configuration file. * @attr id Unique identifier. Usefull when components have to listen to eachother. * @attr name Name * @attr width Width of a component. In pixels or percentage. e.g. width="100" or width="100%" * @attr height Height of a component. In pixels or percentage. e.g. height="100" or height="100%" * @attr left Left position of a component, can be a number (left="50"), a percentage (left="50%") or a guideid (left="mx"). There are four intrinsic guides: "left", "right" and "top", "bottom". The value can be followed by a space and an offset number. Examples: left="50" , right="50%", xcenter="mx", left="mx -2", xcenter="50% 10". * @attr right Right position of a component. See left. * @attr top Top position of a component. See left. * @attr bottom Bottom position of a component. See left. * @attr xcenter Vertical center position of a component. See left. * @attr ycenter Horizontal center position of a component. See left. * @attr listento Comma seperated list of component id's. See the component documentation if this attribute is supported and to which components a component can listen. * @attr visible Visiblity of the component. Reconized values: "true" and "false" * @attr maxwidth Maximum width of a component in pixels. * @attr minwidth Minimum width of a component in pixels. * @attr maxheight Maximum height of a component in pixels. * @attr minheight Minimum height of a component in pixels. */ /** * Parses the default flamingo attributes and stores them at the components movieclip. * @param comp:Object Id or MovieClip representing the component. * @param xml:XML Xml which have to be parsed. */ public function parseXML(comp:Object, xml:XML):Void { if (xml == undefined) { return; } var id:String = this.getId(comp); if (id == undefined) { return; } var mc = this.getComponent(id); //default flamingo attributes if (mc.visible == undefined) { mc.visible = true; } for (var attr in xml.attributes) { var attr:String = attr.toLowerCase(); var val:String = xml.attributes[attr]; switch (attr) { case "name" : mc.name = val; break; case "width" : mc.width = val; break; case "height" : mc.height = val; break; case "left" : mc.left = val; break; case "right" : mc.right = val; break; case "top" : mc.top = val; break; case "bottom" : mc.bottom = val; break; case "xcenter" : mc.xcenter = val; break; case "ycenter" : mc.ycenter = val; break; case "listento" : if (val.length>0) { mc.listento = this.asArray(val); } break; case "visible" : if (val.toLowerCase() == "false") { mc.visible = false; mc._visible = false; } else { mc.visible = true; mc._visible = true; } break; case "maxwidth" : mc.maxwidth = Number(val); break; case "minwidth" : mc.minwidth = Number(val); break; case "maxheight" : mc.maxheight = Number(val); break; case "minheight" : mc.minheight = Number(val); break; } } //parse strings,cursors, styles, guides if (mc.strings == undefined) { mc.strings = new Object(); } if (mc.cursors == undefined) { mc.cursors = new Object(); } if (mc.styles == undefined) { mc.styles = new TextField.StyleSheet(); } if (mc.guides == undefined) { mc.guides = new Object(); } var nodes = xml.childNodes; var count = nodes.length; for (var i:Number = 0; i * With cursor you can add custom cursors to Flamingo. This tag can be situated in the configuration file of a component or in the configuration file of an application. * @hierarchy child-node of or child-node of * @attr id Unique identifier. See the components documentation at 'Cursor id's' for supported id's. * @attr xoffset Offset in pixels of the cursor's hotspot. By default this is on the upperleft of the cursor. When using a swf as a cursor, the hotspot can be defined in the swf. * @attr yoffset See xoffset. * @attr url The filename of the swf, png or jpg which contains the cursor. When using relative filenames, the path is always relative to flamingo.swf * @attr linkageid The linkageid of the cursor when it is situated in the library. */ /** * Gets cursor information from a xml-node and stores it at an object. * @param xml:XML Xml which have to be parsed. * @param cursors:Object Object at which the cursors are stored. * @return Boolean True if a cursor is found, False if there are no cursors. */ public function setCursor(xml:Object, cursors:Object):Boolean { //searches for cursornodes, loads cursors in the mCursor movie if (typeof (xml) == "string") { xml = new XML(String(xml)).firstChild; } if (xml == undefined) { return; } var b:Boolean = false; if (xml.nodeName.toLowerCase() == "cursor") { var id:String; var url:String; var obj = new Object(); for (var attr in xml.attributes) { var val:String = xml.attributes[attr]; switch (attr.toLowerCase()) { case "id" : id = val.toLowerCase(); break; case "xoffset" : obj.dx = Number(val); break; case "yoffset" : obj.dy = Number(val); break; case "url" : url = this.correctUrl(val); break; case "linkageid" : obj.linkageid = val; break; } } if (id.length>0 and url.length>0) { var cursormovie:String; for (var attr in this.mFlamingo.flamingoCursors) { if (this.mFlamingo.flamingoCursors[attr].url == url) { cursormovie = attr; break; } } if (cursormovie == undefined) { var cursormovie = "cursor_"+this.mFlamingo.flamingoCursors.getNextHighestDepth(); var mc:MovieClip = this.mFlamingo.flamingoCursors.createEmptyMovieClip(cursormovie, this.mFlamingo.flamingoCursors.getNextHighestDepth()); //mc._x = dx; //mc._y = dy; mc.url = url; var mcLoader:MovieClipLoader = new MovieClipLoader(); var lLoader:Object = new Object(); lLoader.onLoadInit = function(mc:MovieClip) { mc._visible = false; }; lLoader.onLoadError = function(mc:MovieClip, error:String, httpStatus:Number) { mc.removeMovieClip(); }; mcLoader.addListener(lLoader); mcLoader.loadClip(getNocacheName(url, this.nocache), mc); } obj.movie = cursormovie; cursors[id] = obj; b = true; } } return (b); } /** @tag * With string you can add multi-language support to flamingo. This tag can be situated in the configuration file of a component or in the configuration file of an application. * @hierarchy child-node of or child-node of * @example * * * * * * @attr id Unique identifier. See the components documentation for supported string id's. * @attr {lang} You can define your own 'lang' attributes, followed by the correct string. See example. */ /** * Gets string information from a xml-node and stores it at a language-object. * @param xml:XML Xml which have to be parsed. * @param language:Object Object at which the strings are stored. * @return Boolean True if a string is found, False if not. */ public function setString(xml:Object, language:Object):Boolean { //posibilities // //or // // a label //een label //ein label // // or a combination of both //searches for language nodes and store them in a language object // make helperobject for loading only languages in languagesstring if (typeof (xml) == "string") { xml = new XML(String(xml)).firstChild; } if (xml == undefined) { return; } var a_languages:Array = this.asArray(this.languages.toLowerCase()); var langs:Object; if (this.languages.length>0) { langs = new Object(); for (var j:Number = 0; j0) { //get only the languages in the languageobj if (langs[attr.toLowerCase()] != undefined) { obj[attr.toLowerCase()] = val; b = true; } } else { //get all obj[attr.toLowerCase()] = val; b = true; } break; } } if (id.length>0) { // search for next nodes // the next nodes in a string tag are language nodes for (j=0; j0) { if (langs[l] != undefined) { obj[l] = val; b = true; } } else { obj[l] = val; b = true; } } language[id] = new Object(); language[id] = obj; } delete obj; } return (b); } /** @tag