I have some JS in a file, and some JS on a page.
If I try to access my function via NucleusPreview, it can't be found
If I access it via window.NucleusPreview, it is found
Why is that? Am I doing something wrong, or do I need to be explicit when accessing objects in window scope when in another function?
Update: I was creating NucleusPreview inside the onReady, but moved it so I think the window scope was a red herring. The problem is that when calling it in onReady, gave it time to load the file, but when I moved it out I started calling it too early.
The JS in the the file is basically:
var NucleusPreview;
(function ($) {
NucleusPreview = function NucleusPreview(source) {
//ctor stuff
};
NucleusPreview.prototype.AdjustCaption = function AddCaption() {
//caption stuff
};
})(jQuery);
My JS on the page:
$('.nucleus-preview').each(function eachNucleusPreview(index, element) {
var jElement = $(element),
vidId = jElement.data('video-id'),
np = new NucleusPreview($(element)); //Uncaught RefError: NucleusPreview is not defined
_wq.push({
id: vidId,
onReady: function (video) {
np.AdjustCaption();
}
});
});
As long as the first bit of code you provided is executed first and none of the code is executed prior to the DOM being loaded (you can put all of this code in a document.ready() callback to ensure that is the case), you should be able to. Run this code snippet and wait a moment, you will see that it works without qualifying window.
In the example below, I've placed all the code in a document.ready() callback (although that is not required for the code to run) to ensure that you don't try to access $('.nucleus-preview') before the DOM is ready.
Additionally, doing this will keep NucleusPreview out of the global scope in the first place, which is always a good idea.
// Always make sure the DOM is fully loaded prior to scanning for DOM elements.
// This can be done by placing all of your code in a "document.ready()` callback
// function as I'm doing here or by placing the code at the end of the HTML document,
// just before the close of the body (</body>).
$(function(){
// Now NucleusPreview is scoped to this function, which keeps it out of the
// global scope and that's always good, so you don't pollute the window.
var NucleusPreview;
(function ($) {
NucleusPreview = function NucleusPreview(source) {
//ctor stuff
};
NucleusPreview.prototype.AdjustCaption = function AddCaption() {
//caption stuff
};
})(jQuery);
var _wq = []; // Added to allow code to execute
$('.nucleus-preview').each(function eachNucleusPreview(index, element) {
var jElement = $(element),
vidId = jElement.data('video-id'),
np = new NucleusPreview($(element)); // <-- Works just fine!
_wq.push({
id: vidId,
onReady: function (video) {
np.AdjustCaption();
}
});
});
});
console.log($('.nucleus-preview'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="nucleus-preview"></div>
<div class="nucleus-preview"></div>
<div class="nucleus-preview"></div>
Related
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!
Can you set variables in the beginning of a file to be set through out?
Example:
var works = $('#id1');
var span = $('.icon');
works.focus(function() {
if(this.value.length == 0)
span.hide();
});
works.keyup(function() {
if(this.value.length > 0 && !span.is(':visible'))
span.stop().show();
else if(this.value.length == 0)
span.stop().hide();
});
The variable span inside the function doesn't work. Instead of adding var span = $('.icon'); in each function is it possible I can make it work?
Thanks alot
Ideally you would declare them first, then set them later when the DOM is ready.
<script>
var myFunVariable;
var anotherVariable;
$(function(){
myFunVariable = $("#someElement");
anotherVariable = $("#anotherElement").children();
});
</script>
Yes, you can have global variables, but if you initialize them in a <script> block in the <head> they'll be empty. The DOM won't have been loaded.
You can instead do this:
$(function() {
var span = $('.whatever');
$('something.else').click(function() {
// span will work here
});
});
Not quite the same as globals, but in a way that's better since true globals are kind-of a bad idea. Anything declared with var inside the $(function() { ... }) code will be effectively global to all code in that initialization function.
Oh, and note that putting the initialization code in a function invoked with $() is the jQuery way of deferring execution until the DOM is ready. That will work in a script in the <head>, and it'll also work if you import your scripts at the end of the <body> as many luminaries now advise.
I want to create an element in place where javascript function run.
<script>
var uniqid='an unique Id';
document.write('<iframe id='+uniqid+'></iframe>');
someAsyncFunction(callback)
</script>
in other part of code I set additional parameters for this element
<script>
callback=function(paramfromcallback){
getElementById(uniqid).url=paramfromcallback;
}
</script>
but this is not work in IE. I can't find this element.
My problem is:
There are many elements on page, for each element must be set only this element parameters
I do not know which element is parent, I do not know the script element ID. I need insert an element in place where are first script called
First part of code executed before any call back, and I want to keep it asynchronous
Depending on the order your script blocks are hit, you could have a number of issues here. document.write() creates interesting problems with inline script. More often than not, any script that comes after it won't be able to use the results of the doc.write until after the page finishes loading -- or from within another document.write() block. Waiting for the window to be fully loaded could solve your issue. How about something like this -
Defined Once:
function callback(id) {
var el = document.getElementById(id);
if (el !== null) {
el.url = 'http://google.com';
}
}
Then anywhere you want to write out an iframe:
(function(){
var id = 'an_unique_Id';
document.write('<iframe id='+id+'></iframe>');
var l = window.onload;
var n = function() { someAsyncFunction(function() { callback(id); }); };
window.onload = (typeof l == 'function') ? function() { l(); n(); } : n;
})();
First, use:
document.getElementById(uniqid).url = 'http://google.com';
The method is part of the document object, so you can only use it by prepending document.
Second, use:
var callback = function() {
Will not break your code probably, but variables should be declared with var
I am trying to execute JavaScript code to the webpage when the user clicks the browser action. It worked very well, and when I tried to put it on the background page it messed up.
I want specific code to execute once and when the icon is clicked again, different code to run. I tried to do the following.
//Background page
<Script>
function goNow() {
var live = 2;
chrome.tabs.executeScript(null,
{code:"Code"});
}
function Shutdown(){
var live = 1;
chrome.tabs.executeScript(null,
{code:"Code"});
}
function runLive(live){
if (live==1) {goNow()}
else {Shutdown()}
}
chrome.browserAction.onClicked.addListener(runLive)
</script>
Of course that 'Code' is JavaScript code that works very well when injected into the page.
chrome.browserAction.onClicked.addListener passes a tab object to a callback function, you can't just pass you own parameter there.
Declaring a variable inside a function (by using var keyword) makes it available only inside this function.
You code should be something like this:
//global variable
var live = 1;
function goNow() {
live = 2;
chrome.tabs.executeScript(null, {code:"Code"});
}
function Shutdown(){
live = 1;
chrome.tabs.executeScript(null, {code:"Code"});
}
function runLive(tab){
if(live==1){goNow()}
else{Shutdown()}
}
chrome.browserAction.onClicked.addListener(runLive);
I have replicated a toggle functionality from this site:
http://www.williamsprofessionalpainting.com/FAQ.php
Here is the updated version which renders the basic toggle function with minimum CSS:
http://jsfiddle.net/NinjaSk8ter/yXNmx/
Your code is working fine, but jsFiddle is wrapping it in a function. In other words, it ends up looking something like:
window.onload = function() {
function ToggleFAQ(Ans) {
...
}
};
The function is defined within the onload handler, so when your onclick tries to call it, it doesn't exist.
If you change the drop-down on the top-left of your fiddle to "no wrap", it all works fine. See this modified version.
On your JSFiddle - if you change the wrap method to "no wrap(head)" and it simply works.
Alternatively - you can declare the function as a global var:
ToggleFAQ = function (Ans)
{
//..
}
what renders as
jQuery(document).ready(function(){
//when defined like this - ToggleFAQ will still be visible when the
//"ready" event finishes.
ToggleFAQ = function (Ans)
{
//..
}
}
the wrap you selected puts your code in a function passed to jQuery's "dom-ready" event - and that's a closure that once is executed - all local variables are "vaporized".