How do you call a function to run specific code? - javascript

I'm making my website mobile-friendly and I'm loading different CSS files based on if the user is using a touch device or not. I have edited the question to instead create an alert box to simplify the question.
Please note: LoadCSS(style.css) has been changed to alert()
I want to run javascript code stored in a variable.
From my research, eval(variable) runs/executes the variable as code, but this isn't working.
The code I want to run is stored in "isTouchscreen" and "notTouchscreen".
-- isTouchscreen.js --
function ifTouchscreen(isTouchscreen, notTouchscreen) {
// isTouchscreen being alert('Touchscreen device!')
// notTouchscreen being alert('Not a touchscreen device!')
if(userIsUsingATouchScreen) {
eval(isTouchScreen)
} else {
eval(notTouchScreen);
// expecting "eval" to execute the variables as javascript commands/functions
}
}
-- index.html -- [Edited to use "alert"]
<!--alert() being commands that I want to be executed-->
ifTouchscreen("alert('Touchscreen device!')", "alert('Not a touchscreen device!')")
What I expect to happen is for the "isTouchscreen" variable to be run as javascript code if the user is using a touchscreen device, and for the "notTouchscreen" variable to be run as javascript code if the user is not using a touchscreen device.
I expect an "alert" to take place which doesn't happen.
How do you call a function in javascript with a variable/condition [function(variable/condition)] and get the function to execute said variable/condition as javascript code?

In your current code, LoadCSS(...) is getting called twice, and the values returned from those calls (probably undefined) are being passed as arguments to your function.
It's possible that something like this would work instead:
ifTouchscreen("LoadCSS('mobile-friendly.css')", "LoadCSS('normal.css')")
But what you really want to do is pass in a function as a "callback" for your code to call into.
ifTouchscreen(() => LoadCSS('mobile-friendly.css'), () => LoadCSS('normal.css'))
function ifTouchscreen(isTouchscreen, notTouchscreen) {
if(userIsUsingATouchScreen) {
isTouchScreen();
} else {
notTouchScreen();
}
}

You can load css dynamically like this:
function loadCssDynamically(href){
var head = document.getElementsByTagName('head')[0];
var link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = href;
link.media = 'all';
head.appendChild(link);
}
function ifTouchscreen(isTouchscreenHref, notTouchscreenHref) {
if(userIsUsingATouchScreen) {
loadCssDynamically(isTouchscreenHref)
} else {
loadCssDynamically(notTouchscreenHref);
}
}
ifTouchscreen('http://website.com/css/stylesheet1.css', 'http://website.com/css/stylesheet2.css')

What happens is that both functions get executed before the call to ifTouchScreen.
You must add quotes around it:
ifTouchscreen("LoadCSS('mobile-friendly.css')", "LoadCSS('normal.css')")
It is also possible I misunderstand and LoadCSS is actually returning javascript code as a text.

Related

skip function if missing script

I am building within a content management system, so I have to get creative with load functions.
I have 2 scripts running on load. A random background image for the home page, and the navigation menu. I included both in a separate script that runs on load. The only page to get the background image is the home page. So on all the other pages that do not have the random home script linked, the script errors out and the menu does not load.
I would like the background image to execute first. A bad work around is to load the menu first, and let the random home script break on any sub pages but this is NOT ideal and I am hoping to find a solution.
I would like to load the image first, and then run the navigation script. And in the event that the image script is undefined, I would like it to skip, and execute the navigation script.
Here is my code:
function start() {
var randH = randomHome();
var undefined = false;
if (randH === undefined) {
loadNAV();
}
else {
randomHome();
loadNAV();
}
}
window.onload = start;
The 2 functions are linked in separate files and work just fine when listed like this:
function start() {
loadNAV();
randomHome();
}
window.onload = start;
But this leaves errors on sub pages that do not get the background image. So i am searching for a no error answer that loads the background image first, or skips it, and then the navigation.
Create an anonymous function that runs on load and checks for the existence of the start() function. If it exists, call it.
window.onload = function() {
if (start) {
start();
}
};
Remove the undefined = false line. undefined is a reserved keyword and already evaluates as "falsy" and what you've done will cause a lot of issues for anything else relying on the undefined keyword. Instead, change the if statement to use == instead of ===. == evaluates equality, === evaluates identity.
If you're trying to prevent the randomHome() script from running if it doesn't exist, the same code would be used inside the start() function.
function start() {
// only call randomHome function if it exists
if (randomHome) {
var home = randomHome();
// anything else to do with the homes goes here
}
// load the nav regardless of whether randomHome exists
loadNAV();
}
This is what ended up working. thanks all.
function start() {
if(window.randomHome == undefined )
{
loadNAV();
}
else {
randomHome();
loadNAV();
}
}
window.onload = start;

