Processing.js doesn't allow external javascript bind in firefox - javascript

I'm trying to send data to a processing script. But for some reason the variable pjs below binds to the canvas "competence1" and enters the first if statement, but then the bindJavascript(this)-call returns error, but only in firefox. (works perfectly in chrome):
[pjs.bindJavascript is not a function]
var bound = false;
function initProcessing(){
var pjs = Processing.getInstanceById('competence1');
if (pjs != null) {
// Calling the processing code method
pjs.bindJavascript(this);
bound = true;
//Do some work
}
if(!bound) setTimeout(initProcessing, 250);
}
Environment: Mac OS X - Lion;
OBS! The bindJavascript(this)- method exists in the pde script loaded in the canvas-tag

By wrapping up all my script in a varable-map and by using the second way for setTimeout to be called i can follow each state and control the result.
So wrap it up-->
var ex = {
init : function(canId){
var canId = canId;
// check the if bound
// bind in this closure
// set new timer
}
}
setTimeout-->
setTimeout('ex.init("'+canId+'")', 2000);
and ofcourse add the parameter in so it can hold that value during it's own execution. So processing works just fine and i should use closure more often, that's the solution.

I had the same problem. I was using almost identical JS to you (which I got from the Pomax tutorial), and it was working fine. However, when I added the following preload directive (to load a backdrop), then suddenly my initProcessing function stopped working.
/* #pjs preload="metal_background.jpg"; */
The error message was the same: pjs.bindJavascript is not a function
On debugging, I could see that the pjs object did indeed not have a bindJavaScript function exposed, even though there is one declared in my PDE file.
It turns out this was purely down to timing... the preload had slowed down the initialisation of the processing object, so the second time round the 250ms loop, the pjs object existed, but didn't yet have its bindJavaScript function.
I am not 100% sure how Processing.js does this object construction, but in this case, a simple solution was just to check whether bindJavaScript actually was defined! I changed my code to the following:
var bound = false;
function initProcessing() {
var pjs = Processing.getInstanceById('mySketchId');
if(pjs != null) {
if(typeof(pjs.bindJavaScript) == "function") {
pjs.bindJavaScript(this);
bound = true;
}
}
if(!bound) setTimeout(initProcessing, 250);
}
After this it worked fine!

Related

TypeError: Failed to set the 'buffer' property on 'AudioBufferSourceNode': The provided value is not of type 'AudioBuffer

I am working on the existing codoCircle. Put the volume down.
It works out as expected.
Now i want to use the same code here in codepen and i get this error
TypeError: Failed to set the 'buffer' property on 'AudioBufferSourceNode': The provided value is not of type 'AudioBuffer
I did a bit of research and i have found the first answer useful.
The answer says
At the time i assign in the playSound player.buffer = buffer, buffer is still undefined because the load callback hasn't fired.
This makes sense to me, so then i have tried to do a
setTimeout like:
setTimeout(playSound, 9000);
It did not work out.
Do you know any workaround for this? And why in CodeCircle works and not in Codepen?
his makes sense to me, so then i have tried to do a setTimeout like ..
That's more a quickfix, but tricky as you don't know for sure if everything is loaded.
The solution is to wait until every sample is loaded. The best way is to use Promises for that, but that needs a (large) refactor and isn't compatible with all the current browsers (so you need then Babel or Typescript etc).
So I made a easier approach: for every sample I have created a boolean variable that will be set to true when loading has finished (in the callback function)
var loadedHat = false;
var loadedSnare = false;
var loadedBd = false;
loadSample('cl_hat_3001.wav', function (buffer) {
hat = buffer;
loadedHat = true;
startWhenAllLoaded();
});
loadSample('brp_snrim1.wav', function (buffer) {
snare = buffer;
loadedSnare = true;
startWhenAllLoaded();
});
loadSample('bd08.wav', function (buffer) {
bd = buffer;
loadedBd = true;
startWhenAllLoaded();
});
Then I wrapped your code to start in a start function and made a startWhenAllLoaded, which starts when all the tree booleans are true
function startWhenAllLoaded()
{
if(!started && loadedHat && loadedSnare && loadedBd){
started = true;
start();
}
}
The edited codepen is here
NB: Not sure if everything works now OK, the error is gone but I think the code need some tweaking

object.onload fails with IE and Edge

