Wrong increment and decrement in javascript - javascript

As it's understandable from the code, I'm trying to create a simple img gallery.
I'm currently facing a calculation problem; if you run the snippet performing these actions you'll see what's wrong in the console log:
clicking on an img you'll get the id of the current clicked id
if you click next the first number it prints out is the same of the clicked id
but if you click now prev you'll see that actually the value was correct 'cause it prints the incremented number and you need to clicks to decrement
if you click now on another img you'll get the id of the new clicked div
but if you click now prev or next it performs the increment or decrement two times and it seems as the previous variable $ph_id is not overwritten by the new id
Can someone please explain me where the problem comes from? 'Cause I thought the code was written right but apparently I'm missing something.
[EDIT] I put the $('#next').click(function () and the $('#prev').click(function () outside of the $('.venus-div').click(function () and the problem at points 4. and 5. are now solved
$(document).ready(function () {
$('.venus-div').click(function () {
$this = $(this);
$ph_id = $this.attr('id');
console.log('Current id: ' + $ph_id);
});
$('#next').click(function () {
$next_id = $ph_id++;
console.log('Next id: ' + $next_id);
});
$('#prev').click(function () {
$prev_id = $ph_id--;
console.log('Prev id: ' + $prev_id);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="venus-div" id="1" data-image="../img/bv.jpg">
<img src="../img/thumb/bv_thumb.jpg" class="venus-thumb">
</div>
<div class="venus-div" id="2" data-image="../img/islamuj.jpg">
<img src="../img/thumb/islamuj_thumb.jpg" class="venus-thumb">
</div>
<div class="venus-div" id="3" data-image="../img/vertical.jpg">
<img src="../img/thumb/vertical_thumb.jpg" class="venus-thumb">
</div>
<div class="venus-div" id="4" data-image="../img/pano.jpg">
<img src="../img/thumb/pano_thumb.jpg" class="venus-thumb">
</div>
<p id="prev">BACK</p>
<p id="next">NEXT</p>

$next_id = $ph_id++; sets $next_id to the current value of $ph_id and then increments $ph_id by one. If you want the increment to happen first, you can place the ++ before the variable like so:
$next_id = ++$ph_id;
With this, $next_id will be equal to the incremented $ph_id.
The same applies to --:
$prev_id = --$ph_id;

I think its because you are creating and binding every click a new click event in next and prev, and its triggering multiple times due to this multiple binding. You can either off these events or bind them outside the venus-div click function (making ph_id, next_id and prev_id global vars inside document ready.
I cant write coding from mobile, if you need i'll update it later :)

Related

Link or button sets a variable, then calls the script

I have a script that plays a video in a Modal when a thumbnail gets clicked. This only works with the first video mentioned in the html, so I'm trying to use js to grab the particular video whos thumbnail is clicked on.
I have set up a variable in the js called vidcode, and gave it a value of the first video's address (rLdpnu2dDUY) or whatever it's called. I then set up a value 'start' for the link part before, and 'end' for the link part after. Now I have "showVideo = start + vidcode + end" and then innerHTML = showVideo, which works no problems.
So far the injection part works. My problem now is passing the address of the clicked thumbnail into the vidcode variable to play the corresponding video. I have looked on SO, w3, and Google. I have 6 different tries and none work fully.
I can create a link which
- Sets the variable, but then does not call the script.
- Calls the script but does not pass on the variable.
- Click one thumb to set the variable then another thumb to call the script. That one will then work but it's an extra step. At least with this one I know that the variable is being set..
<!--== Standard button but requires var vidcode to be preset in the Modal script ==-->
<img src="https://img.youtube.com/vi/rLdpnu2dDUY/hqdefault.jpg">
<!--== Add onClick to trigger a mini-script which sets the var vidcode early ==-->
<script>function hDSansxhArU(){var vidcode = 'hDSansxhArU';}</script>
<!--== Adding the javascript directly to the link code, yet it does not trigger the Modal script ===-->
<!--== Adding the javascript directly to the link code, to trigger a mini-script, to then call the modal ===-->
<script>function buttt(){var vidcode = 'duBjWlIzpzQ'; modalviewer();}</script>
<!--== Use the video's code as an id, then calling that id immediately and setting it to var vidcode ==-->
<script>
document.getElementById('hDSansxhArU').onclick = function() {
var vidcode = 'hDSansxhArU';
modalviewer()
};
</script>
Spots are commented out when trying something else
function modalviewer(){ //This function usually isn't here
var start = '<iframe width="840" height="472" src="https://www.youtube.com/embed/';
var end = '" frameborder="0" encrypted-media></iframe>';
//var showVideo = start + vidcode + end;
// This part works fine when vidcode gets a value
document.getElementById("button").addEventListener("click", function() {
document.querySelector(".theVideo").innerHTML = showVideo;
document.querySelector(".bg-modal").style.display = "flex";
});
document.querySelector(".bg-modal").addEventListener("click", function() { //.bg-modal to make the surrounding clickable
document.querySelector(".bg-modal").style.display = "none";
document.querySelector(".theVideo").innerHTML = "";
});
};
Expected results:
Click a link and have either
- set that address to variable 'vidcode', or
- set the address gobbledegook to 'vidcode' from here
and either have the modal script in a separate js file or at the bottom of the page.
As a code-newbie, I'm proud to have figured it out so far (with previous help from SO), it just frustrates me that I can only get half of this to work at a time :/.
#CTOverton provided what was needed, although everyone else and in Stop/Pause video when Modal is closed (not using $ sign) contributed with everything that they got me to look up as well. #Phoenix1355 actually started me on the right path despite me not posting any code at all, in turn leading me to learn so much in very little about Javascript and HTML.
This has been plaguing me for at least a week (I've lost track of time making this website), researching, getting other setups, trying overly-complicated setups, being told it can only be done by paying for a hosting plan or having to use Wordpress.. And this Console.log output, sooo helpful omg. Thank you everyone who contributed!
Here is the finished code:
<html>
<head>
<link href="http://www.jolanxbl.ca/snips/modal.css" rel="stylesheet" />
</head>
<body>
<center>
<br><br><br><br><br>
<!--List of videos-->
<img data-vidcode="rLdpnu2dDUY" src="https://img.youtube.com/vi/rLdpnu2dDUY/hqdefault.jpg" width="200px">
<img data-vidcode="hDSansxhArU" src="https://img.youtube.com/vi/hDSansxhArU/hqdefault.jpg" width="200px">
<img data-vidcode="duBjWlIzpzQ" src="https://img.youtube.com/vi/duBjWlIzpzQ/hqdefault.jpg" width="200px">
</center>
<!-- Modal Section 1 -->
<div class="bg-modal">
<div class="modal-content">
<div class="close">+</div>
<div class="theVideo">
<iframe width="840" height="472" src="https://www.youtube.com/embed/rLdpnu2dDUY" frameborder="0" encrypted-media; picture-in-picture allowfullscreen></iframe>
</div>
</div>
</div>
<script>
let vidcode = 'rLdpnu2dDUY';
// Get all elements with classname 'thumbnail'
let thumbnails = document.getElementsByClassName('thumbnail');
// Loop for every element with class
Array.from(thumbnails).forEach(function(element) {
element.addEventListener('click', thumbnailClicked);
});
function thumbnailClicked(event) {
// Event is mouse click event
// target is the img (as that is what you click on)
// dataset is the data attributes of img
vidcode = event.target.dataset.vidcode;
console.log('vidcode: ', vidcode)
//document.querySelector(".gridContainer").addEventListener("click", function() {
document.querySelector(".theVideo").innerHTML = '<iframe width="840" height="472" src="https://www.youtube.com/embed/' + vidcode + '" frameborder="0" encrypted-media></iframe>';
document.querySelector(".bg-modal").style.display = "flex";
}
document.querySelector(".bg-modal").addEventListener("click", function() { //.bg-modal to make the surrounding clickable
document.querySelector(".bg-modal").style.display = "none";
document.querySelector(".theVideo").innerHTML = "";
});
</script>
</body>
</html>
Based on your description I think you are looking for something along the lines of the "data attribute". Data attributes are custom attributes you can assign to any DOM element that contain essentially whatever you want.
In you case if you have a page with lots of thumbnails and you want a specific action to happen when you click on a specific thumbnail, your best bet is if you store that unique identifier (the video id, or are you put it vidcode) on the element you are clicking on.
This can be done like this:
<body>
<!--List of videos-->
<img data-vidcode="rLdpnu2dDUY" src="https://img.youtube.com/vi/rLdpnu2dDUY/hqdefault.jpg">
<img data-vidcode="example2" src="img2.jpg">
<img data-vidcode="example3" src="img3.jpg">
<script>
let vidcode = 'rLdpnu2dDUY';
// Get all elements with classname 'thumbnail'
let thumbnails = document.getElementsByClassName('thumbnail');
// Loop for every element with class
Array.from(thumbnails).forEach(function(element) {
element.addEventListener('click', thumbnailClicked);
});
function thumbnailClicked(event) {
// Event is mouse click event
// target is the img (as that is what you click on)
// dataset is the data attributes of img
vidcode = event.target.dataset.vidcode;
console.log('vidcode: ', vidcode)
}
</script>
</body>
Try passing the vidcode as an parameter for modalviewer function and then use the value.
function modalviewer(vidcode){
var start = '<iframe width="840" height="472" src="https://www.youtube.com/embed/';
var end = '" frameborder="0" encrypted-media></iframe>';
var showVideo = start + vidcode + end;
document.querySelector(".theVideo").innerHTML = showVideo;
};
<div class="theVideo"></div>
Click
<script>
document.getElementById('hDSansxhArU').onclick = function() {
var vidcode = 'hDSansxhArU';
modalviewer(vidcode)
};
</script>

Creating a javascript variable that adds 1 when an event happens

Context: I'm helping my friend create a political joke sort of website.
I need it to add 1 to a variable every time the onmouseover event is triggered.
<img src="tm.png" onmouseover='this.src="jc.png"'>
I have this so far but I need to find a way to link it with a function that will add 1 to itself when that event happens. I have multiple onmouseover events around the page so I need it to work for them all. I know how to make the variable but I am unsure on how to add 1 each time the onmouseover event happens, I am also unsure on how to add the function to the onmouseover event. Thanks
hoverCounter = 0;
<img src="http://www.darbsterkitty.com/uploads/5/5/5/6/55568079/b8sk1f_orig.jpg" height="200px" onmouseover="hoverCounter++; console.log('hoverCounter: ' + hoverCounter)"></img>
Use event delegation and check whether the hovered element is an image.
var count = 0;
addEventListener("mouseover", function(e){
if(e.target.tagName == "IMG"){
count++;
}
console.log(count);
})
<img src="http://lorempixel.com/50/50?0"/>
<img src="http://lorempixel.com/50/50?1"/>
<img id="someImage1" src="http://via.placeholder.com/350x150" >
<img id="someImage2" src="http://via.placeholder.com/350x150" >
<br/>
Hover Count:
<input id="countDisplay" type="text"/>
JS:
// Initial count
var hoverCount = 0;
// Function to increment
function onHovered(event){
hoverCount++;
document.getElementById('countDisplay').value = hoverCount;
}
// Bind events
document.getElementById('someImage1').onmouseover = onHovered;
document.getElementById('someImage2').onmouseover = onHovered;

Append a div outside of the input parent

Im fairly new to javascript and I just can't figure this out despite my attempt in researching. How do I track the change of a input within a div and trigger an append to an outside div? My code goes as follow:
Append h3 with "Pending" once ".image-value" input has a change in value
<!-- APPEND <h3> -->
<h3>Best Overall Costume<div class="pending">Pending</div></h3>
<div>
<div class="select-form">
<img src="images/vote.jpg" data-value="image_value">
<img src="images/vote.jpg" data-value="image_value2">
<img src="images/vote.jpg" data-value="image_value3">
<img src="images/vote.jpg" data-value="image_value4">
<img src="images/vote.jpg" data-value="image_value5">
<!-- Track the change of this input -->
<input type="hidden" class="image-value" name="selected_image" value="">
</div>
</div>
I tried this:
function changeStatus(statusValue) {
$("input",".select-form").val(statusValue).trigger("change");
}
$("input",".select-form").change(function(){
if (!$(this).val()){
$("<div class='pending'>Pending</div>").appendTo($("h3").prev($(this)));
}
});
But that didn't seem to work. Any ideas?
place an empty div where you want your new div and give it an id i.e(<div id='myDiv'><div>) and then append what you want like this.
$( "#myDiv" ).append( "<div class='pending'>Pending</div>" );
You can also check Append Explained
for more explanations.
Thanks.
I've done a couple things here... First, I'm not sure why you had it all in a named function. When you're using event listeners that often isn't necessary.
Then, I don't know what the val check was for, so I reversed it.
Finally, I'm using one(), which only runs once. This case seemed to call for that.
$('.select-form').one('change', 'input', function () {
if ( $(this).val() ) { alert('asdgf');
$("<div class='pending'>Pending</div>")
.appendTo($(this).parent().prev('h3'));
}
});
Fiddle
try this:
$("input",".select-form").on("change", function(){
var $this = $(this);
if (!$this.val()){
var elem = $('<h3>Best Overall Costume<div class="pending">Pending</div></h3>');
$this.parent().parent().before(elem);
}
});
you can also place a check, that if the pending div is already added, not to add it again.
Of course this solution assumes that there are no other nested divs between the target div(before which you want to append) and the input control

deactivate ONE button/thumb of a list

I have a video array, and then a list of thumbs that correspond to the array. When you click on one of the buttons, it needs to be deactivated for the duration of the video. I have it so that after the first click, it deactivates the whole list
$('li', '.thumbs').on('touchend click', function() {
$("#myVid").on("loadeddata", function() {
$("#bigPic").addClass("move");
$("#MyT").fadeOut(750);
});
playVideo2( $(this).index() );
$('li', '.thumbs').unbind();
});
if each item in the list is set up like this:
<li rel='1' id="first">
<div style="top:0px;">
<img src="graphics/filler.png" alt="" width="280" height="128" />
</div>
</li>
with the id being different for each, can I just put the id instead of the .thumbs, and just have it unbind or turn off itself? I know this must be inefficient, but I'm not sure how else to do it. Do I use this() somehow? If so, how?
You could make use of a global variable to check which video is playing.
//init
var currentlyPlaying = undefined;
Within your event handling part you set this variable to the ID of the clicked button.
currentlyPlaying = $(this).attr('id');
With that setup you can check the variable before doing anything in your script.
if ( !(currentlyPlaying == $(this).attr('id')) ) {
// your script
}
Alternatively, you can use the ID to unbind as you suggested, of course.
$('li', '.thumbs #' + $(this).attr('id')).unbind();

jQuery: How to assign the right ID to a button dynamically

I have a JS/jQuery script that adds our leads (web contacts) to the DOM in a for loop. Everything works fine except for one thing. I want the body of the lead to be hidden upon the initial display, and then have a slideToggle button to display or hide the details That means dynamically adding click events to each button as it is created. The entire HTML (HTML and a JSON object mixed into the HTML) of the lead and the slideToggle button are all appended to a node in the DOM in the for loop. Here is the pertinent part of the for loop:
// Hide the body of the lead; just show the title bar and the first line
var dataID = data[i].id
var div = $('#row' + dataID);
var more = $('#more' + dataID);
div.hide();
// Create click event for each "+" button
more.click(function() {
div.slideToggle();
});
But when I click on the "+" button to reveal the details, it opens the last div, not the div I am trying to open. This is true no matter how many leads I have on the page. How do I get the click event to open the right div. If I console.log "div" in the click event, it gives me the ID of the last div, not the one I am clicking on. But if I console.log(div) outside the click event, it has the right ID.
Also, I was unsure whether I needed the "vars" in the loop or if I should declare them outside the loop.
Here is the HTML. It's one lead plus the beginning of the next lead, which I left closed in Firebug
<div id="lead1115">
<div id="learnmore">
<a id="more1115" class="more" href="#">+</a>
</div>
<div id="lead-info">
<div id="leadID">Lead ID# Date: March 27, 2012 11:26 AM (Arizona time)</div>
<div id="company">No company given</div>
<div id="name">Meaghan Dee</div>
<div id="email">
meaghan.dee#gmail.com
</div>
<br class="clearall">
<div>
<div id="row1115" style="display: none;">
<div id="phone">No phone given</div>
<div id="source">www.ulsinc.com/misc/expert-contact/</div>
<div id="cp-name">No channel partner chosen</div>
<br class="clearall">
<div id="location">
No location given
<br>
<strong>IP Address:</strong>
198.82.10.87
<br>
<span>Approximate Location: Blacksburg, Virginia, United States</span>
<br>
</div>
<div id="details">
<strong>Questions/Comments</strong>
<br>
We have the Professional Series Universal Laser Systems (laser cutter), and I wondered how I would order a high power density 2.0 replacement lens.nnThank you
</div>
</div>
</div>
</div>
<div id="learnmore">
<a id="1115|send_message" class="verify" href="#">Verify</a>
<a id="1115|send_message" class="markAsSpam" href="#">Spam</a>
<a id="1115|send_message" class="markAsDuplicate" href="#">Duplicate</a>
</div>
</div>
<br class="clearall">
<div id="lead1116">
<br class="clearall">
Try using .bind (or .on for 1.7+) and the data parameter.
more.bind("click",{target:div},function(e){
e.data.target.show();
}
or
more.on("click",{target:div},function(e){
e.data.target.show();
}
I think your basic problem is that div is common as a variable to all items. You have to separate the div's from each other by, for example, creating a local function and call it for each item. Something like:
function buildMore(div) {
more.click(function() {
div.slideToggle();
});
}
and in the loop call:
addMore(div);
p.s.
Whether you declare your variables inside or outside the loop doesn't matter: you still get the same variables.
This is because div variable gets changed and settles with the last value set in the loop.
Try this:
...
funciton createClick(div) {
return function() { div.slidToggle();
}
more.click( createClick(div) );
...
The variable div doesn't stay frozen with your click handler so it's value will be what it was at the end of the for loop and all click handlers will use the same value (which is what you're seeing).
There are a number of different ways to approach this and I thought all would be educational. Any one of them should work.
Idea #1 - Manufacture the row id from the clicked on more id
Use the id value on the clicked on link to manufacture the matching row ID. Since you create them in pairs, this can be done programmatically like this:
// Hide the body of the lead; just show the title bar and the first line
var dataID = data[i].id
$('#row' + dataID).hide();
$('#more' + dataID).click(function() {
// manufacture the row ID value from the clicked on id
var id = this.id.replace("more", "#row");
$(id).slideToggle();
});
Idea #2 - Use a function closure to "freeze" the values you want
Another way to do that is to create a function and closure that will capture the current value of div:
// Hide the body of the lead; just show the title bar and the first line
var dataID = data[i].id
var div = $('#row' + dataID).hide();
var more = $('#more' + dataID);
function addClick(moreItem, divItem) {
// Create click event for each "+" button
moreItem.click(function() {
divItem.slideToggle();
});
}
addClick(more, div);
Idea #3 - Use the HTML spatial relationship to find the row associated with a more
To make this work, you need to put a common class=lead on the top level lead div like this:
<div id="lead1115" class="lead">
And, a common class on each row:
<div id="row1115" class="row" style="display: none;">
Then, you can use the position relationships to find the row object that is in the same parent lead object as the clicked on more link like this:
// Hide the body of the lead; just show the title bar and the first line
var dataID = data[i].id
$('#row' + dataID).hide();
$('#more' + dataID).click(function() {
// find out common parent, then find the row in that common parent
$(this).closest(".lead").find(".row").slideToggle();
});
Idea #4 - Put the row ID as data on the more link
// Hide the body of the lead; just show the title bar and the first line
var dataID = data[i].id
$('#row' + dataID).hide();
$('#more' + dataID).data("row", "#row" + dataID).click(function() {
// get the corresponding row from the data on the clicked link
var rowID = $(this).data("row");
$(rowID).slideToggle();
});

Categories

Resources