Problems with addFrameScript on an instance - actionscript

I'm trying to add a frame script via:
private function addFrameScript(mc:MovieClip, label:String, func:Function, arg:*):void {
var labels:Array = mc.currentLabels;
var i:int = labels.length;
while (--i > -1) {
if (FrameLabel(labels[i]).name == label) {
mc.addFrameScript(FrameLabel(labels[i]).frame-1, func(arg));
return;
}
}
trace("WARNING: The label '" + label + "' does not exist in the MovieClip '" + mc.name + "'");
}
private function dispatchFrameEvent(labelName:String):void {
dispatchEvent(new Event(labelName, true));
}
addFrameScript(instanceName, "end", dispatchFrameEvent, "end");
But it doesn't seem to be adding and I can't figure out why. Normally I add Frame scripts to the main timeline, but not to an instance on the timeline (as in the example above).
Clearly there's something I'm missing...is there a way to trace out my frame script to see if it's even being added?

The problem here is that addFrameScript functions being added take no arguments. so whatever func you are passing in must must return a function with no arguments
so your dispatchFrameEvent should look like this
private function dispatchFrameEvent(labelName:String):Function {
return function func():void{
dispatchEvent(new Event(labelName, true));
}
}

Related

how to display a WebView only after a javascript code is done?

I'm trying to force WebView to 'skip' images by using javascript. (like here: https://stackoverflow.com/a/31848599/13174607).
The problem is that the images are disappeared only after the WebView finished loaded. I want to display the WebView only after the javascript is finished.
This is my code:
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(webView, url);
webView.loadUrl("javascript:(function(){ var imgs=document.getElementsByTagName('img');" + "for(i=0;i<imgs.length;i++) { imgs[i].style.display='none'; } })()");
}
});
}
I tried to use setVisibility() method, like this:
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
webView.setVisibility(View.INVISIBLE);
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(webView, url);
webView.loadUrl("javascript:(function(){ var imgs=document.getElementsByTagName('img');" + "for(i=0;i<imgs.length;i++) { imgs[i].style.display='none'; } })()");
webView.setVisibility(View.VISIBLE);
}
});
}
but it didn't help.
Thanks!
EDIT:
By using the proposed solution and the #mustansir comments I wrote this code on 'onPageFinished':
webView.loadUrl("javascript:" + "function taskOne() {" +
"var imgFlag = 0;" + //will sign when the for loop ended
"var imgs = document.getElementsByTagName('img');" +
"if (imgs==0){imgFlag=1;} " +
"for (i = 0; i < imgs.length; i++) {" +
"imgs[i].style.display = 'none';" +
"if (i==imgs.length-1)" +
"{" +
"imgFlag=1;" +
"}"+
"}}" +
"taskOne();" +
"function taskTwo () {" +
"if(imgFlag==1){" +
"window.visibility.changeVisibility(); }" +
"else {" +
"setTimeout(taskTwo(),100);}}" +
"taskTwo();");
but the the webview doesn't become visible. Any idea why?
You can try injecting a JavaScript interface and call that interface method when you reach at the last image in the loop to change WebView visibility.
Something like this:
webview.addJavascriptInterface(this, "visibility");
and call this interface from your JavaScript like this:
var imgs = document.getElementsByTagName('img');
for (i = 0; i < imgs.length; i++) {
imgs[i].style.display = 'none';
if (i == imgs.length-1) {
visibility.changeVisibility();
}
}
Now define changeVisibility() with #JavascriptInterface annotation in that activity in which you have added javascriptInterface like this:
#JavascriptInterface
public void changeVisibility() {
runOnUiThread(() -> webview.setVisibility(View.VISIBLE));
}

Custom Components in Crafty.js

