How do I access this variable without a global? - javascript

I'm trying to figure out how to make this work.
function foo(a) {
$('#this-button').show();
}
function buttonClicked() {
//get access to var a
}
HTML
<button id="this-button" onclick="buttonClicked();">
This is a simplified version of what I have but the idea is the same.
foo takes a variable, and then makes a button visible. When the button is clicked, I want to do more things with var a.
So like wait until the button is clicked to continue the function?
Can't seem to figure it out.
Thanks

Bind the click handler using jQuery. You can use jQuery.Proxy to bind a as an argument:
function foo(a) {
$('#this-button').show().click( $.proxy( buttonClicked, null, a ) );
}
function buttonClicked(a) {
// Use a here
}
and remove the JavaScript from your html attribute:
<button id="this-button" />
EDIT, if all you want to do is execute some code after the button is clicked, you can do something like this:
function foo(a) {
// Code up here executes before the button is clicked
$('#this-button').show().unbind( 'click.foo' ).one( 'click.foo', function ( ) {
console.log( a );
// This code executes after the click, and has access to a
} );
// Code down here executes before the button is clicked
}

You use an event handler content attribute. Those have access to:
Properties defined in the element (if any)
Properties defined in the form owner of the element 8if any)
Properties defined in the document
Properties in the global object (i.e. global variables).
Therefore, you can add the variable as a property of the element:
function foo(a) {
$('#this-button').show().prop('myProp', a);
}
function buttonClicked(a) {
alert(a);
}
foo(123);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="this-button" onclick="buttonClicked(myProp)">Click me</button>
Of course, using an event handler IDL attribute or an event listener would be a better practice.

This is the reason for a global, either that or create an object with functions that could use closure.

You can always access the global scope:
window.a = a;
But this is generally bad practice. Can you restructure the code so that both places have a available.
Ie
var a = {}; //set a
$("#button").click(function(){
// a is available here
});
foo(a);

HTML
<button id="this-button">
JS
function foo(a) {
$('#this-button').show();
$('#this-button').click(buttonClicked);
function buttonClicked() {
//a can be accesed here
}
}
Put buttonClicked method inside foo to get access of variable a

There's a few different ways to skin this cat but one method is to use a closure to capture the a variable:
var myButton = document.getElementById('this-button');
function foo(a) {
myButton.addEventListener("click", buttonClicked(a));
...
}
function buttonClicked(a) {
return function() {
console.log('buttonClicked', a);
}
}
foo('Success!');
In this case, the function buttonClicked returns a function that captures the value of a when run by the foo function. This resulting function is then passed to the event handler and run when triggered.
See the fiddle here: https://jsfiddle.net/ToddT/ae5h1src/

You could use HTML5 localstorage...
function foo(a) {
$('#this-button').show();
localStorage.setItem("variable_a", a); // variable in localstorage =variable_a
}
function buttonClicked() {
localStorage.getItem('variable_a');
//get access to var a
}
HTML5 localstorage allows you to store data on the client browser, and you can access it via getItem()... more info here: [w3schools], [jenkov.com]

Use closure.
(function(){
var dummy_a;
function foo(a) {
//$('#this-button').show();
dummy_a = a;
}
function buttonClicked() {
//get access to var a
alert(dummy_a)
}
foo(2)
buttonClicked()
})();

Related

Passing variable that detects specific button in jQuery

