Creating a JavaScript global array with static elements?
The problem isn't that removeFunction doesn't have access to bigArray. The problem is in your onclick attribute, and the id you're putting on the link:
$('#div').append("<a href='#' id='bigArray[i]' onclick='removeFunction(bigArray[i])'>Element bigArray[i]</a><br />");
In the onclick, you're referring to i, but A) I'm guessing i isn't a global, and B) Even if it is, it will not have the value of i that you used to render that row. The code will look for the value of a global i variable as of when the link is clicked.
Separately, you're creating multiple elements with the same id value, which is bigArray[i] (not bigArray[0], bigArray[1], etc.)
You could use the value instead, like this:
$('#div').append("<a href='#' id='bigArray[" + i + "]' onclick='removeFunction(" + i + ")'>Element bigArray[i]</a><br />");
The changes there are:
For the id, I changed it to: "...id='bigArray[" + i + "]'", which will output id='bigArray[0]', then id='bigArray[1]', etc., instead of repeatedly outputting id='bigArray[i]' (literally.
I just pass the index into removeFunction, again by putting the value there, not a reference to the variable i: "... onclick='removeFunction(" + i + ")' ..."
Then your removeFunction would be:
function removeFunction(i) { // <== i, not id
bigArray.splice(i, 1); // <== real code, not pseudocode
renderArray(bigArray);
}
I would not recommend doing it that way, but it's the minimal fix.
There's no need to pass bigArray to anything. It's a global.
FWIW, I would recommend refactoring so you don't have to re-render the whole thing every time.
Define a variable at the global scope first that will hold your "bigArray", then assign the value to it once you receive the data through your ajax call.
var bigArray;
$.ajax({
bigArray = bigArrayFromAjax;
renderArray(bigArray);
});
... then your other functions should have access to it.
Related
I am building a vue component and I want to call a function defined in Vue methods by calling the onClick attribute when modifying innerHTML. However, it gives me error, "showModal is not defined" as shown below.
Here is my showModal function, I am just trying to console some data to make sure that the function is called:
methods: {
showModal: function() {
console.log("function is called")
//this.$refs.myModalRef.show();
//this.account=account;
}
}
and here is where i am trying to call that function in js by onclick function:
var inputText = document.getElementById("fileContents");
var innerHTML = inputText.innerHTML;
for(var i=0;i<this.violations.length;i++){
var index=innerHTML.indexOf(this.violations[i]);
if(index>0) {
innerHTML = innerHTML.substring(0, index) +"" + innerHTML.substring(index, index + this.violations[i].length) + "</span>" + "" + innerHTML.substring(index + this.violations[i].length);
inputText.innerHTML = innerHTML;
}
}
error: (index):1 Uncaught ReferenceError: showModal is not defined
at HTMLAnchorElement.onclick ((index):1)
Am I calling it in a wrong way?
Thanks!
Edit:
Thanks to #Ferrybig - I know I am able to call the function, however I have another problem; I want to pass the current word that I am changing its html to the funciton like this: onclick='myMethod(violations[i])' I tried setting this.violations array to be global like this:
window.violations=this.violations;
but again, (variable i) which is the index of current word in the array, is not global variable to be passed to 'myMethod' and it says (i is not defined). I cannot set i to global variable because it's an index incremented each time in the loop.
I thought about sending the current index of the tag I am editing to the function, 'myMethod', so I can track which tag I am in and its known by the html in the vue component but not sure how to do that..
Any other suggestions?
When using Vue templates, you get access to easy to use syntaxes that decrease programming time, and it is highly recommended that you start renderering your page using Vue instead.
In the case you are unable to use Vue for renderering your page, you can still use other bad techniques:
First, start by adding a created lifecycle method for created that moves a reference for your Vue method up to the global scope: created(){window.myMethod =this.myMethod;}
Since we then added the method to the global scope, you can just reference it using mymethod inside your vanilla onclick handler.
Note that the above workaround does not support multiple instances of your Vue component, but supporting this becomes way harder, and you should really use proper Vue components in that case.
Hi Just try to remove href='#' and instead add href="javascript:void(0)" along with #click="showModal"
This may help
You are not using a Vue handler in your call. Change onclick to #click
so:
#click="showModal"
or, alternatively,
v-on:click="showModal"
You have to use Vue syntax onClick like Method Event Handlers
So
innerHTML = innerHTML.substring(0, index) +"" + innerHTML.substring(index, index + this.violations[i].length) + "</span>" + "" + innerHTML.substring(index + this.violations[i].length);
need change to
innerHTML = innerHTML.substring(0, index) +""+ "<span style=\"background-color: yellow\">" + innerHTML.substring(index, index + this.violations[i].length) + "</span>" + "" + innerHTML.substring(index + this.violations[i].length);
I am trying to put a class name stored in a variable into my JQuery where I want the class to be, this should change which class is affected depending on the parameter passed through the URL query string.
I have built the class name and stored it in the 'param' variable as below.
var param = '".' + "proj" + location.search.substring(6) + '"';
$(param).css('display', 'inline');
And want to change the css on the class inside of it but this does not seem to work for me. Perhaps because it tries to change the css of the variable rather than what is inside of it.
If not how can I solve this or if so, is there a better way I could go about this?
You're confusing a string literal to be only enclosed by double quotes ", while that is not the case. Remove them
var param = '.' + "proj" + location.search.substring(6);
Set the param variable as the location substring (assuming that this substring is correctly getting the desired result from your URL) - then use that in the jQuery by joining with the common portion as follows.
var param = location.search.substring(6);
$('.proj' + param).css('display', 'inline');
You will need to ensure that a) you have the jQuery library and b) you have the jquery code wrapped in a $(document).ready(function(){}) wrapper.
Also - its usually better to add / remove a class rather than directly affecting the CSS in the jquery
var param = location.search.substring(6);
$('.proj' + param).addClass('displayInline');
//CSS
.displayInline{display: inline}
I am running into a problem people have posted before: JavaScript dynamic parameters
But my code uses nodes rather than innerHTML assignments, so the existing SO post doesn't seem to apply to my code.
I want to dynamically generate HTML buttons in a table. For each button, I want to call a function with parameters that depend on the button's index/position in the table. First I tried just using lambda functions with the variable over which I was incrementing. This didn't work, so I also tried dynamically named variables, meaning each button should be passing a differently named variable to deal with lazy-loading effects. But this didn't work either. You can see both versions of what I tried in the code below:
This code I paste below is in a for-loop. In the following, I increase i by 1 each time. offset and jj are unchanged within the loop.
var variableDynamic = i.toString();
window['variableName' + variableDynamic] = i + offset;
upvote.onclick = function() {
upVoteA(i + offset, jj);
//upVoteA(window['variableName' + variableDynamic] , jj);
};
upvote.innerHTML = "Upvote"
Someone told me to look into closures, so following this recommendation: http://www.usepatterns.com/blog/javascript-closures I rewrote the onclick function declaration as:
upvote.onclick = function() {
var a = i + offset;
var b = kk;
function closeIt(){
upVoteA(a,b);
}
closeIt();
};
This still has the same effect that every button calls upVoteA with the same parameter, namely the last/highest value.
I realize I could refactor my code to turn these into .innerHTML set statements and then I'd print the variable and it would be set as a printed statement instead of a lazily-loaded variable. But I'd like not to do that if possible. (apologies that it's not technically lazy loading, the name seems reasonably apt)
Is there a way to make my code work? And why are the closures failing? I thought closures should preserve the environment they were created in, but that is not the case with my code. Which portion of the "environment" are preserved with closures?
This is a very bad answer, but it works
var funcStr = "function dummy() { upVoteA(" + (i + offset) + "," + jj + "); }";
eval(funcStr);
upvote.onclick = dummy;
But if you have something better, please let me know.
Playing with some jQuery bits and pieces, I can't seem to get it quite right.
What I'm looking to do is loop through the items on a page, and apply a custom click handler to them. This way when I populate the page I just need to fill out the correct ID and the jQuery can automate filling in the link.
The problem I have is both events are firing with the same output, and I can't work out why. I have 2 which I am using as buttons,
<img id="LightButton11Of" src="images/lightbulb_off.png" style="width:32px;
height:32px; vertical-align:middle " alt="off" >
<img id="LightButton11On" src="images/lightbulb_on.png" style="width:32px;
height:32px; vertical-align:middle" alt="on">
and the following code
$(document).ready(function(){
$("[id^=LightButton]").each(function(i,item){
if ($(this).attr('id').substr(13,2)=="On"){lightfunction="1";}
if ($(this).attr('id').substr(13,2)=="Of"){lightfunction="0";}
alert($(this).attr('id').substr(13,2));
numLight = $(this).attr('id').substr(11,2);
strLight = "*1*" + lightfunction + "*" + numLight + "##";
teststr = $(item).attr('id') + " - " + strLight;
alert(teststr);
$(this).bind("click",function(){
SendEvent("OWN","18",strLight,"OK");
});
});
});
The alert(teststr) gives exactly the output I'm expecting, but it seems when I'm binding it is actually binding to all elements and not just the singular item from that iteration of the each loop.
What am I doing wrong!?
Cheers,
Tim.
What am I doing wrong!?
Your variables are all global.
This code in the click handler:
SendEvent("OWN","18",strLight,"OK");
...refers to the global variable strLight, which will have the value set in the last iteration of your .each() loop.
You should declare all of your variables with var, which will make them local to the function, so then each of the click handlers will use the local variable from its containing scope. (Which, thanks to the "magic" of closures, will still exist even though your each callback will have finished by the time the click events occur.)
$("[id^=LightButton]").each(function(i,item){
var lightfunction = this.id.substr(13,2)=="On" ? "1" : "0";
var numLight = this.id.substr(11,2);
var strLight = "*1*" + lightfunction + "*" + numLight + "##";
$(this).bind("click",function(){
SendEvent("OWN","18",strLight,"OK");
});
});
(Note also that there's no need to use $(this).attr('id') when this.id gives you the same value in a way that is faster to type, read and execute, and it's neater to set the value of lightfunction using a ternary operator instead of two if statements.)
I am using DeepModel to access nested attributes in a Backbone.js model. So this works fine:
this.model.set({'chart_configs.mentions_bar_graph.date': "cats"});
However, I'd like to use a variable as part of my key so like:
this.model.set({'chart_configs.'+ this.chartName + '.date': "cats"});
Is this some how possible? I know that I can do it by
this.model.attributes.chart_configs["mentions_bar_graph"].date = "cats";
But that, obviously, does not trigger a "change" event else where in my code.
thanks!
Model#set can be called in two ways:
m.set('key', 'value');
m.set(an_object_of_keys_and_values);
So you should be able to get past the "you can't define an object literal like that" problem by using the first form of Model#set:
this.model.set('chart_configs.' + this.chartName + '.date', 'cats');
If DeepModel doesn't like that then you could do it the long way:
var values = { };
values['chart_configs.' + this.chartName + '.date'] = 'cats';
this.model.set(values);
An object is an object whether it has a name or not and set only cares about the keys and values.