javascript variable substitution for this.refresh , window.refresh - javascript

In my phone-gap index.html javascript part, window.refresh is to be used for IOS and this.refresh for android. I want to use the same index.html for both. Through (navigator.userAgent.toLowerCase().match(), i can distinguish between IOS and android, but i don't want to apply this condition every time window. or this. is to be used. Can i apply this condition globally and assign value to a variable viz. 'this' for android and 'window' for IOS and then use that variable wherever required. Is this kind of a thing possible or any workaround so that multiple if -else statements can be avoided.
Any suggestions are most welcome.
Thanks in advance.

You could just try if this.refresh exists and call it. If its undefined you can fallback to window.refresh. Code example:
if(this.refresh === undefined) {
window.refresh();
} else {
this.refresh();
}
I'm not sure which way it would make the most sense, but I hope you get the concept: if something is undefined, you can't call it and need to figure out something else.

extending jsalonen answer
<script>
function browserRefresh()
{
if(this.refresh === undefined) {
window.refresh();
} else {
this.refresh();
}
}
</script>
and when ever you want to refresh just call
browserRefresh();

Related

Best way to solve this "ReferenceError: Function is not defined"?

I have an AEM page with multiple components, these components have a .js file with a function that encloses all the client side logic. We then call that function inside the component's HTML:
<script>
window.bootstrap_component(function() {
init_component_name();
});
</script>
As stated before init_component_name is the name of a function that encompasses all the logic we need:
function init_component_name() {
//DO STUFF
}
The wrapper bootstrap_component fuction is defined in the shared head.html of all our pages as:
<script>
window.bootstrap_component = function (handler) {
if (typeof handler === 'function') {
if (document.readyState === "complete" || document.readyState === "loaded" || document.readyState === "interactive") {
handler();
} else {
document.addEventListener("DOMContentLoaded", function() {
handler();
});
}
}
}
</script>
This works okay and we don't have any actual issues but we recently started using Bugsnag for error monitoring and reporting and we're getting reports for almost every component saying ReferenceError on page so/and/so init_component_name() is not defined.
The reason I think this is happening is because the init_component_name() function is not declared within the script tag and because this, function(init_component_name) has been attached to the window object it is executing fine and you don't see any console errors.
If I am correct would modifying those scripts tags to be like this work?
<script>
window.bootstrap_component(function() {
window.init_component_name();
})
</script>
A colleague of mine wants to add a timeout to the init_component_name functions of like 1ms but it rubs me the wrong way. Is there a more sensible approach?
If I am correct would modifying those scripts tags to be like this work?
window.bootstrap_component(function() {
window.init_component_name();
})
Yes, but you then have the problem that you're writing multiple data to the global namespace, window, which isn't ideal. What if another third-party script decides to override it?
Ideally you'd have a single namespace and put everything on there, and write only that namespace to window.
window.something = {};
something.bootstrap_component = { //...
and
something.init_component_name = () => {
//DO STUFF
}
Or better still, use modules (though that will need some light code refactoring).
Don't do the timeout hack. It's really, really horrible; what if scripts take longer than a second to load for some reason? You're also forcing your UI to wait a second, often unnecessarily. This hack tends to feature where chronology and scope has not been thought out properly.

HOW TO: Adobe Animate - gotoAndStop(); on a button click

I have created a project in .fla that was exporting to .swf however I now require it in HTML5 format. So I change the file conversion type and now require my ActionScript3 to be converted to JavaScript. However, This is not my strong suit.
I am currently trying:
this.stop();
this.close1_btn.addEventListener("click", function (closebtn)
{
this.gotoAndPlay(1);
});
this.store1_btn.addEventListener("click", function (store1_btn)
{
this.gotoAndPlay(11);
});
this.store2_btn.addEventListener("click", function (store2_btn)
{
this.gotoAndPlay(12);
});
this.store3_btn.addEventListener("click", function (store3_btn)
{
this.gotoAndPlay(13);
});
OVERVIEW: trying to listen to a symbol e.g close1_btn for clicks. when clicked it will link to and stop at a specified frame.
I expect a few bits to be wrong *maybe near the function () part?
Its a fairly simple map so shouldn't be too hard for someone who knows what they are looking at! Thanks so much for any help you can give!
I believe the issue is the function scope, which is a common mistake.
The addEventListener method has no implied scope, so the functions will get called on window. If you output this in your console when those buttons are clicked, you will probably see Window. To solve this, you can:
Bind your methods (docs)
Example:
this.close1_btn.addEventListener("click", function (closebtn)
{
this.gotoAndPlay(1);
}.bind(this));
Use the CreateJS on shortcut, which takes a 3rd parameter (docs)
Example:
this.close1_btn.on("click", function (closebtn)
{
this.gotoAndPlay(1);
}, this);
One important note is that if you play frame 0 again, that frame script will run again, adding another listener to each button each time, resulting in the functions called multiple times when a button is clicked. I recommend something this this:
if (!this.inited) {
// Your code
this.inited = true;
}
Thanks for your response.
I am now using the code you provided:
this.stop();
if (!this.inited) {
// Your code
this.close1_btn.addEventListener("click", function (closebtn)
{
this.gotoAndPlay(1);
}.bind(this));
this.store1_btn.addEventListener("click", function (store1btn)
{
this.gotoAndStop(11);
}.bind(this));
this.inited = true;
}
However, I get this in the output
WARNINGS:
Frame numbers in EaselJS start at 0 instead of 1. For example, this affects gotoAndStop and gotoAndPlay calls. (5)
Content with both Bitmaps and Buttons may generate local security errors in some browsers if run from the local file system.
Any further advice you could give would be appreciated...
cheers for your continued assistance!
The preview doesn't work when it opens in my browser, is this just because I haven't exported it fully and hosted it online?
So I can ignore these errors?
^^ if that's all cleared up. Do you have recommended way to export and host it on a webpage?
Thanks again buddy, appreciate it!

if/else statement in a function: using onclick as a switch

I have looked for solutions to this on google for what seems like an eternity, but I can't seem to formulate my search correctly, or nobody has posted the code I'm looking for earlier.
I am currently trying to make a function that will modify one or several margins of a div element. I want to use an if/else statement within the function, so that the onclick event will switch between the two conditions. This is what I have been working on so far;
function facebookToggle()
{
if($('#facebooktab').style.margin-left == "-250px";)
{
document.getElementById("facebooktab").style.marginLeft="0px";
}
else
{
document.getElementById("facebooktab").style.marginLeft="-250px";
}
}
I have tried twisting it around a little, like switching between "marginLeft" and "margin-left", to see if I was just using the wrong terms.. I'm starting to wonder if it might not be possible to combine jQuery and regular javascript? I don't know.. It's all just guesses on my part at this point.
Anyway, I have a div, which is now positioned (fixed) so almost all of it is hidden outside the borders of the browser. I want the margin to change onclick so that it will be fully shown on the page. And when it is shown, I want to be able to hide it again by clicking it.
I might be approaching this in the wrong way, but I really hope someone can help me out, or even tell me another way to get the same results. Thank you for any help you can give me.
You can see it in action at: http://www.torucon.no/test/
(EDIT: By the way, I am a complete javascript novice, I have no experience with javascript prior to this experiment. Please don't be too harsh, as I am aware I probably made some really stupid mistakes in this short code.)
Fixed problem:
function facebookToggle() {
var fb = $('#facebooktab'); // save reference to element
if( fb.css('margin-left') === '-250px' ) {
fb.css('margin-left', '0px');
} else {
fb.css('margin-left', '-250px');
}
}
A jQuery object doesn't have a property called style, so
if($('#facebooktab').style.margin-left == "-250px";)
// also remove this semi-colon! ^
is going to throw an error. Some options for accessing CSS properties are (1)
document.getElementById("facebooktab").style.marginLeft;
which you have correctly used, or (2)
$('#facebooktab').css('margin-left');
Consider being consistent and using the same approach for all three cases. You can assign css properties with jQuery like
$('#facebooktab').css('margin-left', '-250px');
With these things in mind, here's a suggested rewrite:
function facebookToggle() {
var fb = $('#facebooktab'); // save reference to element
if( fb.css('margin-left') === '-250px' ) {
fb.css('margin-left', '0px');
} else {
fb.css('margin-left', '-250px');
}
}
and here's another that uses a predefined CSS class:
#facebooktab {
margin-left: -250px; /** default state */
}
.no-left-margin {
margin-left: 0px;
}
function facebookToggle() {
$('#facebooktab').toggleClass('no-left-margin');
}
toggleClass
jQuery is just a JavaScript library. It is written in JavaScript and its API is in JavaScript. Your event handler could be rewritten as follows:
function facebookToggle() {
var el = document.getElementById('facebooktab');
if (el)
el.style.marginLeft = (el.style.marginLeft == '250px' ? 0 : -250) + 'px';
}
Since you are mixing jQuery with javascript, you got mixed up. Apart from what paislee's advice. you are do this too.
if($('#facebooktab')[0].style.margin-left == "-250px";){
document.getElementById("facebooktab").style.marginLeft="0px";
}
else {
var fb = document.getElementById("facebooktab");
fb.style.marginLeft="-250px";
}

javascript include once, declare function once, bind once

Is there a way to include a javascript file only once or declare a function only once? The issue I am having is that I have an HTML module that contains a javascript include. Well this module is loaded in a loop, and therefore that file is loaded multiple times. I've worked out most of the kinks, but what bothers me is that I know the same function is getting created multiple times, and this look can be as many as 30 iterations. To me, I don't like the fact that the same function is getting created over and over. Should I care? Is there a way I can prevent this? I know I can detect when a function exists, can I put the function declaration in between an if statement?
Update
I've tried out one of the suggestions:
if(typeof btnSendInvite_click != 'function')
{
function btnSendInvite_click()
{
alert("#invite_guest_" + $(this).attr("event_id"));
return false;
}
}
but that doesn't work. I've also tried
if(!btnSendInvite_click)
{
function btnSendInvite_click()
{
alert("#invite_guest_" + $(this).attr("event_id"));
return false;
}
}
but it doesn't work. What happens is that I have this line:
$(document).ready(function()
{
$(".btnSendInvite").bind("click", btnSendInvite_click);
});
and when the button gets clicked, that functions is executed six times, which is the amount of times that the file was included which tells me that the function is being created multiple times... I think.
Update
So after a lot of struggling, this problem is turning into something different than what I thought. The bind is being called multiple times, so it's getting bound multiple times, and therefore calling the function multiple times. I guess my next question is, is there a way to bind a function to a control only once? I've tried the jquery "one" already and it doesn't work.
Yes, you can (run on jsfiddle).
if (!window.myFunction) {
window.myFunction = function() {
//...
}
}
Edit: In your case it would be:
if (!window.btnSendInvite_click) {
window.btnSendInvite_click = function() {
alert("#invite_guest_" + $(this).attr("event_id"));
return false;
}
}
The call to bind() also has to be somewhere in that conditional block.
Note: The following variant won't work, at least not on all browsers:
if (!window.myFunction) {
function myFunction() {
//...
}
}
Edit 2: For your update:
Declare a variable when you call bind.
if (window.iBoundThatStuff!=true) {
iBoundThatStuff=true;
//call bind() here
}
Having JS included in a loop is ridiculous. Move your JS out of the loop.
JS can tell if function was defined but fixing bad server side loop in JS is definitively a bad practice.
Yes you should worry about not including your script file several times and not to declare the function several times...
For the first part, you may want to look into changing your html structure so the js file is only included once (even though js files are cached by the browser, and the second time may not actually go to the server -- depending of several factors... there's still a penalty)
Now as for declaring your function only once, remember that functions are also object (1st class citizens) in js, so you can test if a function is already define as if you were testing an object.... if(!window.myFunc) { window.myFunc = function(){} }...
You may want to look a bit into functions and scoping in js.. here are some links
http://robertnyman.com/2008/10/09/explaining-javascript-scope-and-closures/
http://www.yuiblog.com/blog/2010/02/24/video-crockonjs-3/
http://www.slideshare.net/douglascrockford/crockford-on-javascript-act-iii-function-the-ultimate

Add console.profile statements to JavaScript/jQuery code on the fly

We have a thick client app using jQuery heavily and want to profile the performance of the code using firebug's console.profile API. The problem is, I don't want to change the code to write the profile statements. Take this example:
var search=function(){
this.init=function(){
console.log('init');
}
this.ajax=function(){
console.log('ajax');
//make ajax call using $.ajax and do some DOM manipulations here..
}
this.cache=function(){
console.log('cache');
}
}
var instance=new search();
instance.ajax();
I want to profile my instance.ajax method, but I dont want to add profile statements in the code, as that makes it difficult to maintain the code.
I'm trying to override the methods using closures, like this: http://www.novogeek.com/post/2010/02/27/Overriding-jQueryJavaScript-functions-using-closures.aspx but am not very sure how I can achieve. Any pointers on this? I think this would help many big projects to profile the code easily without a big change in code.
Here is the idea. Just run the below code in firebug console, to know what I'm trying to achieve.
var search=function(){
this.init=function(){
console.log('init');
}
this.ajax=function(){
console.log('ajax');
//make ajax call using $.ajax and do some DOM manipulations here..
}
this.cache=function(){
console.log('cache');
}
}
var instance=new search();
$.each(instance, function(functionName, functionBody){
(function(){
var dup=functionBody
functionBody=function(){
console.log('modifying the old function: ',functionName);
console.profile(functionName);
dup.apply(this,arguments);
console.profileEnd(functionName);
}
})();
console.log(functionName, '::', functionBody());
});
Now what I need is, if i say instance.ajax(), I want the new ajax() method to be called, along with the console.profile statements. Hope I'm clear with the requirement. Please improvise the above code.
Regards,
Krishna,
http://www.novogeek.com
If you only want to modify the single instance of "search" then this should work:
$.each(instance, function(name, method){
if (typeof method !== 'function') return;
instance[name] = function() {
console.profile(name);
var ret = method.apply(this, arguments);
console.profileEnd(name);
return ret;
};
});
I know this is from a long time ago but I wanted to add this in case other people find this answer. You can make anonymous/private functions work by adding a name to each one. The other comments mention doing it manually bit I wanted to explain how to:
$('.stuff').each(function() { ... });
to
$('.stuff').each(function workOnStuff() { ... });

Categories

Resources