I'm trying to dynamically preload list of files which may be anything between images and JavaScript files. Everything is going supersmooth with Chrome and Firefox, but failing when I'm trying to preload JavaScript files with Edge. Edge still can handle images for example but no js files. And yes I've tried with addEventListener, it's not working either.
Edge doesn't give me any errors.
var object = {};
object = document.createElement('object');
object.width = object.height = 0;
object.data = path/to/javascriptfile.js
body.appendChild(object);
object.onload = function(){
console.log('hello world')
//not firing with edge
}
Anything relevant I'm missing?
UPDATE: Didn't get any success after the day. Will probably leave it for now and just skip preloading script files with edge until i find a solution.
Perhaps worth a check - from msdn:
The client loads applications, embedded objects, and images as soon as
it encounters the applet, embed, and img objects during parsing.
Consequently, the onload event for these objects occurs before the
client parses any subsequent objects. To ensure that an event handler
receives the onload event for these objects, place the script object
that defines the event handler before the object and use the onload
attribute in the object to set the handler.
https://msdn.microsoft.com/en-us/library/windows/apps/hh465984.aspx
Edit, a clarification:
You should attach the event listener before the element is added to the page.
Even doing that I'm not sure if it'll work or not though. But to make sure you've exhausted all options try the example below:
function doLoad() {
console.log('The load event is executing');
}
var object = {};
object = document.createElement('object');
object.width = object.height = 0;
object.data = 'path/to/javascriptfile.js';
object.onreadystatechange = function () {
if (object.readyState === 'loaded' || object.readyState === 'complete') doLoad();
console.log('onreadystatechange');
}
if (object.addEventListener) {
object.addEventListener( "load", doLoad, false );
console.log('addEventListener');
}
else
{
if (object.attachEvent) {
object.attachEvent( "onload", doLoad );
console.log('attachEvent');
} else if (object.onLoad) {
object.onload = doLoad;
console.log('onload');
}
}
var body = document.getElementsByTagName("body")[0];
body.appendChild(object);
If this doesn't work, you could perhaps preload using "image" instead of "object" in IE: https://stackoverflow.com/a/11103087/1996783
Working temporary solution is to put onload event directly to script element instead of object. It's sad since it works like a charm in Chrome & FF.
It turns out, object.data with css source did not load either. I don't know if it's a bug since it still can load image from to object.data.
But show must go on.
Cheers, eljuko

Why does waitForKeyElements() only trigger once despite later changes?

For several years I've used the waitForKeyElements() function to track changes in webpages from a userscript. However, sometimes I've found it doesn't trigger as expected and have worked around out. I've run into another example of this problem, and so am now trying to figure out what the problem is. The following is the barest example I can create.
Given a simple HTML page that looks like this:
<span class="e1">blah</span>
And some Javascript:
// function defined here https://gist.github.com/BrockA/2625891
waitForKeyElements('.e1', handle_e1, false);
function handle_e1(node) {
console.log(node.text());
alert(node.text());
}
setInterval(function() {
$('.e1').text("updated: "+Math.random());
}, 5000);
I would expect this code to trigger an alert() and a console.log() every 5 seconds. However, it only triggers once. Any ideas?
Here's a codepen that demonstrates this.
By design and default, waitForKeyElements processes a node just once. To tell it to keep checking, return true from the callback function.
You'll also want to compare the string (or whatever) to see if it has changed.
So, in this case, handle_e1() would be something like:
function handle_e1 (jNode) {
var newTxt = jNode.text ();
if (typeof this.lastTxt === "undefined" || this.lastTxt !== newTxt) {
console.log (newTxt);
this.lastTxt = newTxt;
}
return true; // Allow repeat firings for this node.
}
With the constant string comparisons though, performance might be an issue if you have a lot of this on one page. In that scenario, switching to a MutationObserver approach might be best.

Automation script is not working?