I am new to Crafty.js. I am currently working a 2D Top Down RPG using this frame work. I am trying to create a custom component that will contain the Unit's information such as Health, Mana, Name etc. My component's code are as follows:
Crafty.c("UnitInfo", {
init: function() {
this.bind("EnterFrame", function(){
console.log("Custom Component Test: " + this.message);
});
},
unitinfo: function(message) {
this.message = message;
}
});
Then I added this component to a unit which is in my case, an Enemy entity:
enemy1 = Crafty.e('Enemy, 2D, Canvas, Color, enemy_default, SpriteAnimation, Solid, Collision, UnitInfo')
.attr({x: (screenWidth/2) + 150, y: (screenHeight/2) + 150, w: spriteBaseW, h: spriteBaseH, curHealth: 100 })
.checkHits("Skill")
.unitinfo("Random Msg")
.bind("HitOn", function() {
var rndDmg = 0;
if(currentSkill==1) rndDmg = skillDamage.skill1;
else if(currentSkill==2) rndDmg = skillDamage.skill2;
else if(currentSkill==3) rndDmg = skillDamage.skill3;
else if(currentSkill==4) rndDmg = skillDamage.skill4;
rndDmg = randomRange(rndDmg-9,rndDmg);
this.curHealth -= rndDmg;
Crafty.e("2D, DOM, Text, Tween")
.attr({x: this.x, y: this.y})
.textColor("white")
.text(rndDmg)
.textFont({size: "20px"})
.tween({y: this.y-30, alpha: 0.0}, 2000)
.bind("TweenEnd", function(){
this.destroy();
});
if(this.curHealth<=0) {
//this.destroy();
//console.log("An Enemy was killed!!!!");
}else{
console.log("Enemy HP: " + this.curHealth + ", Damage Taken: " + rndDmg);
}
})
.bind("EnterFrame", function() {
enemyAI(this);
});
When I execute the code, it shows me this error:
console error
I believe that the unitinfo() is properly working as the "Random Msg" is appearing on the console logs and it is being executed every frame. I just don't understand why "this" is being recognized as undefined. Can someone help me on this?
This is because you're attempting to call bind on the result of unitinfo(), but that method doesn't return the entity.
This is a fundamental aspect of javascript, but it's definitely a gotcha when implementing custom components in Crafty. From the docs
Keep in mind that the method chaining technique (calling e.place().color()) is only possible because we explicitly return this from our custom method. Forgetting to do so can be a common source of errors, so keep that in mind if you get a hard-to-pin-down "method undefined" message.
i.e. when you define a method, you have to explicitly return this to use it in this manner.

Why my md-autoComplete is not displaying return values

I am using Angular Material for the first time. I am stuck with an issue with autocomplete. Below is my template:
<md-autocomplete class="flex"
md-no-cache="true"
md-selected-item="c.receipt"
md-item-text="item.name"
md-search-text="SearchText"
md-items="item in querySearch(SearchText)"
md-floating-label="search">
<md-item-template>
<span><span class="search-result-type">{{item.GEOType}}</span><span md-highlight-text="SearchText">{{item.GEOName+(item.country?' / '+item.country:'')}}</span></span>
</md-item-template>
<md-not-found>No matches found.</md-not-found>
</md-autocomplete>
And in ctrl I have:
$scope.querySearch = function (query) {
var GeoDataAPIUrl = '/api/TargetSettings/RetrieveCorridorLeverValues';
if (query.length < 5)
return;
else {
var GeoDataSearchUrl = GeoDataAPIUrl + '?' + 'strGeoName=' + query;
$http
.get(GeoDataSearchUrl)
.then(function (geoAPIResponse) {
console.log("GeoAPIResponse was ", geoAPIResponse);
return geoAPIResponse.data;
},
function (geoAPIError) {
console.log("GeoAPI call failed ", geoAPIError);
});
}
};
With above code, I am getting nothing as suggestions, only my not-found text is displayed, while my http call return an array which is printed in console too. Am I missing something??
I saw at many places, people have used some filters with autocomplete, I dont think that is something essential.
Pls advice how to make above work.
$http returns promise and md-autocomplete uses same promise to display the result. In your case you are returning result but not promise. Your code should be
$scope.querySearch = function (query) {
var GeoDataAPIUrl = '/api/TargetSettings/RetrieveCorridorLeverValues';
if (query.length < 5)
return;
else {
var GeoDataSearchUrl = GeoDataAPIUrl + '?' + 'strGeoName=' + query;
var promise = $http.get(GeoDataSearchUrl).then(function (geoAPIResponse) {
console.log("GeoAPIResponse was ", geoAPIResponse);
return geoAPIResponse.data;
},
function (geoAPIError) {
console.log("GeoAPI call failed ", geoAPIError);
});
return promise;
}
};
It will work now.

