I am very new to javascript and I hope to get some help simplifying the code.
I have two div box that contains 3 images each. Each div box displays an image by default (no. 1 and 4) and the mouse hover toggle a change in image (independently). See http://jsfiddle.net/hdaq9se5/6/.
The following code works just right but I am hoping to get some help simplifying the code, e.g. modify the animation function such that it takes the class of the div box as input.
$(document).ready(function () {
$("#image_two, #image_three, #image_five, #image_six").hide();
$(".image_rollover").hover(function () {
animation()
});
$(".image_rollover2").hover(function () {
animation2()
});
});
function animation() {
var $curr=$(".image_rollover img:visible");
var $next=$curr.next();
if($next.size()==0) $next=$(".image_rollover img:first");
$next.show();
$curr.hide();
}
function animation2() {
var $curr=$(".image_rollover2 img:visible");
var $next=$curr.next();
if($next.size()==0) $next=$(".image_rollover2 img:first");
$next.show();
$curr.hide();
}
Like this?
Using jquery, this is in most places (almost everywhere) the current Element. Like the Element that dispatched an event, ...
knowing this you don't need to pass any classes into animation, jquery already provides you with all you need.
$(document).ready(function() {
$(".image_box img").not(":first-child").hide();
$(".image_box").hover(animation);
});
function animation() {
var $curr = $("img:visible", this);
var $next = $curr.next();
if ($next.length === 0) {
$next = $("img:first", this);
}
$next.show();
$curr.hide();
}
.image_box {
border: 1px solid #000000;
width: 130px;
height: 80px;
overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="image_rollover image_box">
<img id="image_one" src="http://placehold.it/130x80&text=1">
<img id="image_two" src="http://placehold.it/130x80&text=2">
<img id="image_three" src="http://placehold.it/130x80&text=3">
</div>
<div class="image_rollover2 image_box">
<img id="image_four" src="http://placehold.it/130x80&text=4">
<img id="image_five" src="http://placehold.it/130x80&text=5">
<img id="image_six" src="http://placehold.it/130x80&text=6">
</div>
Related
If I've got multiple items that I want to change from a display of 'none', to a display of 'block', what's the most efficient way of doing it?
The JS I would use for a single item is below, but I imagine there are several on a page or site. Should I make use of function constructors somehow?
var sideNav = document.getElementById('sideNav');
var menuButton = document.getElementById('menuButton');
function toggle() {
if(sideNav.style.display) {
sideNav.style.display = '';
} else {
sideNav.style.display = 'block';
}
}
menuButton.addEventListener('click', toggle);
Take a look, see if this helps you.
I did it with vanilla JS, I don't know if you are currently using jQuery (would be easier if yes)
What I did:
Every button have it's own id that is used to "connect" to the elements that it should toggle.
First I add the listener to all buttons, passing it's id when the function is called.
Then in the function, I used document.querySelectorAll to get all elements with the class that should be hidden/show.
Then finally I run a loop in those elements, showing or not showing, depending on it's current 'display'.
var menuButtons = document.querySelectorAll('.menuButton');
menuButtons.forEach(function(btn){
btn.addEventListener("click", toggle.bind(this, btn.id));
})
function toggle(id) {
var sideNav = document.querySelectorAll('.nav_' + id);
sideNav.forEach(function(el){
if (el.style.display == 'none'){
el.style.display = "block";
} else {
el.style.display = "none"
}
})
}
div{
height: 30px;
width: 50px;
margin: 2px 0;
background: #999;
text-align: center
}
<button id="menuButton1" class="menuButton">Toggle 1</button>
<button id="menuButton2" class="menuButton">Toggle 2</button>
<button id="menuButton3" class="menuButton">Toggle 3</button>
<div class="nav_menuButton1">1</div>
<div class="nav_menuButton1">1</div>
<div class="nav_menuButton2">2</div>
<div class="nav_menuButton3">3</div>
<div class="nav_menuButton3">3</div>
<div class="nav_menuButton3">3</div>
Probably there are better approaches, but I'm now in a hurry and this is the best I could think in that moment
Use JQuery to obtain it:
$(document).ready(function(){
$('#menuButton').click(toggle);
});
function toggle(){
$('.toggle-item').each(function(){
$(this).show();
})
}
and for all you items, add the toggle-item class with this css:
.toggle-item{
display: none;
}
If for every button there is an item to show, this is the way:
$(document).ready(function(){
$('.menuButton').each(function(){
var button = $(this);
button.click(function(){
toggle(button.attr('data-target')));
});
});
});
function toggle(itemId){
$(itemId).show();
}
Adding this attribute to button:
<button class="menuButton" data-target="#toggle-item-1"></button>
I am not quite sure if that's the correct way to phrase it, but here is my problem
As you can see, pretty simple code:
<div class="first"></div>
<div></div>
What I want to achieve is:
You click on the div with the first class, it will swap that class with the sibling element
You click the sibling element, and it swaps it back, so you just swap classes around 2 elements
The problem here is it works correctly only the first time, and the second time when the new element receives the class via addClass, jQuery doesn't recognize that it contains the class by the first page load? How can I resolve this?
P.S: I made a console.log(111); just to make sure, and sure enough it triggers ONLY when I click on the black div after the first swap (the one that SHOULD NOT have the first class anymore)
To achieve this behavior, you can use delegated events http://api.jquery.com/delegate/ on elements wrapper;
$(document).delegate('.first', 'click', function(e){
e.preventDefault();
console.log(123);
$(this).removeClass('first');
$(this).siblings().addClass('first');
})
A quick and simple way to do it is this:
$(document).ready(function() {
var first = $('.first');
var second = first.next();
first.click(function(e) {
e.preventDefault();
first.removeClass('first');
second.addClass('first');
});
second.click(function(e) {
e.preventDefault();
second.removeClass('first');
first.addClass('first');
});
});
div {
background-color: black;
height: 100px;
width: 100px;
margin-bottom: 10px;
}
.first {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="first"></div>
<div></div>
This way does not scale well.
Your problem was you only change when you click the $(first) which does not change when clicked it's still point to the first div.
A better way with vanilla javascript:
document.addEventListener('click', function(e) {
if (e.target.classList.contains('first')) {
e.target.classList.remove('first')
var sibling = getNextSibling(e.target) || getPreviousSibling(e.target)
if (sibling) {
sibling.classList.add('first')
}
}
})
function getNextSibling(elem) {
var sibling = elem.nextSibling
while(sibling && sibling.nodeType != 1) {
sibling = sibling.nextSibling
}
return sibling
}
function getPreviousSibling(elem) {
var sibling = elem.previousSibling
while(sibling && sibling.nodeType != 1) {
sibling = sibling.previousSibling
}
return sibling
}
All you need to do is push both items into an array, then flip between indexes on click.
var elems = [];
$(document).on("click", ".first", function(event) {
elems = elems.length == 0 ? [event.originalEvent.target, $(event.originalEvent.target).next()] : elems;
$(elems[event.originalEvent.target === elems[0] ? 1 : 0]).addClass("first");
$(elems[event.originalEvent.target === elems[0] ? 0 : 1]).removeClass("first");
});
.first {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="first">x</div>
<div>y</div>
So I am trying to change the background color of a div after the page loads.
The div with the background and the img are inside an li.
When the mouse enters the .dlmain div I check the img src and give the div .darkbg a background depending on the img src
THE ISSUE: It shows me the correct img src the first time and second time but then on the next div I enter it shows the previous divs img src. I have about 100 divs that the mouse enters and background color should be changed
Am I supposed to have a .each function here? I tried this with no luck
$(document).ready(function () {
$(document).on("mouseenter", ".dlmain", function () {
if ($('.carimg').attr('src') == '/css/1359532013.jpg') {
$(".darkbg").css({
"backgroundColor": "#EE1C25"
});
alert($('.carimg').attr('src'));
} else if ($('.carimg').attr('src') == '/css/1359532047.jpg') {
$(".darkbg").css({
"backgroundColor": "blue"
});
alert($('.carimg').attr('src'));
} else {
alert($('.carimg').attr('src'));
}
});
});
Here is the HTML:
<li id="13592635281366253285" class="myli" style="width:170px;height:170px;">
<div class="favs"></div>
<div class="mylimg" style="background:url(/images/th135926352813662532851.jpg) 50% 50% no- repeat;"></div>
<div class="darkbg" style="background-color: rgb(238, 28, 37); opacity: 0;"></div>
<div class="dlprice">$69.99</div>
<div class="dlmain" style="top: 153px;">
<img class="carimg" src="/css/1359532047.jpg">
</li>
<li id="13592635281366253092" class="myli" style="width:170px;height:170px;">
<div class="favs"></div>
<div class="mylimg" style="background:url(/images/th135926352813662530921.jpg) 50% 50% no-repeat;"></div>
<div class="darkbg" style="background-color: rgb(238, 28, 37); opacity: 0;"></div>
<div class="dlprice">$59.99</div>
<div class="dlmain" style="top: 153px;">
<img class="carimg" src="/css/1359532013.jpg">
</li>
Thank you in advanced for any help
You need to find the element relative to the current hovered element. you need to target the carimg and darkbg elements with the same li as the entered dlmain element. So use .closest() to find the li element and then use .find() in the li element to find the other 2 elements
Try
$(document).ready(function () {
$(document).on("mouseenter", ".dlmain", function () {
var $li = $(this).closest('li'),
src = $li.find('.carimg').attr('src'),
$darkbg = $li.find('.darkbg')
if (src == '/css/1359532013.jpg') {
$darkbg.css({
"backgroundColor": "#EE1C25"
});
} else if (src == '/css/1359532047.jpg') {
$darkbg.css({
"backgroundColor": "blue"
});
} else {}
alert(src);
});
});
Another tweak that can be applied is
$(document).ready(function () {
var backgrounds = {
'/css/1359532013.jpg': '#EE1C25',
'/css/1359532047.jpg': 'blue'
};
$(document).on("mouseenter", ".dlmain", function () {
var $li = $(this).closest('li'),
src = $li.find('.carimg').attr('src'),
$darkbg = $li.find('.darkbg');
$darkbg.css({
"backgroundColor": backgrounds[src]
});
alert(src);
});
});
if you have different '.carimg' for each divs, you should pick the specific one.
$('.carimg').attr('src') is giving you the same value for all the divs.
If the img '.carimg' and div '.darkbg' are in the current div '.dlmain', please try this:
$(document).ready(function () {
$(document).on("mouseenter", ".dlmain", function () {
var $this=$(this);
if ($this.find(‘.carimg').attr('src') == '/css/1359532013.jpg') {
$this.find(“.darkbg").css({
"backgroundColor": "#EE1C25"
});
alert($this.find('.carimg').attr('src'));
} else if ($this.find('.carimg').attr('src') == '/css/1359532047.jpg') {
$this.find(".darkbg").css({
"backgroundColor": "blue"
});
alert($this.find('.carimg').attr('src'));
} else {
alert($this.find('.carimg').attr('src'));
}
});
});
I'm trying to build an image cropper similar to Twitters - http://jsfiddle.net/yarKr/1/. What I'm stuck on is the ability to drag the image. What is the best way to do this without resorting to jquery ui?
<div class="canvas">
<span class="window"></span>
<img src="http://www.dailystab.com/blog/wp-content/uploads/2009/03/katy-perry-esquire-4.jpg" class="draggable" />
</div>
I want to be able to move drag the image around inside the .canvas div.
Something like this will work: jsFiddle
var TheDraggable = null;
$(document).ready(function () {
$('.draggable').on({
mousedown: function () { TheDraggable = $(this); },
mouseup: function () { TheDraggable = null; }
});
$(document).mousemove(function (e) {
if (TheDraggable) {
TheDraggable.css({'top': e.pageY, 'left': e.pageX});
}
});
});
And then for the CSS you add this: .draggable { position:absolute; }
You could rewrite this and add some form of easing on the repositioning, change the cursor or add a more precise starting point based on where the initial click happened on the picture but overall, that should get you started.
How about, while dragging, making the position absolute and setting it to or near the position of the mouse?
This is mine.
http://jsfiddle.net/pd1vojsL/
3 draggable buttons in a div, dragging constrained by div.
<div id="parent" class="parent">
<button id="button1" class="button">Drag me</button>
<button id="button2" class="button">Drag me</button>
<button id="button3" class="button">Drag me</button>
</div>
<div id="log1"></div>
<div id="log2"></div>
Requires JQuery (only):
$(function() {
$('.button').mousedown(function(e) {
if(e.which===1) {
var button = $(this);
var parent_height = button.parent().innerHeight();
var top = parseInt(button.css('top')); //current top position
var original_ypos = button.css('top','').position().top; //original ypos (without top)
button.css({top:top+'px'}); //restore top pos
var drag_min_ypos = 0-original_ypos;
var drag_max_ypos = parent_height-original_ypos-button.outerHeight();
var drag_start_ypos = e.clientY;
$('#log1').text('mousedown top: '+top+', original_ypos: '+original_ypos);
$(window).on('mousemove',function(e) {
//Drag started
button.addClass('drag');
var new_top = top+(e.clientY-drag_start_ypos);
button.css({top:new_top+'px'});
if(new_top<drag_min_ypos) { button.css({top:drag_min_ypos+'px'}); }
if(new_top>drag_max_ypos) { button.css({top:drag_max_ypos+'px'}); }
$('#log2').text('mousemove min: '+drag_min_ypos+', max: '+drag_max_ypos+', new_top: '+new_top);
//Outdated code below (reason: drag contrains too early)
/*if(new_top>=drag_min_ypos&&new_top<=drag_max_ypos) {
button.css({top:new_top+'px'});
}*/
});
$(window).on('mouseup',function(e) {
if(e.which===1) {
//Drag finished
$('.button').removeClass('drag');
$(window).off('mouseup mousemove');
$('#log1').text('mouseup');
$('#log2').text('');
}
});
}
});
});
Drag icon - less jumping
Borrowing from frenchie's answer I have to create a movable popup on the fly. Have to add dragability to the object after it's created. This not flawless - any faster than a slow drag and the cursor leaves the behind until you let go, at which point the <div> then snaps and sticks to the cursor movements until you click again.
<!-- language: lang-html -->
<input type="button" value="pop" onclick="pop('NN')" id="btnNN"><!-- NN is the query rownumber -->
<b style="display:none;" id="protoContent">
<div id="divdrag~">
<img style="float:left;" id="drag~">
my form <input id="inp1_~">...
</div>
</b>
<!-- language: lang-js -->
var TheDraggable = null;
$(document).ready(function () {
$(document).mousemove(function (e) {
if (TheDraggable) {
TheDraggable.css({'top': e.pageY-15, 'left': e.pageX-15});
}//"-15" gets the cursor back on img inside the <div>
});
});
var gOpenPop="";
function pop(NN){
if(gOpenPop!=""){
document.getElementById("divdrag"+gOpenPop).style.display="none";//hide opened
if(gOpenPop==NN){
gOpenPop="";
return;
}
}
gOpenPop=NN;
//add div after the button
$("#btn"+NN).after(
//get div w/ form, replace of any "~"s with argument NN
$("#protoContent").html().replace(/~/g,NN)
);
//ojb created, now bind click for dragability to the img
$('#drag'+NN).on(
{mousedown: function () {TheDraggable = $("#divdrag"+NN); },//
mouseup: function () { TheDraggable = null; }
});
...
}
I made this script, which opens a div with the right class and close the others.
function showhide(id) {
if (document.getElementById) {
var divid = document.getElementById(id);
var divs = document.getElementsByClassName("hideable");
for (var i = 0; i < divs.length; i = i + 1) {
divs[i].style.display = "none";
}
divid.style.display = "block";
}
return false;
}
Is it possible to make some animation, like fadout, easeout instead of just showing it by display options?
You could try this
function showhide(id) {
if (document.getElementById) {
var divid = document.getElementById(id);
var divs = document.getElementsByClassName("hideable");
for (var i = 0; i < divs.length; i = i + 1) {
$(divs[i]).fadeOut("slow");
}
$(divid).fadeIn("slow");
}
return false;
}
Have a look at this fiddle "http://jsfiddle.net/9jtd3/"
There are many more techniques provided by Jquery library, You should have a look at that too.
You can use slideDown() and slidUp() of jQuery
$( document.body ).click(function () {
if ( $( "div:first" ).is( ":hidden" ) ) {
$( "div" ).slideDown( "slow" );
} else {
$( "div" ).slideUp("slow");
}
});
This example will toggle multiple elements with the same class name. This example does not need jquery.
HTML:
<button onclick="fadeInAndOut(this)" style="width:100%">Toggle 1</button>
<div class="accordianPanel acordianPanelHidden accordianPanelStyle">Panel 1</div>
<button onclick="fadeInAndOut(this)" style="width:100%">Toggle 2</button>
<div class="accordianPanel acordianPanelHidden accordianPanelStyle">Panel 2</div>
Javascript:
function fadeInAndOut(thz) {
var elmt = thz.nextElementSibling;//Get the element that is below the button that
//was just clicked
elmt.classList.toggle("acordianPanelHidden");//Toggle the class which changes
//attributes which triggers the `transition` CSS
}
CSS
.accordianPanel {
opacity: 1;
height:100%;
transition: all 1s;
}
.accordianPanel.acordianPanelHidden {
opacity: 0;
height: 0px;
visibility:hidden;/* This must be used or some strange things happen -
What happens is that even though the content of the panel is not shown
any buttons in the content can still be clicked -
So basically there are invisible buttons that can accidently get clicked -
if the visibility is not set to hidden - And the visibility doesn't need to be explicitly changed to visible
from hidden in order to show the content
because if visibility:hidden is not used then by default the content is
displayed -
*/
}
.acordianPanelShown {
height: 100%;
width: 100%;
opacity: 1;
}
.accordianPanelStyle {
background:red;
}
This will surely solve your problem.
You can use .fadeOut() directly if you have included jQuery library in your script.
This is way easier with only CSS.
You make a class
div {
display:block;
transition: all .2s ease-out;
}
.hidden {
display:none;
}
And with javascript, you apply or remove the class hidden when you want to. jQuery animation lib is wayyyy far from good to be used. It's clunky, and ressource eating for your user. CSS works with your GPU instead, allowing a more fluid animation.
If You are using Jquery then another way to do this is
function showhide(id) {
$(".hideable").fadeOut("slow");
$("#" + id).fadeIn("slow");
}
Assuming "hideable" as className in your group of divs
Good luck.
You can do that using a Library like jQuery or something.
You can sure make it using plain javascript, but there's no point doing that since jQuery is an amazing library.
See some examples of show and hide