This is the first time I get my hands on with automation instruments in xcode The script works well for all button taps but the one making server connection. I don't know the reason
Here is the script I tried so far
var target = UIATarget.localTarget();
target.pushTimeout(4);
target.popTimeout();
var window=target.frontMostApp().mainWindow()
var appScroll=window.scrollViews()[0];
appScroll.logElementTree();
UIATarget.localTarget().delay(2);
appScroll.buttons()[1].tap();
The above script works up to showing the UIActivityIndicator instead of moving to next controller after success
I know There must be a very simple point I am missing. So help me out
UIAutomation attempts to make things "easy" for the developer, but in doing so it can make things very confusing. It sounds like you're getting a reference to window, waiting for a button to appear, then executing .tap() on that button.
I see that you've already considered messing with target.pushTimeout(), which is related to your issue. The timeout system lets you do something that would be impossible in any sane system: get a reference to an element before it exists. I suspect that behind-the-scenes, UIAutomation repeatedly attempts to get the reference you want -- as long as the timeout will allow.
So, in the example you've posted, it's possible for this "feature" to actually hurt you.
var window=target.frontMostApp().mainWindow()
var appScroll=window.scrollViews()[0];
UIATarget.localTarget().delay(2);
appScroll.buttons()[1].tap();
What if the view changes during the 2-second delay? Your reference to target.frontMostApp().mainWindow.scrollViews()[0] may be invalid, or it may not point to the object you think you're pointing at.
We got around this in our Illuminator framework by forgetting about the timeout system altogether, and just manually re-evaluating a given reference until it actually returns something. We called it waitForChildExistence, but the functionality is basically as follows:
var myTimeout = 3; // how long we want to wait
// this function selects an element
// relative to a parent element (target) that we will pass in
var selectorFn = function (myTarget) {
var ret = myTarget.frontMostApp().mainWindow.scrollViews()[0];
// assert that ret exists, is visible, etc
return ret;
}
// re-evaluate our selector until we get something
var element = null;
var later = get_current_time() + myTimeout;
while (element === null && get_current_time() < later) {
try {
element = selectorFn(target);
} catch (e) {
// must not have worked
}
}
// check whether element is still null
// do something with element
For cases where there is a temporary progress dialog, this code will simply wait for it to disappear before successfully returning the element you want.

Javascript variable is changing its value, reasons that can cause such?

I am debugging the weirdest error I ever seen. At this point my code look like this.
var counter = 0;
function setup() {
var count = ++counter;
var test = false;
function getSetter(arg?) {
if (typeof (arg) !== "undefined") {
console.log(["setting",count, arg]);
test = arg;
} else {
console.log(["getting",count, test]);
return test;
}
}
return getSetter;
}
var verticalScrollDisabled = setup();
this is in a closed scope and i have made sure that the variable test is not accessed outside the above code. I can change it to any name with same result. Updated such its clear that its not accessed outside of this scope. And updated with a counter to show its not written over.
Copy pasting result from the console.
["enter scroll area", div.fxs-blade-content, true, "3511>401 || 577>585"] HorizontalScrollBindingHandler.ts:12
["setting", 1,true] HorizontalScrollBindingHandler.ts:132
disable vert HorizontalScrollBindingHandler.ts:72
n.Event {originalEvent: WheelEvent, type: "mousewheel", isDefaultPrevented: function, timeStamp: 1422128039040, jQuery21104183536011260003: true…} HorizontalScrollBindingHandler.ts:15
["getting", 1,false] HorizontalScrollBindingHandler.ts:15
["getting", 1, false] HorizontalScrollBindingHandler.ts:75
[false, false]
Issue
As commented, my problem is that as seen in the trace. the variable get set to true, but when its being accessed again its false. I cant get why that can happen.
and the handler attached to mousescroll event.
var scrollHorizontally =(e) => {
// console.log([verticalScrollDisabled(), scrollInAction]);
console.log(e);
if (verticalScrollDisabled() && !scrollInAction)
return;
console.log([verticalScrollDisabled(), scrollInAction]);
This code has been working for ever and nothing changed to it other than we in some seperate code are opening a popup and closing it again. Is there anything that could cause events to be doing something out of the expected related to if the window loses focus or something? Again, the test variable is not altered outside the verticalcrollDisabled function, so I have no clue why it can go change itself to false, notice the ["setting", true].
Just verified that the popup is not the cause.
Heres the hole file. https://gist.github.com/s093294/e49ed46d2680c1403e3b
Answer is, validate your assumptions.
I assumed that the file was not loaded twice since it being a module defined with define and loaded with requirejs. This didnt hold up since there was some ID mapping that made two ids load this file and as one of the comments said, this is the thing that makes it possible.
I resolved the requirejs configuration and problem vent away.

Categories