I created function that recognize which post has been clicked on.
jQuery(document).ready(function() {
jQuery(.recognize-post).on("click", function() {
var clickedButton = jQuery(this).data("id")
console.log("click button with post id: ", clickedButton)
button-id = "recognize-post"
...
...
})
})
}
html
<button id="recognize-post" class="recognize-post" data-id="<?php the_title() ?>">POST</button>
Code above works perfectly and in recognizes the correct post, but I need to pass clickedButton outside of this function and I don't know how to do so.
I need to have it in else if function, this is my attempt
else () {
...
} else if (button-id === "recognize-post") {
console.log(clickedButton)
}
Here the problem comes, clickedButton is underfined and need it to recognize post in exactly the same way how in on click function. Is it possible?
You can make a separate function that takes in the information you want to preserve.
// make a new function
function doSomethingWithTheIdAndBtn(id, btn) {
// take in arguments that represent the id or btn or whatever you need
else () {
...
} else if (id === "recognize-post") {
console.log(btn)
}
}
jQuery(document).ready(function() {
jQuery(.recognize-post).on("click", function() {
var clickedButton = jQuery(this).data("id")
console.log("click button with post id: ", clickedButton)
button-id = "recognize-post"
doSomethingWithTheIdAndBtn(button-id, clickedBtn) // call the function
...
...
})
})
}
So, the issue here is that if you declare a variable function in a given "scope" — in your case, the anonymous function's scope — it will only be defined inside of that scope. If you want to use the variable outside of the function, you need to declare it outside of the function.
So, for instance, if your code was
function foo() {
var myVariable = 0;
}
foo();
// This will throw an error, cuz myVariable is not defined in this scope
console.log(myVariable);
you could fix it by declaring the variable outside of the function's scope
var myVariable; // declare it outside of the function
function foo() {
myVariable = 0; // give it a value inside of the function
}
foo(); // call foo so that myVariable has a value
console.log(myVariable); // this will print 0. Success!

jQuery $(this) not working when inside a function

I have this simple function that copies some html, and places it in another div.
If I put the code for the function in the click event it works fine, but when I move it into a function (to be used in multiple places) it no longer works.
Do you know why this is?
If I console.log($(this)); in the function it returns the window element.
function addHTMLtoComponent () {
var wrapper = $(this).closest(".wrapper");
var component = $(wrapper).find(".component");
var componentCodeHolder = $(wrapper).find('.target');
$(componentCodeHolder).text(component.html())
//console.log($(this));
}
$(".js_show_html").click(function () {
addHTMLtoComponent();
});
codepen here - http://codepen.io/ashconnolly/pen/ebe7a5a45f2c5bbe58734411b03e180e
Should i be referencing $(this) in a different way?
Regarding other answers, i need to put the easiest one:
$(".js_show_html").click(addHTMLtoComponent);
since you called the function manually the function doesn't know the "this" context, therefore it reverted back to use the window object.
$(".js_show_html").click(function () {
addHTMLtoComponent();
});
// Change to this
$(".js_show_html").click(function () {
// the call function allows you to call the function with the specific context
addHTMLtoComponent.call(this);
});
Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
this in the context of the click() event is the element clicked. In the context of the function addHTMLtoComponent this no longer is a reference to the element clicked.
Try passing the clicked object to the function to maintain the object reference.
function addHTMLtoComponent ($obj) {
var $wrapper = $obj.closest(".wrapper");
var $component = $wrapper.find(".component");
var $componentCodeHolder = $wrapper.find('.target');
$componentCodeHolder.text($component.html());
}
$(".js_show_html").click(function () {
addHTMLtoComponent($(this));
});
The special keyword this, when you call a function by itself, is the window object (which is what you observed). For the behavior you need, just add a parameter to the function that loads the appropriate context:
function addHTMLtoComponent(context) {
var wrapper = $(context).closest(".wrapper");
var component = $(wrapper).find(".component");
var componentCodeHolder = $(wrapper).find('.target');
$(componentCodeHolder).text(component.html())
//console.log($(context));
}
$(".js_show_html").click(function() {
addHTMLtoComponent(this);
});
One thing you could consider is that addHTMLtoComponent() could be made into a jQuery function itself:
$.fn.addHTMLtoComponent = function() {
return this.each(function() {
var wrapper = $(this).closest(".wrapper");
var component = $(wrapper).find(".component");
var componentCodeHolder = $(wrapper).find('.target');
componentCodeHolder.text(component.html())
});
}
Now you can call it like any other jQuery method:
$(".js_show_html").click(function () {
$(this).addHTMLtoComponent();
});
The value of this in a jQuery method will be the jQuery object itself, so you don't need to re-wrap it with $(). By convention (and when it makes sense), jQuery methods operate on all elements referred to by the root object, and they return that object for further chained operations. That's what the outer return this.each() construction does.
Inside the .each() callback, you've got a typical jQuery callback situation, with this being set successively to each member of the outer jQuery object.
You have to pass the element as parameter to this function.
eg:
<div onclick="addHTMLtoComponent ($(this))"></div>

