i plan to show some images on the page and when the user press up button some related new images will be shown. I have been achieving that by changing the "src" attribute already existing image html tag.
i have json data like [["a","b"],["c","d"]] which gives the name of images like a.jpg, b.jpeg etc.
Here is the problem i can not pass the array value to jquery click object. my javascript functions as below:
var a; // a global variable holding the json array [["a","b"],["c","d"]]
function rileri(){ //img next
var ix=parseInt($("#up").attr('rel'));
ix=(ix+1)%a.length;
for(var i=0;i<2;i+=1){
$("#k"+i).attr("src","img/m/t/"+a[ix][i]+".jpg");
$("#k"+i).click(function() { rgetir(a[ix][i]);}); //problem is here!!
}
$("#up").attr('rel',ix); // i keep index data of appearing img on "rel"
}
function rgetir(n){ //img down ajax
$("#brc").load("data/rgetir.php", {'name':n});
}
I wonder how can i bind click event and if there is any better solutions ?
html is like that (no "src" at start, is it ok ?):
<img id="k0"/><img id="k1"/>
<input id="up" rel="0" type="button" onclick="rileri()" value="Next">
Yeap the main problem is passing the multidimensional array value to a function :(
The problem has nothing to do with "multidimensional arrays." It is that you are using i inside the assigned click value, and i changes with every iteration of the loop. Each assigned click value holds a reference to i, so when rileri is finished each points to the same value. You need to break the reference, usually done by passing i to a function and binding the click in there.
There are many flavors of using a function to break a reference, but since you're using jQuery and iterating an array, we'll use $.each:
(what follows is untested but should serve as an example)
function rileri(){
var ix=parseInt($("#up").attr('rel'),10);
ix=(ix+1)%a.length;
$.each(a[ix], function (i) {
var img_name = this;
$("#k"+i)
.attr("src","img/m/t/"+img_name+".jpg")
.click(function () {
rgetir(img_name);
});
if (i >= 2)
{
return false;
}
});
$("#up").attr('rel',ix);
}
Here is a simple fiddle that shows your problem
http://jsfiddle.net/MHJx6/
The problem is your ix and i variables are closures, so at the time the event runs they have the wrong values as you can see in this example.
I tried to write some code that will do what I think you are trying to do below. It would be easier if I knew what you were trying to do (use case). Maybe this is what you want?
var a; // a global variable holding the json array [["a","b"],["c","d"]]
function rileri(){ //img next
$("#k0").click(function() { handleClick(0); });
$("#k1").click(function() { handleClick(1); });
}
function handleClick(index) {
var ix=parseInt($("#up").attr('rel'));
ix=(ix+1)%a.length;
$("#k"+index).attr("src","img/m/t/"+a[ix][index]+".jpg");
$("#up").attr('rel',ix);
}
Related
It's my first app, I have been in tutorial hell for one year and decided to start my own little app.
So in this part Im using an addEventListener(),which appends and create text. The text is a variable created by the sum of the results of other functions (I don't know if this is relevant), but the thing is once I submit a button and creates the HTML element, if I keep submitting the elements will pile up. So I tried removeChild() but it didn't work because the variable was already created with its value, or...brought an error that can't removedChild() of undefined (since I tried to clear the values before appending), also tried to reseting the variable by adding a .innerHTML=""; but I don't know where to locate it. I also checked the replaceChild() but it didn't make sense, since everytime you click should be a new first event created. I tried the empty().append() but seems it's for jquery.
Seems that I need to learn a lot about scopes.
let frase;
function armarPersonaje() {
if(!reversarNombre() || !descMes || !descDia){
return false
} else {
frase = nombreReves + descMes + descDia;
return true
}
}
let div;
let h3Element;
function mostrarPersonaje(){
let div = document.getElementById('container')
let h3Element = document.createElement("h3")
h3Element.className = "addedH3"
if(frase.length > 0){
h3Element.appendChild(document.createTextNode(frase));
div.appendChild(h3Element)
}
}
enter image description here
Here's the complete code
https://jsfiddle.net/santiso/mzv3ct5e/
The problem here that in your last function mostrarPersonaje() you are always creating the element h3Element before the if , and even if you empty the parent node which is the div it will create a new element whit class addedH3 the very next click !
How to fix it ? first do not create until you enter the condition , then delete it when ever you click again even before the condition
here is the fiddle
and this is what i added
let oldH3Element = document.querySelector('h3.addedH3')
if(oldH3Element) oldH3Element.parentNode.removeChild(oldH3Element)
I have a html5 Canvas animation that I am doing on Adobe Animate and tweaking with some code.
I have a portion on the animation that will be like a combobox with all the links to navigate through the different frames. The thing is, I don't want to be creating a bunch of EventListener to many buttons because from experience I know that doesn't work so well. So I am trying to think of a more creative solution. This is my idea.
Create an array that will contain all the buttons.
Assing a variable for each target frame.
Create a for loop with a function inside that assigns the listener to the selected button and then points it to the desired frame (variable)
This is what I have got so far, (not much)
var combobox = [this.btncasco , this.btnbanyera , this.btnLumbrera , this.btnproapopa, this.btnestriborbabor ];
for (var i=0; i<combobox.length; i++) {
var clipcasco = gotoAndStop(0);
var clipbanyera = gotoAndStop(2);
var cliplumbera = gotoAndStop(4);
var clipproapoa = gotoAndStop(6);
var clipestriborbabor = gotoAndStop(8);
}
Would that be feasible ?
In your example, you are just assigning the result of gotoAndStop (with no scope, so likely you're getting an error in the console)
I think you are looking for something like this:
for (var i=0; i<combobox.length; i++) {
// This is kind of complex, but if you just reference "i" in your callback
// It will always be combobox.length, since it references the value of i
// after the for loop completes variable.
// So just store a new reference on your button to make it easy
combobox[i].index = i*2; // x2 lines up with your code 0,2,4,etc.
// Add a listener to the button
combobox[i].on("click", function(event) {
// Use event.target instead of combobox[i] for the same reason as above.
event.target.gotoAndStop(event.target.index);
}
}
You might have the same problem as your other StackOverflow post where the button is undefined (check the console). There is actually a bug in Animate export right now where children of a clip are not immediately available. To get around this, you can call this.gotoAndStop(0); at the start to force it to update the children.
I have the following code, which preprocesses some response data from an AJAX call before displaying it (the displaying part is not shown). In particular, it sets the src attribute of the image in each li element of the response.
$(response.items).filter('li').each(function(i){
$('img', this).attr('src', 'images/Picture.jpg');
if (i==0){
console.log(this);
console.log(response.items);
}
});
The output of console.log(this) shows that the src attribute gets set correctly in the context represented by this, but the output of console.log(response.items) shows that response.items is unchanged.
Is there a (preferably non-hacky) way to persist all changes to the li elements to response.items?
I think the problem here is that you're using the filter method. Filter (and also map) don't modify the original array, they essentially make a copy of it. So if you would check the return value of this whole code block like this:
var processed = $(response.items).filter('li').each(function(i){
$('img', this).attr('src', 'images/Picture.jpg');
if (i==0){
console.log(this);
}
});
console.log(processed);
It should properly show the changed values. Depending on what you want to do you could also use a map method after the each.
I have list of input area in the form with id like "contact1_title", "contact2_title", "contact3_title" ....
And I also have a list of selection in this form with id like "contact1_name", "contact2_name", "contact2_name" ....
I want to write a loop to dynamic bind the onchange function for the selections.
Here is my code:
for(var j=1;j<6;j++){
$('#contact'+j+'_name').change(function() {
alert(j);
//json.engineer is a json object
$('#contact'+j+'_title').val( json.engineer[this.selectedIndex-1].title );
});
}
When I change the selection, it always alert 6.
and title input area cannot be changed by select.
Does it mean the variable in javascript always change?
How can I bind an action dynamically?
I can hack it by using "this.name.split("_")[0]" but the code seems ugly.
Thanks in advanced.
Wrap your change functionality by closure:
for(var j=1;j<6;j++){
(function(j){
$('#contact'+j+'_name').change(function() {
alert(j);
//json.engineer is a json object
$('#contact'+j+'_title').val( json.engineer[this.selectedIndex-1].title );
});
})(j);
}
The problem was, when you click, your loop is already ended, so j is equal to 6.
Another solution would be to pass the counter as event data:
for(var j=1;j<6;j++){
$('#contact'+j+'_name').change({index: j}, function(event) {
$('#contact' + event.data.index + '_title')
.val(json.engineer[this.selectedIndex-1].title );
});
}
Even better would be if you could avoid using a for loop, but that depends on your markup and whether you have control over the created elements since you probably have to adjust them to do so.
There is a closure already, use it efficiently.
for(var j=1;j<6;j++){
$('#contact'+j+'_name').change(function() {
var k=j;
alert(k);
//json.engineer is a json object
$('#contact'+k+'_title').val( json.engineer[this.selectedIndex-1].title );
});
}
I ran into a problem with an object which I'm trying to modify. The object has a certain amount of keys in the format key_yyyy-mm-dd. When certain inputfields lose focus, I trigger a function to modify the object. This function is as follows:
function updateHotelBooking()
{
$(".no_hotel").each(function(i) {
var day = $(this).attr('name').match(/\[(.*?)\]/)[1];
hotelBooking["key_" + day] = parseInt($(this).val());
});
}
.no_hotel are the textboxes that trigger the function, and they also provide a value which I want to put in my object.
Now, say I put 3 in my first text box, a console.log will return the following object:
Object
key_2011-08-21: 3
key_2011-08-22: 0
key_2011-08-23: 0
key_2011-08-24: 0
key_2011-08-25: 0
However, the next time I put something in the textbox (or another textbox that should trigger the function), it DOES trigger, however the object returned remains the same. So instead of changing the first number to, say, 5, it will just return 3 again.
I have no idea why. My code seems pretty straightforward, and a console.log of day and $(this).val() returns the right values. It's just my object that doesnt get updated.
Does anyone have any idea? Thanks a lot!
EDIT:
hotelBooking is initialized right after $(document).ready():
var hotelBooking = {};
The method that calls updateHotelBooking is the following:
$(".roomrequest").blur(function()
{
updateHotelBooking();
});
EDIT2: JSFiddle: http://jsfiddle.net/pBYeD/2/
it has to do with something with the console rather than your code, if you change the logging code to this, you will see that you have the correct values:
function updateHotelBooking()
{
$(".no_hotel").each(function(i) {
var day = $(this).attr('name').match(/\[(.*?)\]/)[1];
hotelBooking["key_" + day] = parseInt($(this).val());
**logObject(hotelBooking);**
});
}
function logObject(hotelBooking){
for(var i in hotelBooking){
console.log(i+": "+hotelBooking[i]);
}
console.log("------");
}
Are you sure the problem does not come from the debugger output?
As far as i can see in my chrome output, if i let the fiddle as is, the object doesn't appear to change in the console (just the number on the left takes a +3). However if I add something like console.log(hotelBooking["key_" + day]); just before or after, it's shown as changing.