I have a variable declared:
var recent;
And I wrote a function which needs the variable passed into it. However, I believe what is happening is the variable is being passed as a string. The var is represented by thisVar:
function detachVariable(thisDiv, thisVar, fileName) {
//Check if this section is visible:
if($(thisDiv + " li").length > 0) {
$(thisDiv).prepend(thisVar);
} else {
//If variable does not have content stored, store it:
if(thisVar === undefined) {
$("#site-nav li a").parents().removeClass("nav-active");
$(this).addClass("nav-active");
$(thisDiv + " ul.top-level").load('assets/includes/' + thisFile, function () {
$(this).show().siblings().hide();
ajaxAudioController();
});
//If variable has content, show it:
} else {
$("#site-nav li a").parents().removeClass("nav-active");
$(this).addClass("nav-active");
$(thisDiv).prepend(thisVar);
}
}
}
My click function:
$("#site-nav .nav1").on("click", function (event) {
detachVariable("#recent", "recent", "recent.php");
event.preventDefault();
});
Is there a way I can pass my variable into the function?
If I understood correctly.. all you have to do is remove the quotes around recent.. see below,
detachVariable("#recent", recent, "recent.php"); //removed quotes
Just omit the quotes around the second parameter. With them, you are indeed passing a string literal instead of the variable.
Variables in Javascript have a global scope. So you can literally just use recent == whatever instead of trying to pass it as a parameter.
Related
I have something like the following:
$('#country1').change(function() {
var hrc = "Yes";
if (className == "HR") {
var hrc = "Yes";
return true;
} else {
var hrc = "No";
return false;
}
Then I am pulling this with JSON into a SP List like:
$('.submitdataAccounts').on('click', function() {
var data = {
__metadata: {
'type': 'SP.Data.ChangeOfAddressListListItem'
},
"high_risk_country": hrc,
};
This part works correctly as everything else in the form posts successfully into the list
If I leave it as a static variable at the top of the page it passes correctly but does not work if it's based on the fuction.
Thanks,
Declare the variable outside the functions, so it is a global variable, and then you can acces it everywhere in your code. If you give a global variable an another value, it is redefined and gets that value until an another value change.
Is it possible to access an object inside another if statement? Because the situation is like this.
I have an edit button and it will set a <div> to contenteditable. so if I press the cancel button, the text inside the <div> should also reset. and now my javascript goes like this
$('.class').on('click','.etc',function(){
var orig = {};
$a = $(this).('.etc').text().trim(); // just getting the text of the button
if($a == "Edit") // just checking if edit button
{
orig.text = $(this).find('original-text').text(); // should store the original text
}
else if ($a == "Cancel")
{
// the div must be set to the original text
alert(orig.text); // undefined
}
});
I'm really at lost here
Declare the variable at a scope where it is accessible by both the if and the else condition or maybe at a global scope. But make sure it's initialized before you try to access its properties!
var orig = {text:""};
$('.class').on('click','.etc',function(){
if($a == "Edit") // just checking if edit button
{
orig.text = $(this).find('original-text').text();
}
else if ($a == "Cancel")
{
alert(orig.text);
}
});
The issue is in the scope of the variable orig. JS has function level lexical scope.
So to answer your title question, yes you can access a variable created in an in in if in the else so long as the else is sure to occur after the if has occurred at least once. But that's not really what's causing your problems.
Your issue is that you are trying to persist this variable beyond the onclick function. When that function ends so does the life of the variable. The simple fix is to declare it outside the function and utilize JS closures.
var orig = {};
$('.class').on('click', function () {
if ($(this).text() == "Store") {
orig.text = $("#display").text();
} else if ($(this).text() == "Cancel") {
alert(orig.text);
}
});
I had to adapt it a bit because I don't know your full HTML, but it works.
UPDATE
To avoid the bad practice of global variables you can create a closed scope for the whole thing like so:
(function () {
var orig = {};
$('.class').on('click', function () {
if ($(this).text() == "Store") {
orig.text = $("#display").text();
} else if ($(this).text() == "Cancel") {
alert(orig.text);
}
});
})();
And here's that in practice
I'm making a hangman game and I'm writing a function to search for a letter in the word. So when the user clicks on a letter, I am grabbing the text in there and searching for it in the chosen word.
The code I have written is:
function searchLetter()
{
var aLetter = letter.toLowerCase();
var aChosenWord = chosenWord.toLowerCase();
//chosenWord is a global variable initialised in another function
if(aChosenWord.indexOf(aLetter) != -1)
alert("Letter is there")
else
{
alert("Letter not found")
}
}
The variable 'letter' is a global variable and was given a value based on what has been clicked:
$(function(){
$('a').click(function () {
letter = $(this).text();
$(this).slideUp();
searchLetter()
});
});
I'm not sure what I've done wrong here. I put in a bunch of alert boxes and my code seems to be grabbing the letters correctly.
When I run this however, every time I'm getting the value of -1 for indexOf; i.e. the letter is not found in the word.
I cannot figure out what it is I've done wrong here!!
Any input is greatly appreciated,
Thanks
While I am not an advocate for unnecessary global vars, the code below should do what you need.
HTML
<span id="chosenWord">Some awesome word</span>
<br />
a
b
d
e
JS
var letter,
chosenWord = document.getElementById('chosenWord');
$('a').on('click', function () {
if (chosenWord.innerHTML.toLowerCase().indexOf($(this).text().toLowerCase()) !== -1) {
console.log('Found ' + $(this).text())
} else {
console.log($(this).text() + ' not found.');
}
});
JSFiddle demo
It would be better to create a context for your global variables, e.g.:
jQuery(function($) {
var chosenWord;
$('a').click(function() {
var $this = $(this);
$this.slideUp();
searchLetter($this.text(), chosenWord);
});
// link that generates new game?
$('.generate-new-word').function() {
chosenWord = generateNewWord();
});
});
The searchLetter() function receives the letter and word as its arguments and is thus decoupled from this code.
I've also written an example of how the word generation function can be integrated. As with searchLetter() this function has no knowledge of any global state.
This would be the implementation of your searchLetter():
function searchLetter(letter, chosenWord)
{
var aLetter = letter.toLowerCase();
var aChosenWord = chosenWord.toLowerCase();
if(aChosenWord.indexOf(aLetter) != -1) {
alert("Letter is there")
} else {
alert("Letter not found")
}
}
Organizing your code this way reduces the chance of introducing bugs in the code, because the context is managed exclusively inside only a small part of your code.
Did you declare the global variable with? (check the scope):
var letter = ''
Why not prefer passing the variables within the argument list of the searching function?
I'm using dajaxice to retrieve a json attribute - that I would like to be global. I'm not sure why my global var is always "undefined":
var recent_id;
$(function(){
recent_id = Dajaxice.ticker.get_home_timeline(get_home_timeline_callback);
alert(recent_id);
});
function get_home_timeline_callback(data){
if(data==Dajaxice.EXCEPTION){
alert('Error! Something happens!');
}else{
var parsed = JSON.parse(data.home_timeline);
var parsed_id = {'parsed_id':parsed[0].id_str};
console.log(parsed_id);
}
return parsed_id;
}
#dajaxice_register
def get_home_timeline(request):
home_timeline = oauth_req(
'http://api.twitter.com/1/statuses/home_timeline.json?count=1',
settings.TWITTER_TOKEN_KEY,
settings.TWITTER_TOKEN_SECRET
)
return simplejson.dumps({'home_timeline': home_timeline })
Is this a bad way to access a var to be used in another ajax function?
Seems like async issue. Modify your get_home_timeline_callback function as following
function get_home_timeline_callback(data){
if(data==Dajaxice.EXCEPTION){
alert('Error! Something happens!');
}else{
var parsed = JSON.parse(data.home_timeline);
var parsed_id = {'parsed_id':parsed[0].id_str};
console.log(parsed_id);
}
//debug
alert(parsed_id);
//since the value has come, now assign it to the global variable
recent_id = parsed_id;
}
It seems like the variable scope issue. The scope of the variable parsed_id is declared within the else statement within the { }, so its scope is within the else statement. And when you return the parsed_id outside the brackets it might be giving undefined.
Go through the scope of variables explanation here
Change your function as shown below.
function get_home_timeline_callback(data)
{
var parsed_id = "";
if(data==Dajaxice.EXCEPTION)
{
alert('Error! Something happens!');
}
else
{
var parsed = JSON.parse(data.home_timeline);
parsed_id = {'parsed_id':parsed[0].id_str};
console.log(parsed_id);
}
return parsed_id;
}
Now here the scope of the variable parsed_id can be accessed anywhere within function.
Hope this solves your problem if not sorry. This was my assumption that the scope might be affected.
I am stuck at the following code. At first I'll describe the use-case: The function "addPreset" gets called with an instance of ColorGradient. When calling this.listController.addItem(...) a callback function named onSelect ist supplied, which gets called everytime the onSelect-event on the listController-item is triggered. What I wanted to do is wrapping the call to GLab.ColorSlider.applyColorGradient(...) into a new closure, so that the assigned value of addPreset's "cg" argument"* will be "caught" inside it. But it doesn't work.
PROBLEM: Now everytime addPreset is called, the value of cg (being passed with a call) will override all values that bad been assigned before. However, this.presetList holds always correct values (the ones I expected to be caught inside the closure-function. Even inserting an anonymous function for breaking the scope doesn't help.
Please help me. :-)
Thanks, so far
function addPreset(cg) {
if (!(cg instanceof ColorGradient)) {
throw new TypeError("PresetManager: Cannot add preset; invalid arguments received");
}
var newIndex = this.listController.addItem(cg.getName(), {
onSelect: (function(cg2) {
return function() {
// addPreset's scope should now be broken
GLab.ColorSlider.applyColorGradient(cg2);
console.log(cg2);
}
})(cg)
});
this.presetList[newIndex] = cg;
}
#bobince: of course you can.
the code snippet above is part of PresetManager.js and the listController is an instance of the class ListWrapper.js
http://code.assembla.com/kpg/subversion/nodes/GradientLab/lib-js/PresetManager.js
http://code.assembla.com/kpg/subversion/nodes/GradientLab/lib-js/ListWrapper.js
#Matt: cg is an instance of ColorGradient. A custom class of myself. Further more, it is assured, that always "valid" values are passed in as cg. (When you'd have a few minutes you can download the whole assembla repo as zip-archive. Unzip and test in FF > 3.5 with Firebug console enabled.)
Answer can be found in this question: Doesn't JavaScript support closures with local variables?
Someone please correct me if I am wrong, as I am still fairly new to JavaScript closures and scope. But it would seem to me that the wrapping anonymous function you have is simply there to provide a proper scoped variable/closure for the function it is returning. Could this be simplified as such?
function addPreset(cg) {
if (!(cg instanceof ColorGradient)) {
throw new TypeError("PresetManager: Cannot add preset; invalid arguments received");
}
var closured = cg;
var newIndex = this.listController.addItem(cg.getName(), {
onSelect: function() {
// addPreset's scope should now be broken
GLab.ColorSlider.applyColorGradient(closured);
console.log(closured);
}
});
this.presetList[newIndex] = cg;
}
Just want to tell you, that I finally solved my problem by myself. It cost me almost 2 days (in the sparetime) to puzzling it out, but I think its worth that. At least my code remained elegant and I definitely got the whole thing with closures. Let's have a look:
My faulty code
Part 1 of 2:
function addPreset(cg) {
if (!(cg instanceof ColorGradient)) {
throw new TypeError("PresetManager: blablabla");
}
// calls the function in Part 2
var newIndex = this.listController.addItem(cg.getName(), {
onSelect: (function(cg2) {
return function() {
// addPreset's scope should now be broken
GLab.ColorSlider.applyColorGradient(cg2);
console.log(cg2);
}
})(cg)
});
this.presetList[newIndex] = cg;
}
Part 2 of 2:
// The method being called by this.listController.addItem(..)
function addItem(caption, args) {
var _this = this,
currIndex,
id,
newItem
itemSelectCb = (!!args && typeof args.onSelect == "function") ?
args.onSelect :
undefined;
currIndex = this.numOfItems;
id = this.ITEM_ID_PREFIX + currIndex;
newItem = this.$itemTemplate
.clone()
.text(caption)
.attr("id", id)
.bind("click", function(e) {
e.stopPropagation();
if (typeof itemSelectCb != "undefined") {
itemSelectCb();
}
_this._onSelect($(".ListWrapperItem").index(this));
})
.appendTo(this.$container);
this.numOfItems = $("." + this.DEFAULT_ITEM_CLASS, this.$container).length;
return currIndex;
}
The fixed code
The bug was in Part 2; when calld jQuery's bind-method for adding an click-event-listener I used an anonymous function (= new closure), but referenced itemSelectCb inside; so the anonymous function's scope stayed "connected" to the one of addItem. Everytime I called addItem, an other value were assigned toitemSelectCb what lead to the unknown sideeffect, that all references to itemSelect inside previously created anonymous functions are pointing to that value. What meant, that the last assigned value, had been used by all anonymous function.
To "break" the scope, all I had to do was to modify the lines of Part 2 where the event-handler for jQuery's bind was created. The fixed code looks then like this:
function addItem(caption, args) {
var _this = this,
currIndex,
id,
newItem
itemSelectCb = (!!args && typeof args.onSelect == "function") ?
args.onSelect :
undefined;
currIndex = this.numOfItems;
id = this.ITEM_ID_PREFIX + currIndex;
newItem = this.$itemTemplate
.clone()
.text(caption)
.attr("id", id)
.bind("click", (function(itemSelectCb) {
return function(e) {
e.stopPropagation();
if (typeof itemSelectCb != "undefined") {
itemSelectCb();
}
_this._onSelect($(".ListWrapperItem").index(this));
}
})(itemSelectCb))
.appendTo(this.$container);
this.numOfItems = $("." + this.DEFAULT_ITEM_CLASS, this.$container).length;
return currIndex;
}