Calling Predicate() constructor causes Knockout to throw unexplained exception.

I'm new to breeze and I can't begin to imagine what's causing this to happen. This is a two part question:
1) My function is very simple. I'm querying with two predicates:
var getUserHealthMetricFromId = function (userId, healthMetricId, forceRemote) {
var p1 = new Predicate('userId', '==', userId);
var p2 = new Predicate('healthMetricId', '==', healthMetricId);
var query = EntityQuery.from('UserHealthMetrics').select('lowerValue', 'upperValue')
.where(p1.and(p2));
if (!forceRemote) {
//results = getUserHealthMetricFromLocal(userId, healthMetricId);
var query = query.using(breeze.FetchStrategy.FromLocalCache);
}
var promise = manager.executeQuery(query);
return promise;
};
While I'm debugging (Chrome) the first predicate declaration line, calling the Predicate ctor causes execution to jump to the following finally clause in Knockout-3.0.0.debug.js (line 1483):
finally {
ko.dependencyDetection.end();
_isBeingEvaluated = false;
}
When I execute the "_isBeingEvaluated = false" statement,
an exception is inexplicably thrown landing me here (line 2607):
} catch (ex) {
ex.message = "Unable to process binding \"" + bindingKey + ": " + bindings[bindingKey] + "\"\nMessage: " + ex.message;
throw ex;
}
Thinking this might have more to do with Knockout than with Breeze, I tested by altering the code by hardcoding the Id's so that the parameter variables (which are observables) aren't involved in calling the ctor anymore:
var p1 = new Predicate('userId', '==', 1);
var p2 = new Predicate('healthMetricId', '==', 4);
No dice. The same thing happens. When I try to step into Predicate() the same thing happens. I just throws me over to the knockout debug file.
2) In the same function, the variables I'm passing in are showing up as dependentObservables() in the debug window. These values are the product of another breeze call to the server. Why would breeze render these as dependentObservables instead of plain observables (I do not declare any computeds anywhere in the code)? Here's a quick overview of my code:
In the view model:
var latestEntriesObservable = ko.observableArray(null);
function activate() {
$('#rangeDialog').hide();
var promise = Q.all([datacontext.getLatestEntries(latestEntriesObservable, currentUserId, false),
datacontext.getUserHealthMetrics(userHealthMetricsObservable, currentUserId, false),
datacontext.getUserHealthMetricNames(userHealthMetricNamesObservable, currentUserId, false)]);
return promise;
}
var getLatestEntries = function (latestEntriesObservable, userId, forceRemote) {
var lastEntryQuery = EntityQuery.from('LatestEntries').withParameters({ id: 1 });
if (!forceRemote) {
var e = getLocal('HealthMetricValues', 'healthMetricId');
if (e.length > 0) {
latestEntriesObservable(e);
return Q.resolve();
}
}
return manager.executeQuery(lastEntryQuery)
.then(querySucceeded)
.fail(queryFailed);
// handle the ajax callback
function querySucceeded(data) {
if (latestEntriesObservable) {
latestEntriesObservable(data.results);
//latestEntriesObservable(model.toProtectedObservableItemArray(data.results));
}
log('Retrieved latest entries.', data, true);
}
};
function getLocal(resource, orderBy) {
var query = EntityQuery.from(resource).orderBy(orderBy).withParameters({ id: 1 });
return manager.executeQueryLocally(query);
}
If I haven't provided enough code to help make a diagnosis I'll be happy to provide more upon request.
Any suggestions would be much appreciated!
Ok, I think the issue is that the class is actually breeze.Predicate. In order to save typing we often assign a local variable like this.
var Predicate = breeze.Predicate;
var p1 = new Predicate('userId', '==', 1);
or you can explicitly do this via
var p1 = new breeze.Predicate('userId', '==', 1);
or
var p1 = breeze.Predicate.create('userId', '==', 1);
Presumably, you are doing the same thing with EntityQuery, i.e.
var EntityQuery = breeze.EntityQuery;

Adobe Air how to check if URL is online\gives any response exists?