Getting "This" into a namespace in Javascript

I'm sure this should be a simple question but I'm still learning so here it goes:
I have some code to run a function on click to assign the clicked element's ID to a variable but I don't know how to pass the "this.id" value to the namespace without making a global variable (which I thought was bad).
<script>
fsa = (function() {
function GetTemplateLoc() {
templateId = document.activeElement.id;
alert(templateId + templateId2);
}
return {
GetTemplateLoc: GetTemplateLoc,
}
})();
//call the functions
$(document).on('click', '.template', function () {
fsa.GetTemplateLoc();
});
</script>
and HTML with random picture:
<img id="template-1" class="template" src="http://fc02.deviantart.net/fs70/f/2010/028/c/b/cb21eda885b4cc6ee3f549a417770596.png"/>
<img id="template-2" class="template" src="http://fc02.deviantart.net/fs70/f/2010/028/c/b/cb21eda885b4cc6ee3f549a417770596.png"/>
The following would work:
var fsa = (function() {
function GetTemplateLoc() {
var templateId = this.id;
alert(templateId);
}
return {
GetTemplateLoc: GetTemplateLoc,
}
})();
//call the functions
$(document).on('click', '.template', fsa.GetTemplateLoc);
jQuery generally calls functions you pass as event handlers with this set to the DOM object the event is associated with.
In this case it will call GetTemplateLoc() with this set to either .template element, so you can use this directly in the function and don't need to pass any parameters.
Important tip: Always declare variables using var. JavaScript has no automatic function-local scope for variables, i.e. every variable declared without var is global, no matter where you declare it. In other words, forgetting var counts as a bug.
Try this : You can directly use this.id to pass id of the clicked element where this refers to the instance of clicked element.
<script>
fsa = (function() {
function GetTemplateLoc(templateId ) {
//templateId = document.activeElement.id;
alert(templateId + templateId2);
}
return {
GetTemplateLoc: GetTemplateLoc,
}
})();
//call the functions
$(document).on('click', '.template', function () {
fsa.GetTemplateLoc(this.id);
});
</script>
If you're able to use jQuery within the GetTemplateLoc function, you could do something like this:
var fsa = (function() {
function GetTemplateLoc($trigger) {
var templateId = $trigger.attr('id'),
templateId2 = $($trigger.siblings('.template')[0]).attr('id');
alert(templateId + ' ' + templateId2);
}
return {
GetTemplateLoc: GetTemplateLoc,
}
})();
$(document).on('click', '.template', function () {
fsa.GetTemplateLoc($(this));
});
You can set GetTemplateLoc to expect a jQuery object as a parameter (the dollar sign at the beginning of $trigger can be used to distinguish it as a jQuery object rather than any other data type, it's not necessary but can help clarify things sometimes).
templateId will store the value of the clicked image's ID, and templateId2 will store the value of the other image's ID. I also added a space between the two variables in the alert.
If you can't use jQuery within GetTemplateLoc, you could do something like this:
var fsa = (function() {
function GetTemplateLoc(trigger) {
var templateId = trigger.id;
var templateId2 = trigger.nextElementSibling == null ? trigger.previousElementSibling.id : trigger.nextElementSibling.id;
alert(templateId + ' ' + templateId2);
}
return {
GetTemplateLoc: GetTemplateLoc,
}
})();
This time, the .template that triggered the event is passed into GetTemplateLoc, but this time it's not a jQuery object. templateId is assigned to the trigger's ID and then templateId2 is assigned in a ternary. First, the nextElementSibling of trigger is checked to see if it's null. If it is, we know that trigger is the second of the two .template elements. Therefore we can set templateId2 to the ID of trigger's previous sibling. If trigger's nextElementSibling is not null, then we know that trigger is the first template and we populate templateId2 with the ID of nextElementSibling. This exact method will only work with two .template's, if there are more you'll need some additional/different logic, probably to retrieve all .template IDs and then loop through them to add them to the alert message. Hope this helps.

How to pass parameters to a function declared like left = function()

How can I pass parameters to a function declared like something = function(){};
window.prototype.initInterface = function(){
this.mainPane = document.createElement('div');
this.mainPane.style.border="5px solid grey";
this.mainPane.style.margin="0px";
this.mainPane.style.width="420px";
this.mainPane.style.height="600px";
this.exitButton = document.createElement('input');
this.exitButton.setAttribute("type", "button");
this.exitButton.setAttribute("value", "exit");
this.exitButton.onclick = function(){
document.body.removeChild(this.mainPane);
};
this.mainPane.appendChild(this.exitButton);
document.body.appendChild(this.mainPane);
}
When the user presses the exit button I want to remove the mainPane from the body of the html page.
this.exitButton.onclick = function(this.mainPage){
document.body.removeChild(this.mainPane);
};
Does not work
How can I do this?
For your exitButton.onclick function to have access to variables you create in the enveloping initInterface function you want a to create a closure in the exitButton.onclick function by returning a function that performs the action you want and passing that the variable.
exitButton.onclick = function () {
return (function() {
document.body.removeChild(mainPane);
})(mainPane);
};
Read more on how closures work here and here and see a working example fiddle.
Alternatively, you forget about closures and walk up the DOM from the button which triggers the event to your mainPane
exitButton.onclick = function() {
// in here "this" is the object that triggered the event, exitButton
document.body.removeChild(this.parentNode);
}
As an aside, window.prototype does not exist if you are doing this in a browser; window is the object at the top of prototype chain in browser scripting. You want just window.initInterface = function () {} which is the exact same thing as function initInterface() {} because everything you do in javascript in the browser becomes a property of window.
This function is the function w/o function name. It could only be used once and you may not easy to find out what parameters should be passed.
You can create another function like :
function go(a1){}
And call it like window.prototype.initInterface = go(a1);
Or you can get some DOM parameters in this unnamed function by using functions like getDocumentById("DOM ID") etc.

How do you assign a JavaScript 'onclick' attribute dynamically?

I'm creating a button dynamically using JavaScript and at the same time assigning attributes such as 'ID', 'type' etc and also 'onclick' in order to trigger a function.
All works fine apart from the assignment of the 'onclick'. When clicked, the button is not triggering the function as it is supposed to. the function I'm trying to run is 'navigate(-1)' as seen below.
Where am I going wrong?
Here's my code:
function loadNavigation() {
var backButton;
backButton = document.createElement('input');
backButton.ID = 'backButton';
backButton.type = 'button';
backButton.value='Back';
backButton.onclick = 'navigate(-1)';
document.body.appendChild(backButton);
}
As the other said you should assign a function.
Just wanted to point out that in this case you want to pass a value so you need to assign an anonymous function (or a named function defined inline) like
button.onclick = function() {otherfunction(parameter)};
If the function you want to assign does NOT require a parameter you can use it directly
button.onclick = otherfunction;
Note that there is no parenthesis in this case
button.onclick = otherfunction(); // this doesn't work
won't work as it will call otherfunction as soon as it is parsed
you are assigning text to the onclick, try assigning a function.
backButton.onclick = function(){navigate(-1);};
You have to assign a function, not a string.
backButton.onclick = function wastefulDuplicationOfBackButton () {
navigate(-1);
}
Use a function instead of a string. For example,
backButton.onclick = function () { navigate(-1); };
You should assign a function, not a string:
//...
backButton.onclick = function () {
navigate(-1);
};
//...
backButton.onclick = function() { navigate(-1); }
In case this question is passed as a dupe, here is how to do it in current browsers
ES6
backButton.addEventListener("click",() => history.back());
Older but newer than onclick
backButton.addEventListener("click",function() { history.back() });

Categories

Resources