Access of undefined property error in Flash using ExternalInterface - javascript

I am new to flash, so the solution to this problem may be simple. Unfortunately I have been unable to find a working solution, so I am hoping you guys can help. I am developing a site using 3rd party flash - Coverflow, for an album. It looks great and you can download it here: http://www.weberdesignlabs.com/blog/2009/12/flash-10-coverflow/. My challenge is that I want to progress the albums from a Javascript call within my HTML. In my search I have discovered ExternalInterface, but I can't get it to work. When I try to export the movie I get an "Access of undefined property gotoCoverFlowItem" error.
Below follows the code contained in the Coverflow.ai file which I am trying to modify, with the modification in it. The full code can be found at the link above. I am using the Flash 10 version.
////////////////////////////////////////////
// Project: Flash 10 Coverflow
// Date: 10/3/09
// Author: Stephen Weber
////////////////////////////////////////////
package {
////////////////////////////////////////////
// IMPORTS
////////////////////////////////////////////
import flash.display.Sprite;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.MovieClip;
import flash.display.BlendMode;
import flash.display.Loader;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.events.IOErrorEvent;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.geom.ColorTransform;
import flash.net.URLRequest;
import flash.net.URLLoader;
import flash.net.navigateToURL;
import flash.display.Stage;
import flash.utils.setTimeout;
import flash.external.ExternalInterface;
//TweenLite - Tweening Engine - SOURCE: http://blog.greensock.com/tweenliteas3/
import com.greensock.*;
import com.greensock.easing.*;
import com.greensock.plugins.*;
public class Coverflow extends Sprite {
////////////////////////////////////////////
// VARIABLES
////////////////////////////////////////////
// size of the stage
private var sw:Number;
private var sh:Number;
private var background:Background;
// padding between each cover, can be customed via xml
private var coverflowSpacing:Number=30;
// transition time for movement
private var transitionTime:Number=0.75;
// the center of the stage
private var centerX:Number;
private var centerY:Number;
// store each image cover's instance
private var coverArray:Array=new Array();
// title of each image
private var coverLabel:CoverflowTitle = new CoverflowTitle();
// the slider under the image cover
private var coverSlider:Scrollbar;
// how many image covers
private var coverflowItemsTotal:Number;
// how to open the link
private var _target:String;
// size of the image cover
private var coverflowImageWidth:Number;
private var coverflowImageHeight:Number;
//Holds the objects in the data array
private var _data:Array = new Array();
// the y position of the item's title
private var coverLabelPositionY:Number;
//Z Position of Current CoverflowItem
private var centerCoverflowZPosition:Number=-125;
// display the middle of the cover or not
private var startIndexInCenter:Boolean=true;
// which cover to display in the beginning
private var startIndex:Number=0;
// the slide's Y position
private var coverSlidePositionY:Number;
//Holder for current CoverflowItem
private var _currentCover:Number;
//CoverflowItem Container
private var coverflowItemContainer:Sprite = new Sprite();
//XML Loading
private var coverflowXMLLoader:URLLoader;
//XML
private var coverflowXML:XML;
// the image cover's white border padding
private var padding:Number=4;
// stage reference
private var _stage:Stage;
//reflection
private var reflection:Reflect;
//Reflection Properties
private var reflectionAlpha:Number;
private var reflectionRatio:Number;
private var reflectionDistance:Number;
private var reflectionUpdateTime:Number;
private var reflectionDropoff:Number;
////////////////////////////////////////////
// CONSTRUCTOR - INITIAL ACTIONS
////////////////////////////////////////////
public function Coverflow(_width:Number, _height:Number, __stage:Stage = null):void {
_stage=__stage;
sw=_width;
sh=_height;
centerX=_width>>1;
centerY=(_height>>1) - 20;
loadXML();
//Grabs Background color passed in through FlashVars
var backgColor:String = _stage.loaderInfo.parameters["backgroundColor"];
if(backgColor == null) {
//Black
backgColor = "0x000000";
//White
//backgColor = "0xFFFFFF";
}
//Creates Background MovieClip
background = new Background();
//Set Background To Provided Width/Height
background.width = _width;
background.height = _height;
//Adds background MovieClip to DisplayList
addChild(background);
//Tints Background MovieClip with provided tint
TweenPlugin.activate([TintPlugin]);
TweenLite.to(background, 0, {tint:backgColor});
//Grabs Background color passed in through FlashVars
var labelColor:String = _stage.loaderInfo.parameters["labelColor"];
//Check for value and then default
if(labelColor == null) {
//Black
//labelColor = "0x000000";
//White
labelColor = "0xFFFFFF";
}
//Tint Coverflow label to color provided
TweenLite.to(coverLabel, 0, {tint:labelColor});
if (_stage) {
_stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
}
}
////////////////////////////////////////////
// FUNCTIONS
////////////////////////////////////////////
private function keyDownHandler(e:KeyboardEvent):void {
if (e.keyCode==37||e.keyCode==74) {
clickPre();
}
if (e.keyCode==39||e.keyCode==75) {
clickNext();
}
// 72 stand for "H" key, 191 stand for "?" key
if (e.keyCode==72||e.keyCode==191) {
}
}
// display the previous image
private function clickPre(e:Event=null):void {
_currentCover--;
if (_currentCover<0) {
_currentCover=coverflowItemsTotal-1;
}
coverSlider.value=_currentCover;
gotoCoverflowItem(_currentCover);
}
// display the next image
private function clickNext(e:Event=null):void {
_currentCover++;
if (_currentCover>coverflowItemsTotal-1) {
_currentCover=0;
}
coverSlider.value=_currentCover;
gotoCoverflowItem(_currentCover);
}
// loading the XML
private function loadXML():void {
//Loads XML passed through FlashVars
var xml_source:String = _stage.loaderInfo.parameters["xmlPath"];
//If XML not found through FlashVars then defaults to xml path below
if(xml_source == null) {
xml_source = 'xml/data.xml';
}
// loading the cover xml here
coverflowXMLLoader = new URLLoader();
coverflowXMLLoader.load(new URLRequest("xml/data.xml"));
coverflowXMLLoader.addEventListener(Event.COMPLETE, coverflowXMLLoader_Complete);
coverflowXMLLoader.addEventListener(IOErrorEvent.IO_ERROR, coverflowXMLLoader_IOError);
}
// parse the XML
private function coverflowXMLLoader_Complete(e:Event):void {
coverflowXML=new XML(e.target.data);
coverflowItemsTotal=coverflowXML.cover.length();
coverflowSpacing=Number(coverflowXML.#coverflowSpacing);
coverflowImageWidth=Number(coverflowXML.#imageWidth);
coverflowImageHeight=Number(coverflowXML.#imageHeight);
coverLabelPositionY=Number(coverflowXML.#coverLabelPositionY);
coverSlidePositionY=Number(coverflowXML.#coverSlidePositionY);
transitionTime=Number(coverflowXML.#transitionTime);
centerCoverflowZPosition=Number(coverflowXML.#centerCoverflowZPosition);
//Image Border
padding = Number(coverflowXML.#imagePadding)
//Reflection Attributes
reflectionAlpha=Number(coverflowXML.#reflectionAlpha);
reflectionRatio=Number(coverflowXML.#reflectionRatio);
reflectionDistance=Number(coverflowXML.#reflectionDistance);
reflectionUpdateTime=Number(coverflowXML.#reflectionUpdateTime);
reflectionDropoff=Number(coverflowXML.#reflectionDropoff);
startIndex=Number(coverflowXML.#startIndex);
startIndexInCenter = (coverflowXML.#startIndexInCenter.toLowerCase().toString()=="yes");
_target=coverflowXML.#target.toString();
for (var i=0; i<coverflowItemsTotal; i++) {
//Make An Object To Hold Values
var _obj:Object = new Object();
//Set Values To Object from XML for each CoverflowItem
_obj.image = (coverflowXML.cover[i].#img.toString());
_obj.title = (coverflowXML.cover[i].#title.toString());
_obj.link = (coverflowXML.cover[i].#link.toString());
_data[i] = _obj;
}
loadCover();
}
private function coverflowXMLLoader_IOError(event:IOErrorEvent):void {
trace("Coverflow XML Load Error: "+ event);
}
// load the image cover when xml is loaded
private function loadCover():void {
for (var i:int = 0; i < coverflowItemsTotal; i++) {
var cover:Sprite=createCover(i,_data[i].image);
coverArray[i]=cover;
cover.y=centerY;
cover.z=0;
coverflowItemContainer.addChild(cover);
}
if (startIndexInCenter) {
startIndex=coverArray.length>>1;
gotoCoverflowItem(startIndex);
} else {
gotoCoverflowItem(startIndex);
}
_currentCover=startIndex;
coverSlider=new Scrollbar(coverflowItemsTotal,_stage);
coverSlider.value=startIndex;
coverSlider.x = (_stage.stageWidth/2) - (coverSlider.width/2);
coverSlider.y=_stage.stageHeight-40;
coverSlider.addEventListener("UPDATE", coverSlider_Update);
coverSlider.addEventListener("PREVIOUS", coverSlider_Previous);
coverSlider.addEventListener("NEXT", coverSlider_Next);
addChild(coverSlider);
//coverLabel.x = (sw - coverLabel.width)>>1;
coverLabel.x = (_stage.stageWidth/2) - (coverLabel.width/2);
coverLabel.y=coverLabelPositionY;
addChild(coverLabel);
addChild(coverSlider);
addChild(coverLabel);
}
private function coverSlider_Update(e:Event):void {
var value:Number=(coverSlider.value);
gotoCoverflowItem(value);
e.stopPropagation();
}
private function coverSlider_Previous(e:Event):void {
clickPre();
}
private function coverSlider_Next(e:Event):void {
clickNext();
}
// move to a certain cover via number
private function gotoCoverflowItem(n:int):void {
_currentCover=n;
reOrderCover(n);
if (coverSlider) {
coverSlider.value=n;
}
}
ExternalInterface.addCallback("gotoCover", gotoCoverflowItem);
private function cover_Selected(event:CoverflowItemEvent):void {
var currentCover:uint=event.data.id;
if (coverArray[currentCover].rotationY==0) {
try {
// open the link if user click the cover in the middle again
if (_data[currentCover].link!="") {
navigateToURL(new URLRequest(_data[currentCover].link), _target);
}
} catch (e:Error) {
//
}
} else {
gotoCoverflowItem(currentCover);
}
}
// change each cover's position and rotation
private function reOrderCover(currentCover:uint):void {
for (var i:uint = 0, len:uint = coverArray.length; i < len; i++) {
var cover:Sprite=coverArray[i];
if (i<currentCover) {
//Left Side
TweenLite.to(cover, transitionTime, {x:(centerX - (currentCover - i) * coverflowSpacing - coverflowImageWidth/2), z:(coverflowImageWidth/2), rotationY:-65});
} else if (i > currentCover) {
//Right Side
TweenLite.to(cover, transitionTime, {x:(centerX + (i - currentCover) * coverflowSpacing + coverflowImageWidth/2), z:(coverflowImageWidth/2), rotationY:65});
} else {
//Center Coverflow
TweenLite.to(cover, transitionTime, {x:centerX, z:centerCoverflowZPosition, rotationY:0});
//Label Handling
coverLabel._text.text=_data[i].title;
coverLabel.alpha=0;
TweenLite.to(coverLabel, 0.75, {alpha:1,delay:0.2});
}
}
for (i = 0; i < currentCover; i++) {
addChild(coverArray[i]);
}
for (i = coverArray.length - 1; i > currentCover; i--) {
addChild(coverArray[i]);
}
addChild(coverArray[currentCover]);
if (coverSlider) {
addChild(coverSlider);
addChild(coverLabel);
}
}
//Create CoverflowItem and Set Data To It
private function createCover(num:uint, url:String):Sprite {
//Setup Data
var _data:Object = new Object();
_data.id=num;
//Create CoverflowItem
var cover:CoverflowItem=new CoverflowItem(_data);
//Listen for Click
cover.addEventListener(CoverflowItemEvent.COVERFLOWITEM_SELECTED, cover_Selected);
//Set Some Values
cover.name=num.toString();
cover.image=url;
cover.padding=padding;
cover.imageWidth=coverflowImageWidth;
cover.imageHeight=coverflowImageHeight;
cover.setReflection(reflectionAlpha, reflectionRatio, reflectionDistance, reflectionUpdateTime, reflectionDropoff);
//Put CoverflowItem in Sprite Container
var coverItem:Sprite = new Sprite();
cover.x=- coverflowImageWidth/2-padding;
cover.y=- coverflowImageHeight/2-padding;
coverItem.addChild(cover);
coverItem.name=num.toString();
return coverItem;
}
}
}
The code I added is:
ExternalInterface.addCallback("gotoCover", gotoCoverflowItem);
Please help!

Putting the ExternalInterface call at the end of the Coverflow constructor should work as desired. The current line you have is not inside a function.
I don't know what your javascript looks like, but this code requires a parameter for gotoCoverflowItem, so I am assuming you are passing the appropriate data.
I haven't gone through all the code, but keep in mind that the current code might have certain things that it does - that might not get done if you are feeding it just the index of the next cover. I do see code in the gotoColorflowItem function that updates variables for the slider and current cover based on the selection, so it might be just fine.
Also, you are most likely going to get a runtime error if you try to test this outside of a browser for any reason, so you might want to put a try/catch for that case.
The author included his wisdom on the page :
"NOTE: I would not recommend trying to learn flash with this file. There are a lot of people asking how to change text color, if you are having these requests I would suggest going through some Lynda.com Flash tutorials to get you familiar with Flash or hiring a Flash developer to help you out."

Well, you can't just dump the ExternalInterface call anywhere you want to. It needs to be inside a function such as the constructor.

Related

How can i make a ticking like noise (clock) using web audio api

I am starting with basic whitenoise and I want to create a delay that makes it come on and off after every second like a clock. I'm then going to tweak the noise with different filters to alter the noise.
At the moment I have the noise with a low pas filter to change the frequency sound of the noise. Can someone help with my next step, it's my first time using stack overflow sorry if i haven't given enough info.
Here is my code:
html
<html>
<input type="button" value="Start/Stop" id="StartStop">
<input type="number" min="1000" max="2000" value="1000" id="Filter">
<script>
let context= new AudioContext();
StartStop.onclick = function() {
if (context.state === 'suspended') context.resume();
else context.suspend();
}
context.audioWorklet.addModule('mySound.js').then(() => {
let myNoise = new AudioWorkletNode(context,'noise-generator');
let myFilter = new AudioWorkletNode(context,'lowpass-filter',{parameterData:{frequency:1000}});
Filter.oninput = function() {
myFilter.parameters.get('frequency').value=this.value;
FilterLabel.innerHTML = this.value ;
}
myNoise.connect(myFilter);
myFilter.connect(context.destination);
});
</script>
</html>
javascropt
registerProcessor('noise-generator',class extends AudioWorkletProcessor {
process(inputs, outputs) {
for (let i=0;i<outputs[0][0].length;++i) outputs[0][0][i]=2*Math.random()-1;
return true;
}
});
registerProcessor('gain-processor',class extends AudioWorkletProcessor {
// Custom AudioParams can be defined with this static getter.
static get parameterDescriptors() { return [{name:'gain',defaultValue:0.1}] }
// constructor() { super() } // The super constructor call is required
process(inputs, outputs, parameters) {
const input = inputs[0],output = outputs[0];
for (let channel=0;channel<inputs[0].length;++channel)
for (let i=0;i<input[channel].length;++i) output[channel][i] = input[channel][i] * parameters.gain[0];
return true;
}
});
registerProcessor('lowpass-filter', class extends AudioWorkletProcessor {
static get parameterDescriptors() { return [{name:'frequency',defaultValue:1000,minValue:0}]; }
constructor() {
super();
this.lastOut = 0;
}
process(inputs, outputs, parameters) {
let input = inputs[0],output = outputs[0],coeff;
let frequency = parameters.frequency;
for (let channel = 0; channel < output.length; ++channel) {
let inputChannel = input[channel],outputChannel = output[channel];
coeff = 2 * Math.PI * frequency[0] / sampleRate;
for (let i = 0; i < outputChannel.length; ++i) {
outputChannel[i]=inputChannel[i] * coeff +(1-coeff)*this.lastOut;
this.lastOut=outputChannel[i];
}
}
return true;
}
});
Welcome to StackOverflow.
First off, I'd reduce complexity by using the builtin GainNode and BiquadFilterNode (or IIRFilterNode) instead of AudioWorkletNode to implement these.
To make the noise turn off and on every second, I'd use a looping AudioBufferSourceNode to create the regular off/on clicks and feed that into the gain AudioParam of the GainNode. Something like this (totally untested!):
// Create buffer that's 1 sec long
let buffer = new AudioBuffer({sampleRate: context.sampleRate, length: context.sampleRate});
let data = buffer.getChannelData(0);
// Set the first few values of the buffer to 1. You'll have to decide how many.
// This is basically a square wave with a short duty cycle.
data[0] = 1;
// Create the source that loops forever.
let tick = new AudioBufferSourceNode(context, {buffer: buffer});
tick.loop = true;
let gain = new GainNode(context, {gain: 0});
tick.connect(gain.gain);
// Start the source now.
tick.start();
// A Biquad filter instead of your worklet. You'll have to choose the parameters.
let filt = new BiquadFilterNode(context);
// Connect up your noise source to the gain node, and connect the gain node
// to the destination:
myNoise.connect(filt).connect(gain).connect(context.destination);
The tick is 1 for a short time and that gets added to the gain of the GainNode. Hence the gain of the node is 1 for a bit, then 0 for the rest of the time. This is applied to your noise, so you get noise output for a bit then silence.
I think this is what you're asking for.

Modifying remote JavaScripts as they load with CefSharp?

I am building a custom browser as part of an interface to a remote website. Their GUI sucks so I'm doing some JavaScript hacks to make it look better.
Currently, to make modifications to their UI I am using the following GreaseMonkey script (on Firefox):
// ==UserScript==
// #name winman-load
// #namespace winman
// #description stuff to do when winman.js loads
// #include https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/
// #version 1
// #grant none
// #run-at document-start
// ==/UserScript==
document.addEventListener("beforescriptexecute", function(e) {
src = e.target.src;
content = e.target.text;
//console.log("src: " + src);
if (src.search("winman.js") > -1) {
console.info("============ new winman ===========\n" + src);
var newContent = "";
$.ajax({
async: false,
type: 'GET',
url: '/script/winman.js',
success: function(data) {
newContent = data.replace('pos += currentPos;', 'pos += currentPos + 100;');
newContent = newContent.replace('var enable = false;', 'var enable = true;');
newContent = newContent.replace('var available = true;', 'var available = false;');
}
});
// Stop original script
e.preventDefault();
e.stopPropagation();
unsafeWindow.jQuery(e.target).remove();
var script = document.createElement('script');
script.textContent = newContent;
(document.head || document.documentElement).appendChild(script);
script.onload = function() {
this.parentNode.removeChild(this);
}
}
});
I want to be able to do something if this nature with CefSharp, where I can modify the scripts on-the-fly as the browser loads the page.
Ok I figured this out. You create a RequestHandler with a method like this:
IResponseFilter IRequestHandler.GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response) {
var url = new Uri(request.Url);
if (request.Url.Equals(scriptToUpdate, StringComparison.OrdinalIgnoreCase)) {
Dictionary<string, string> dictionary = new Dictionary<string, string>();
dictionary.Add(search1, replace1);
dictionary.Add(search2, replace2);
return new FindReplaceResponseFilter(dictionary);
}
return null;
}
And then for the multiple search/replace you make a FindReplaceResponseFilter:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using CefSharp;
namespace CefFilters {
public class FindReplaceResponseFilter : IResponseFilter {
private static readonly Encoding encoding = Encoding.UTF8;
/// <summary>
/// The portion of the find string that is currently matching.
/// </summary>
private int findMatchOffset;
/// <summary>
/// Overflow from the output buffer.
/// </summary>
private readonly List<byte> overflow = new List<byte>();
/// <summary>
/// Number of times the the string was found/replaced.
/// </summary>
private int replaceCount;
private Dictionary<string, string> dictionary;
public FindReplaceResponseFilter(Dictionary<string, string> dictionary) {
this.dictionary = dictionary;
}
bool IResponseFilter.InitFilter() {
return true;
}
FilterStatus IResponseFilter.Filter(Stream dataIn, out long dataInRead, Stream dataOut, out long dataOutWritten) {
// All data will be read.
dataInRead = dataIn == null ? 0 : dataIn.Length;
dataOutWritten = 0;
// Write overflow then reset
if (overflow.Count > 0) {
// Write the overflow from last time.
WriteOverflow(dataOut, ref dataOutWritten);
}
// Evaluate each character in the input buffer. Track how many characters in
// a row match findString. If findString is completely matched then write
// replacement. Otherwise, write the input characters as-is.
for (var i = 0; i < dataInRead; ++i) {
var readByte = (byte) dataIn.ReadByte();
var charForComparison = Convert.ToChar(readByte);
if (replaceCount < dictionary.Count) {
var replace = dictionary.ElementAt(replaceCount);
if (charForComparison == replace.Key[findMatchOffset]) {
//We have a match, increment the counter
findMatchOffset++;
// If all characters match the string specified
if (findMatchOffset == replace.Key.Length) {
// Complete match of the find string. Write the replace string.
WriteString(replace.Value, replace.Value.Length, dataOut, ref dataOutWritten);
// Start over looking for a match.
findMatchOffset = 0;
replaceCount++;
}
continue;
}
// Character did not match the find string.
if (findMatchOffset > 0) {
// Write the portion of the find string that has matched so far.
WriteString(replace.Key, findMatchOffset, dataOut, ref dataOutWritten);
// Start over looking for a match.
findMatchOffset = 0;
}
}
// Write the current character.
WriteSingleByte(readByte, dataOut, ref dataOutWritten);
}
if (overflow.Count > 0) {
//If we end up with overflow data then we'll need to return NeedMoreData
// On the next pass the data will be written, then the next batch will be processed.
return FilterStatus.NeedMoreData;
}
// If a match is currently in-progress we need more data. Otherwise, we're
// done.
return findMatchOffset > 0 ? FilterStatus.NeedMoreData : FilterStatus.Done;
}
private void WriteOverflow(Stream dataOut, ref long dataOutWritten) {
// Number of bytes remaining in the output buffer.
var remainingSpace = dataOut.Length - dataOutWritten;
// Maximum number of bytes we can write into the output buffer.
var maxWrite = Math.Min(overflow.Count, remainingSpace);
// Write the maximum portion that fits in the output buffer.
if (maxWrite > 0) {
dataOut.Write(overflow.ToArray(), 0, (int) maxWrite);
dataOutWritten += maxWrite;
}
if (maxWrite < overflow.Count) {
// Need to write more bytes than will fit in the output buffer.
// Remove the bytes that were written already
overflow.RemoveRange(0, (int) (maxWrite - 1));
}
else {
overflow.Clear();
}
}
private void WriteString(string str, int stringSize, Stream dataOut, ref long dataOutWritten) {
// Number of bytes remaining in the output buffer.
var remainingSpace = dataOut.Length - dataOutWritten;
// Maximum number of bytes we can write into the output buffer.
var maxWrite = Math.Min(stringSize, remainingSpace);
// Write the maximum portion that fits in the output buffer.
if (maxWrite > 0) {
var bytes = encoding.GetBytes(str);
dataOut.Write(bytes, 0, (int) maxWrite);
dataOutWritten += maxWrite;
}
if (maxWrite < stringSize) {
// Need to write more bytes than will fit in the output buffer. Store the
// remainder in the overflow buffer.
overflow.AddRange(encoding.GetBytes(str.Substring((int) maxWrite, (int) (stringSize - maxWrite))));
}
}
private void WriteSingleByte(byte data, Stream dataOut, ref long dataOutWritten) {
// Number of bytes remaining in the output buffer.
var remainingSpace = dataOut.Length - dataOutWritten;
// Write the byte to the buffer or add it to the overflow
if (remainingSpace > 0) {
dataOut.WriteByte(data);
dataOutWritten += 1;
}
else {
// Need to write more bytes than will fit in the output buffer. Store the
// remainder in the overflow buffer.
overflow.Add(data);
}
}
public void Dispose() {}
}
}
Keep in mind that this iterates through left to right, top to bottom, so make sure your search and replaces are in the right order.

How to establish a click listener in a separate class from the event Vaadin

I am very new to Vaadin and v-Leaflet. I have created a component that takes some geojson data and puts it over a map. I am able to click on any of the polygons/ multi polygons and get back a few bits of information in the form of a notification. The thing is, I need to take this information and click event and have it influence about 4 other separate components in their own separate classes. I have been racking my brain with this for the past 2 days and just can't seem to grasp it.
Here is my map/ click event:
private LMap map;
String filePath = this.getClass().getResource("/fccpeasgeo.json").getPath();
File file = new File(filePath);
//ArrayList<String> peaNames = new ArrayList<String>();
//#Override
public LMap createMap() {
map = new LMap();
FeatureJSON io = new FeatureJSON();
try {
long currentTimeMillis = System.currentTimeMillis();
// Look ma, no proxy needed, how cool is that!
FeatureCollection fc = io.readFeatureCollection(file);
Logger.getLogger(LeafletMap.class.getName()).severe("Download in " + (System.currentTimeMillis() - currentTimeMillis));
currentTimeMillis = System.currentTimeMillis();
FeatureIterator iterator = fc.features();
try {
while (iterator.hasNext()) {
Feature feature = iterator.next();
final String name = feature.getProperty("PEA_Name").getValue().toString();
final String population = feature.getProperty("POPs_2010").getValue().toString();
Geometry geometry = (Geometry) feature.getDefaultGeometryProperty().getValue();
// The geojson provided in example is rather complex (several megabytes)
// Use JTS to simplyfy. Note that it is rather easy to use
// different settings on different zoom levels, as well as decide
// to drop the feature form client altogether
geometry = DouglasPeuckerSimplifier.simplify(geometry, 0.2);
// In this example can be Polygon/Multipolygon
Collection<LeafletLayer> toLayers = JTSUtil.toLayers(geometry);
for (LeafletLayer l : toLayers) {
map.addComponent(l);
if (l instanceof LPolygon) {
LPolygon lPolygon = (LPolygon) l;
lPolygon.addClickListener(new LeafletClickListener() {
#Override
public void onClick(LeafletClickEvent event) {
Notification.show("PEA: " + name + " Population: " + population);
}
});
}
}
}
Logger.getLogger(LeafletMap.class.getName()).severe("Reducing and creating layers " + (System.currentTimeMillis() - currentTimeMillis));
} finally {
iterator.close();
}
} catch (MalformedURLException ex) {
Logger.getLogger(LeafletMap.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(LeafletMap.class.getName()).log(Level.SEVERE, null, ex);
}
map.zoomToContent();
//map.setCenter(40, -95.2);
//map.setZoomLevel(2.5);
LTileLayer tf = new LTileLayer();
tf.setUrl("http://{s}.tile.thunderforest.com/transport/{z}/{x}/{y}.png");
tf.setSubDomains(new String[]{"a", "b", "c"});
tf.setActive(true);
map.addBaseLayer(tf, "ThunderForest Transport");
return map;
}
Here is one of the components that will be receiving the event.
public Chart mhzPerSqMile() {
Chart chart = new Chart();
run();
chart.setCaption("Total MHz Per Square Mile");
chart.getConfiguration().setTitle("");
chart.getConfiguration().getChart().setType(ChartType.PIE);
chart.getConfiguration().getChart().setAnimation(false);
chart.setWidth("100%");
chart.setHeight("90%");
DataSeries series = new DataSeries();
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName()!=null)
{
if (evt.getPropertyName().equals("abcTask"))
{
}
}
for (int i = 0; i < 5; i++) {
Operator operator = operators.get(i);
if (selectedPea != null) {
if (operator.getPeaName().toLowerCase() == selectedPea.toLowerCase()){
DataSeriesItem item = new DataSeriesItem(operator.getName(),
operator.getTotalMHzSqMile());
series.add(item);
item.setColor(DummyDataGenerator.chartColors[i]);
}
}
}
chart.getConfiguration().setSeries(series);
PlotOptionsPie opts = new PlotOptionsPie();
opts.setBorderWidth(0);
opts.setShadow(false);
opts.setAnimation(false);
chart.getConfiguration().setPlotOptions(opts);
Credits c = new Credits("");
chart.getConfiguration().setCredits(c);
return chart;
}
}
}
Any advice would be very appreciated!
what I think you simply need to fire a property with any specific name (Event name) and all your listener classes have implemented PropertyChangeListener which triggers on every fireProperty() call , obviously you are matching your event name there and hence all you 4 classes perform their task upon receiving such a property change
You need to register PropertyChangeSupport for current instance
PropertyChangeSupport pcs = new PropertyChangeSupport(this);
further you'll use this object to fire your event
Firing event
//this firing code will probably go inside your click method that actually causes an event to occur
pcs.firePropertyChange("abcTask", oldValue, newValue);
Recieving event
#Override
public void propertyChange(PropertyChangeEvent evt)
{
if (evt.getPropertyName()!=null)
{
if (evt.getPropertyName().equals("abcTask"))
{
//perform task
}
}
}

Batch Export Symbols to SVG - Illustrator

Question:
I've created a script that iterates through all symbols in an Illustrator document and exports them as PNGs.
I need it to work for SVGs as well, however, it's not as simple as just changing the file-type.
Because of Illustrator's default behaviour of making a recently saved svg the app.activeDocument, the for loop nests new directories for each symbol.
e.g.
exports/
symbol01.svg
exports/
symbol02.svg
exports/
symbol03.svg
etc..
I'm pretty sure the problem lays between //create directory and //choose directory, but I can't for the life of me figure it out.
var doc = app.activeDocument;
var symbolCount = doc.symbols.length;
if (symbolCount >= 1) {
if (confirm("Are all your layers hidden?")) {
// create temp layer
doc.layers.add();
for (var i = 0; i < doc.symbols.length; i++) {
// place a symbol instance - temp
var s = doc.symbolItems.add(doc.symbols[i]);
// create directory
var dest = new Folder(doc.path + "/exports");
if (!dest.exists) dest.create();
// choose directory
dest.changePath(doc.symbols[i].name);
// export symbols
saveSVG(dest);
// delete temp symbol instance
s.remove();
}
// remove temp layer
doc.layers[0].remove();
}
function saveSVG(file) {
// save options
var type = ExportType.SVG;
var options = new ExportOptionsSVG();
// export
doc.exportFile(file, type, options);
}
} else {
alert("You don't have any symbols in this document");
}
Having a way to store the initial app.activeDocument would probably fix the issue, but I can't figure out how to do that.. if that's even the best way?
Bonus:
Another problem with this script is the artboard doesn't resize to the symbols, so I found a function fitArtboardToSelectedArt() which I've tried implementing with no success.. can anyone can explain how it should work?
PS. Here's a link for the Illustrator scripting documentation: http://adobe.ly/1JxLlUK
Figured it out :)
Feel free to use the following script if you need to do the same.
/*
* Export Symbols as SVGs - Illustrator
* --------------------------------------
* Created By Shane Parsons - 30PT Design Inc.
* http://30ptdesign.com/
*/
var doc = app.activeDocument;
var symbolCount = doc.symbols.length;
if (symbolCount >= 1) {
if (confirm("Are all your layers hidden?")) {
// choose directory
var dest = Folder(doc.path).selectDlg();
// folder chosen
if (dest) {
// create temp layer
doc.layers.add();
// create temp artboard
doc.artboards.add(doc.artboards[0].artboardRect);
// get temp artboard
var tempAB = doc.artboards.getActiveArtboardIndex();
// loop through symbols
for (var i = 0; i < doc.symbols.length; i++) {
// place a symbol instance - temp
var symbol = doc.symbolItems.add(doc.symbols[i]);
// resize artboard
doc.artboards[tempAB].artboardRect = doc.visibleBounds;
app.redraw();
// choose directory
var filename = doc.symbols[i].name;
// export symbols
saveSVG(dest, filename);
// delete temp symbol instance
symbol.remove();
}
// remove temp layer
doc.layers[0].remove();
// remove temp artboard
doc.artboards[tempAB].remove();
}
}
function saveSVG(dest, filename) {
// save options
var type = ExportType.SVG;
var options = new ExportOptionsSVG();
// file
var file = new File(dest + "/" + filename);
// export
doc.exportFile(file, type, options);
}
} else {
alert("You don't have any symbols in this document");
}

how to create phonegap brightness plugin for Android

As I have found out there is no way to change the device brightness using Phonegap, so I have decided to create this plugin by my self. I am new to Phonegap and I do not know is it hard or not.
I have red some examples on how to create plugins for Phonegap But there are some things I don't understand.
I have this code for changing the screen brightness and I want to create a method for Phonegap that calls it:
private void setBrightness(int brightness) {
WindowManager.LayoutParams layoutParams = getWindow().getAttributes();
layoutParams.screenBrightness = brightness / 100.0f;
getWindow().setAttributes(layoutParams);
}
is it possible?
Thanks
Yeah, it's pretty easy to do if you follow the plugin development guide. For what you want to do it would be like this:
cordova.define("cordova/plugin/brightness",
function(require, exports, module) {
var exec = require("cordova/exec");
var Brightness = function () {};
var BrightnessError = function(code, message) {
this.code = code || null;
this.message = message || '';
};
Brightness.CALL_FAILED = 0;
Brightness.prototype.set = function(level,success,fail) {
exec(success,fail,"Brightness", "set",[level]);
};
var brightness = new Brightness();
module.exports = brightness;
});
Then you'll need to write some Java code to do the phone call. You'll need to create a new class that extends the Plugin class and write an execute method like this:
public PluginResult execute(String action, JSONArray args, String callbackId) {
PluginResult.Status status = PluginResult.Status.OK;
String result = "";
try {
if (action.equals("set")) {
int brightness = args.getInt(0);
WindowManager.LayoutParams layoutParams = getWindow().getAttributes();
layoutParams.screenBrightness = brightness / 100.0f;
this.cordova.getActivity().getWindow().setAttributes(layoutParams);
}
else {
status = PluginResult.Status.INVALID_ACTION;
}
return new PluginResult(status, result);
} catch (JSONException e) {
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
}
}
Whatever you call this class you'll need to add a line in the res/xml/config.xml file so the PluginManager can create it.
<plugin name="Brightness" value="org.apache.cordova.plugins.Brightness"/>
and finally in your JavaScript code you'll need to create they plugin and call it like this:
function panicButton() {
var brightness = cordova.require("cordova/plugin/brightness");
brightness.set(50);
}
That should about do it.

Categories