I have url I want to check if it is live. I want to get bool value. How to do such thing?
You can use an URLLoader and listen for the events to check if it loads, and if not what might be the problem. Would be handy to use the AIRMonitor first to make sure the client's computer is online in the first place.
Here is a class I started to write to illustrate the idea:
package
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.HTTPStatusEvent;
import flash.events.IEventDispatcher;
import flash.events.IOErrorEvent;
import flash.events.SecurityErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
/**
* ...
* #author George Profenza
*/
public class URLChecker extends EventDispatcher
{
private var _url:String;
private var _request:URLRequest;
private var _loader:URLLoader;
private var _isLive:Boolean;
private var _liveStatuses:Array;
private var _completeEvent:Event;
private var _dispatched:Boolean;
private var _log:String = '';
public function URLChecker(target:IEventDispatcher = null)
{
super(target);
init();
}
private function init():void
{
_loader = new URLLoader();
_loader.addEventListener(Event.COMPLETE, _completeHandler);
_loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, _httpStatusHandler);
_loader.addEventListener(IOErrorEvent.IO_ERROR, _ioErrorEventHandler);
_loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, _securityErrorHandler);
_completeEvent = new Event(Event.COMPLETE, false, true);
_liveStatuses = [];//add other acceptable http statuses here
}
public function check(url:String = 'http://stackoverflow.com'):void {
_dispatched = false;
_url = url;
_request = new URLRequest(url);
_loader.load(_request);
_log += 'load for ' + _url + ' started : ' + new Date() + '\n';
}
private function _completeHandler(e:Event):void
{
_log += e.toString() + ' at ' + new Date();
_isLive = true;
if (!_dispatched) {
dispatchEvent(_completeEvent);
_dispatched = true;
}
}
private function _httpStatusHandler(e:HTTPStatusEvent):void
{
/* comment this in when you're sure what statuses you're after
var statusesLen:int = _liveStatuses.length;
for (var i:int = statusesLen; i > 0; i--) {
if (e.status == _liveStatuses[i]) {
_isLive = true;
dispatchEvent(_completeEvent);
}
}
*/
//200 range
_log += e.toString() + ' at ' + new Date();
if (e.status >= 200 && e.status < 300) _isLive = true;
else _isLive = false;
if (!_dispatched) {
dispatchEvent(_completeEvent);
_dispatched = true;
}
}
private function _ioErrorEventHandler(e:IOErrorEvent):void
{
_log += e.toString() + ' at ' + new Date();
_isLive = false;
if (!_dispatched) {
dispatchEvent(_completeEvent);
_dispatched = true;
}
}
private function _securityErrorHandler(e:SecurityErrorEvent):void
{
_log += e.toString() + ' at ' + new Date();
_isLive = false;
if (!_dispatched) {
dispatchEvent(_completeEvent);
_dispatched = true;
}
}
public function get isLive():Boolean { return _isLive; }
public function get log():String { return _log; }
}
}
and here's a basic usage example:
var urlChecker:URLChecker = new URLChecker();
urlChecker.addEventListener(Event.COMPLETE, urlChecked);
urlChecker.check('wrong_place.url');
function urlChecked(event:Event):void {
trace('is Live: ' + event.target.isLive);
trace('log: ' + event.target.log);
}
The idea is simple:
1. You create a checked
2. Listen for the COMPLETE event(triggered when it has a result
3. In the handler check if it's live and what it logged.
In the HTTP specs, 200 area seems ok, but depending on what you load, you might need
to adjust the class. Also you need to handle security/cross domain issue better, but at least it's a start.
HTH
An important consideration that George's answer left out is the URLRequestMethod. If one were trying to verify the existence of rather large files (e.g, media files) and not just a webpage, you'd want to make sure to set the method property on the URLRequest to URLRequestMethod.HEAD.
As stated in the HTTP1.1 Protocol:
The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response.
Hence, if you really only want to verify the existence of the URL, this is the way to go.
For those who need the code spelled out:
var _request:URLRequest = URLRequest(url);
_request.method = URLRequestMethod.HEAD; // bandwidth :)
Otherwise, George's answer is a good reference point.
NB: This particular URLRequestMethod is only available in AIR.

Resources