Chrome Extension JavaScript Program Not Working

I am learning chrome extension programming from the tutorial here .
You can find the full code for the chrome extension here.
The code snippet where I tried to remove few links:
var clean_twitter = function(){
var ugly = [];
ugly.push('.Trends module trends');
ugly.push('.flex-module');
ugly.push('.MomentMakerHomeModule-header');
ugly.push('.Footer module roaming-module');
ugly.push('.flex-module-header');
$('.promoted-tweet').hide(); // oops! :P
for(var i=0;i<ugly.length;i++) {
var u = $(ugly[i]).find('a'); // also 'b'
u.text('');
}
}
The code tries to remove some buttons and div from the twitter website.
Now, when I put it on my pc nothing happens. I tried to remove the change link inside the trends box and it isn't removed.
Please help if I am doing something wrong here. Thanks.
At the beginning of the process_new_tweets function there's a comment explaining how the presence or absence of .mini-profile in the DOM is used as a flag.
In summary, the absence of the .mini-profile element in the DOM means that the function returns and won't proceed any further. Since the tutorial was written it would appear that Twitter no longer has a .mini-profile element anywhere in its DOM, so the function is always returning and script execution is not proceeding any further.
Remove the following lines from the beginning of the process_new_tweets function:
var mp = document.getElementsByClassName('mini-profile');
if(mp.length === 0) { return; }
And the elements that you've selected in your clean_twitter function will be removed from the DOM as expected.

Using JavaScript or JQuery how do I determine when a DOM element is added to the page?

An external JavaScript adds a DOM element to a page.
Using JavaScript or JQuery how do I determine when this DOM element is added to the page?
You basically have three choices, one of which isn't available on all browsers:
Get a notification from the other script that it's added an element (if it provides one)
Poll (I'd use setTimeout and reschedule each following check on purpose) to see if the element appears. E.g.:
var CHECK_INTERVAL = 100; 100 = 1/10th second, choose appropriate
function checkForElement() {
/* ...check for the element... */
if (/*...you found the element...*/) {
// Do something with it
}
else {
// Check again after a brief pause
setTimeout(checkForElement, CHECK_INTERVAL);
}
}
setTimeout(checkForElement, CHECK_INTERVAL);
Use a mutation observer, which is the replacement for the broken old mutation events. This lets you register a callback to be called on certain mutation events. Support is reasonable but — quelle shock — IE didn't get them until IE11.
If you have access to that external javascript file, you can just call a function in your page from that file just after you add an element. If you don't have this facility or there is not event triggering in between, you can keep on checking existence of such element in a certain interval using javascript setInterval() method.
var chekElement = function (){
// this will rerun function every second
var chekElemRecursiveTimer = setTimeout(chekElement, 1000);
var someElement = $('.someElement');
if (someElement){
alert("its on page!");
clearTimeout(chekElemRecursiveTimer);
}
}
// run function in page or from external js file
chekElement();
another way to checked this
var chekForElement = function (){
var chekElementTimer = setTimeout(chekForElement, 1000);
if ($('.chcekedElementclass').length > 0){
alert("found in page");
clearTimeout(chekElemRecursiveTimer);
}
}
// run function in page or from external js file
chekForElement();

Google Chrome editing Javascript on the fly

I've tried to ease my life by using Google Chrome's devtools and as I've tried to modify javascript of page on fly but it seems to behave unexpectedly
I have this function that is called every frame of the game
View.prototype.onHit = function() {
for(var i = 0; i < this.obstacles.length; i++) {
if(this.obstacles[i].dealsDamage) {
//deal damage
} else {
//do something else
}
}
}
and when I open it on chromes "Sources tab" and pause execution and add something simple such as
console.log("hey");
it starts printing text "hey" on console as expected but the moment i modify some code such as the if check to
if(!this.obstacles[i].dealsDamage) {
//do something else
} else {
//deal damage
}
inverting the behaviour and save the document, the code doesnt take effect and the logging source changes to View.js (old)
and anything I change after that doesn't affect the running javascript
The "(old)" script normally should only appear if the more complex changes are applied. Namely, if you change a function parameter number or start (and lamently stop) using a variable from outer scope.
If live edit fails to work in such simple use-case as you describe, it could be a good thing to file to http://crbug.com

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

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!

Categories