I'm currently trying to make a hover effect (make a div fadein, and then out when not hovering) on my list of pictures that users has uploadet. Since i dont want all my pictures to hover when one of the pictures are selected, i have made PHP echo out a variable for the divs ids.
In my jQuery code below, i got a loop where i count from 1 to 16 (thats the number of pictures in my gallery) and the selector has the name of the divs.
PHP Part:
echo "<div class='cell1' id=sovs$sovs style='overflow: hidden; position: relative;'>
<a href=image.php?p=$presentnew->upload_id>
<img style='min-width: 177px; min-height: 177px;' src='content/$presentnew->user_name/thumbs/medium_$presentnew->file_name'>
<div class='celltext'>
<b style='color: white; line-height: 28px; margin-left: 5px; font-size: 10pt;'><a style='color: white;' href='profil.php?bruger=$presentnew->user_name'>$presentnew->user_name</a></b>
</div>
</a>
</div>";
$sovs++;
}
Javascript Part:
for (var h = 1; h <= 16; h++) {
$(function() {
$("#sovs" + h).hover(
function() {
alert("g");
});
});
}
The code above is just a test where i want my divs to respond to the function.
problem is that they dont do that. they will respond if i change the name of the selector to, for instance $('#sovs1').
Can anybody enlighten me on what I am doing wrong?
$(document).ready(function(){
for(var h=1; h<=16; h++){
$("#sovs"+h).mouseover(function(){
alert("G");
});
}
});
Works, but if i attach the fadeIn function to it, it doesn't
You will have to give a lot more info to get an answer, just one important thing:
for (var h = 1; h <= 16; h++) {
$(function() { // <======= This will create 16! dom ready event handlers
$("#sovs" + h).hover(
function() {
alert("g");
});
});
}
Move it to an outer scope (If needed at all..)
$(function() {
for (var h = 1; h <= 16; h++) {
$("#sovs" + h).hover(function() {
alert("g");
});
}
}
Try this code, to see if the problem is with delegate event VS direct event.
$(function() {
for (var h = 1; h <= 16; h++) {
$('body').on('mousemove', "#sovs" + h, function() {
alert('g');
});
}
}
$(document).ready(function() {
for(var h=1; h<=16; h++) {
$("#sovs"+h).live('hover', function() {
alert("g");
});
}
});
Related
Is it possible for li elements animation from here:
http://jsfiddle.net/8XM3q/light/
to animate when there is show/hide function used instead of remove?
When i have changed "remove" to "hide" elements didn't move: http://jsfiddle.net/8XM3q/90/
I wanted to use this function for my content filtering animations - thats why i have to replace "remove" to "hide/show".
I'm not good at JS but i think that it counts all elements, even when they are hidden:
function createListStyles(rulePattern, rows, cols) {
var rules = [], index = 0;
for (var rowIndex = 0; rowIndex < rows; rowIndex++) {
for (var colIndex = 0; colIndex < cols; colIndex++) {
var x = (colIndex * 100) + "%",
y = (rowIndex * 100) + "%",
transforms = "{ -webkit-transform: translate3d(" + x + ", " + y + ", 0); transform: translate3d(" + x + ", " + y + ", 0); }";
rules.push(rulePattern.replace("{0}", ++index) + transforms);
}
}
var headElem = document.getElementsByTagName("head")[0],
styleElem = $("<style>").attr("type", "text/css").appendTo(headElem)[0];
if (styleElem.styleSheet) {
styleElem.styleSheet.cssText = rules.join("\n");
} else {
styleElem.textContent = rules.join("\n");
}
So my question is how to adapt that part of code to count only "show" (displayed) elements?
If you want to have the animation and still have all of the data then use detach() function instead of remove: jQuery - detach
And to count or select elements try to do this using css's class attached to each element.
I edited your jsFiddle:
http://jsfiddle.net/8XM3q/101/
notice that I changed this line:EDIT: http://jsfiddle.net/8XM3q/101/
$(this).closest("li").remove();
to this:
$(this).closest("li").hide("slow",function(){$(this).detach()});
This means hide the item, speed = slow, when done hiding remove it.
Hope this is what you meant.
EDIT: Included detach.
As per your comment:
I wanted to use this function for my content filtering animations -
thats why i have to replace "remove" to "hide/show" I don't want to
remove elements at all. Im sorry if I mislead You with my question.
What you can do is to use a cache to store the list-items as they are hidden when you do the content filtering. Later when you need to reset the entire list, you can replenish the items from the cache.
Relevant code fragment...
HTML:
...
<button class="append">Add new item</button>
<button class="replenish">Replenish from cache</button>
<div id="cache"></div>
JS:
...
$(this).closest("li").hide(600, function() {
$(this).appendTo($('#cache'));
});
...
$(".replenish").click(function () {
$("#cache").children().eq(0).appendTo($(".items")).show();
});
Demo Fiddle: http://jsfiddle.net/abhitalks/8XM3q/102/
Snippet:
$(function() {
$(document.body).on("click", ".delete", function (evt) {
evt.preventDefault();
$(this).closest("li").hide(600, function() {
$(this).appendTo($('#cache'));
});
});
$(".append").click(function () {
$("<li>New item <a href='#' class='delete'>delete</a></li>").insertAfter($(".items").children()[2]);
});
$(".replenish").click(function () {
$("#cache").children().eq(0).appendTo($(".items")).show();
});
// Workaround for Webkit bug: force scroll height to be recomputed after the transition ends, not only when it starts
$(".items").on("webkitTransitionEnd", function () {
$(this).hide().offset();
$(this).show();
});
});
function createListStyles(rulePattern, rows, cols) {
var rules = [], index = 0;
for (var rowIndex = 0; rowIndex < rows; rowIndex++) {
for (var colIndex = 0; colIndex < cols; colIndex++) {
var x = (colIndex * 100) + "%",
y = (rowIndex * 100) + "%",
transforms = "{ -webkit-transform: translate3d(" + x + ", " + y + ", 0); transform: translate3d(" + x + ", " + y + ", 0); }";
rules.push(rulePattern.replace("{0}", ++index) + transforms);
}
}
var headElem = document.getElementsByTagName("head")[0],
styleElem = $("<style>").attr("type", "text/css").appendTo(headElem)[0];
if (styleElem.styleSheet) {
styleElem.styleSheet.cssText = rules.join("\n");
} else {
styleElem.textContent = rules.join("\n");
}
}
createListStyles(".items li:nth-child({0})", 50, 3);
body { font-family: Arial; }
.items {
list-style-type: none; padding: 0; position: relative;
border: 1px solid black; height: 220px; overflow-y: auto; overflow-x: hidden;
width: 600px;
}
.items li {
height: 50px; width: 200px; line-height: 50px; padding-left: 20px;
border: 1px solid silver; background: #eee; box-sizing: border-box; -moz-box-sizing: border-box;
position: absolute; top: 0; left: 0;
-webkit-transition: all 0.2s ease-out; transition: all 0.2s ease-out;
}
div.cache { display: none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="items">
<li>Monday delete
</li><li>Tuesday delete
</li><li>Wednesday delete
</li><li>Thursday delete
</li><li>Friday delete
</li><li>Saturday delete
</li><li>Sunday delete</li>
</ul>
<button class="append">Add new item</button>
<button class="replenish">Replenish from cache</button>
<div id="cache"></div>
EDIT: There is a simpler way without adding any classes, is to use the :visible selector
You need to understand a concept is Javascript, which is that functions are considered objects. You can pass a function to another function, or return a function from a function.
Let's check the documentation on jQuery for the hide function
.hide( duration [, easing ] [, complete ] )
It says that it accepts a function as an argument for complete, which is called when the hide animation is complete.
The function hide does not remove the element from the DOM but simply "hides" it as the name suggests. So what we want to do, is hide the element then when the animation of hiding is done, we add a class "removed" to the list element.
We will accomplish that by passing a function (complete argument) like so :
$(this).closest("li").hide(400, function() {
$(this).addClass('removed');
});
When you want to select the list elements that are not "removed", use this selector $('li:not(.removed)')
PURE JS ONLY PLEASE - NO JQUERY
I have a div with overflow scroll, the window (html/body) never overflows itself.
I have a list of anchor links and want to scroll to a position when they're clicked.
Basically just looking for anchor scrolling from within a div, not window.
window.scrollTo etc. don't work as the window never actually overflows.
Simple test case http://codepen.io/mildrenben/pen/RPyzqm
JADE
nav
a(data-goto="#1") 1
a(data-goto="#2") 2
a(data-goto="#3") 3
a(data-goto="#4") 4
a(data-goto="#5") 5
a(data-goto="#6") 6
main
p(data-id="1") 1
p(data-id="2") 2
p(data-id="3") 3
p(data-id="4") 4
p(data-id="5") 5
p(data-id="6") 6
SCSS
html, body {
width: 100%;
height: 100%;
max-height: 100%;
}
main {
height: 100%;
max-height: 100%;
overflow: scroll;
width: 500px;
}
nav {
background: red;
color: white;
position: fixed;
width: 50%;
left: 50%;
}
a {
color: white;
cursor: pointer;
display: block;
padding: 10px 20px;
&:hover {
background: lighten(red, 20%);
}
}
p {
width: 400px;
height: 400px;
border: solid 2px green;
padding: 30px;
}
JS
var links = document.querySelectorAll('a'),
paras = document.querySelectorAll('p'),
main = document.querySelector('main');
for (var i = 0; i < links.length; i++) {
links[i].addEventListener('click', function(){
var linkID = this.getAttribute('data-goto').slice(1);
for (var j = 0; j < links.length; j++) {
if(linkID === paras[j].getAttribute('data-id')) {
window.scrollTo(0, paras[j].offsetTop);
}
}
})
}
PURE JS ONLY PLEASE - NO JQUERY
What you want is to set the scrollTop property on the <main> element.
var nav = document.querySelector('nav'),
main = document.querySelector('main');
nav.addEventListener('click', function(event){
var linkID,
scrollTarget;
if (event.target.tagName.toUpperCase() === "A") {
linkID = event.target.dataset.goto.slice(1);
scrollTarget = main.querySelector('[data-id="' + linkID + '"]');
main.scrollTop = scrollTarget.offsetTop;
}
});
You'll notice a couple of other things I did different:
I used event delegation so I only had to attach one event to the nav element which will more efficiently handle clicks on any of the links.
Likewise, instead of looping through all the p elements, I selected the one I wanted using an attribute selector
This is not only more efficient and scalable, it also produces shorter, easier to maintain code.
This code will just jump to the element, for an animated scroll, you would need to write a function that incrementally updates scrollTop after small delays using setTimeout.
var nav = document.querySelector('nav'),
main = document.querySelector('main'),
scrollElementTo = (function () {
var timerId;
return function (scrollWithin, scrollTo, pixelsPerSecond) {
scrollWithin.scrollTop = scrollWithin.scrollTop || 0;
var pixelsPerTick = pixelsPerSecond / 100,
destY = scrollTo.offsetTop,
direction = scrollWithin.scrollTop < destY ? 1 : -1,
doTick = function () {
var distLeft = Math.abs(scrollWithin.scrollTop - destY),
moveBy = Math.min(pixelsPerTick, distLeft);
scrollWithin.scrollTop += moveBy * direction;
if (distLeft > 0) {
timerId = setTimeout(doTick, 10);
}
};
clearTimeout(timerId);
doTick();
};
}());
nav.addEventListener('click', function(event) {
var linkID,
scrollTarget;
if (event.target.tagName.toUpperCase() === "A") {
linkID = event.target.dataset.goto.slice(1);
scrollTarget = main.querySelector('[data-id="' + linkID + '"]');
scrollElementTo(main, scrollTarget, 500);
}
});
Another problem you might have with the event delegation is that if the a elements contain child elements and a child element is clicked on, it will be the target of the event instead of the a tag itself. You can work around that with something like the getParentAnchor function I wrote here.
I hope I understand the problem correctly now: You have markup that you can't change (as it's generated by some means you have no control over) and want to use JS to add functionality to the generated menu items.
My suggestion would be to add id and href attributes to the targets and menu items respectively, like so:
var links = document.querySelectorAll('a'),
paras = document.querySelectorAll('p');
for (var i = 0; i < links.length; i++) {
links[i].href=links[i].getAttribute('data-goto');
}
for (var i = 0; i < paras.length; i++) {
paras[i].id=paras[i].getAttribute('data-id');
}
I am trying to create multiple divs each with a mousedown callback.
But that callback function should not be common for all the divs , it should function differently depending upon the div clicked.
Here is the code I am using the generate the divs and setting the callbacks.
//some number
var num=4;
for(var z = 0 ; z < num ;z++)
{
//create a div with id 'z'
$("<div/>",{id:z}).appendTo("#empty");
//displaying the id on the screen
$("#"+z).text(z);
console.log("button "+z+" created");
//Callback function , which is not working as I want it to. See the bottom section for more details
$("#"+z).mousedown(function(){
console.log("Button "+z+" clicked !");
});
}
The above code runs as follows...
On clicking anyone of the divs the message "Button 4 clicked!" is generated in the console.
What should be done in order to achieve what I was aiming for ?
It would be better to use a class for the buttons and create a callback for the item.
var num=4;
for(var z = 0 ; z < num ;z++)
{
//create a div with id 'z'
$("<div/>",{id:z,class:'btn'}).appendTo("#empty");
//displaying the id on the screen
$("#"+z).text(z);
console.log("button "+z+" created");
}
$(".btn").mousedown(function(){
var z = $(this).attr('id');
console.log("Button "+z+" clicked !");
});
Keep track of your button, try modifying your code as:
var num = 4;
var btn;
for (var z = 0; z < num; z++) {
btn = $("<div>", {
id: z,
text: z
}).appendTo("#empty");
btn.on('click', function() {
alert("Button " + $(this).text() + " clicked !");
});
}
#empty div {
padding: 5px;
border: 1px solid grey;
margin-bottom: 2px;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id='empty'></div>
Using single click handler:
$(function() {
var num = 4;
var btn;
var empty = $("#empty");
empty.on('click', 'div.btn', function() {
alert("Button " + $(this).text() + " clicked !");
});
for (var z = 0; z < num; z++) {
btn = $("<div>", {
'id': z,
'text': z,
'class': 'btn'
});
empty.append(btn);
}
});
div.btn {
padding: 5px;
border: 1px solid grey;
margin-bottom: 2px;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id='empty'></div>
Give your elements a class. Then use the index of the clicked element within that class to know which one was click and act on that:
//some number
var num=4;
for(var z = 0 ; z < num ;z++)
{
$('#divHolder').append('<div class="mydivs"></div>');
}
$('body').on('mousedown', '.mydivs', function() {
// get the index of the clicked div
var curDiv = $('.mydivs').index(this);
// call a function and pass it this index
doStuff(curDiv);
});
function doStuff(clickedDiv){
// the index that was passed in will tell you what
// div was clicked do something with that
$('#show').html( 'you clickded div:' + clickedDiv);
};
.mydivs{
background-color:#cccccc;
margin-top:15px;
height:100px;
width:100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="show"></div>
<div id="divHolder"></div>
One way to resolve this problem is to handle the event outside of the for loop.
Working Code Snippet:
//some number
var num=4;
for(var z = 0 ; z < num ;z++)
{
//create a div with id 'z'
$("<div/>",{id:z}).appendTo("#empty");
//displaying the id on the screen
$("#"+z).text(z);
console.log("button "+z+" created");
}
//Callback function taken out of the for loop and added event delegation since it is a dynamically added element
$(document).on('click', 'div div', function(){
console.log("Button "+ $(this).attr('id') +" clicked !");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="empty"></div>
I have one main "Div" on which after clicking it gets split into n X n matrix. On every click inside it with a random colour div. Until here it's fine, now I want to create a click function on that random colourful div which currently is on any where inside the whole main "div"..
$(window).load(function() {
var no = 1,
$m = $(".main_div"),
size = 200;
$m.live('click', function() {
no++;
var n = no * no,
i, _size;
$m.empty();
for (i = 0; i < n; i++)
$m.append($('<div title=' + i + '/>'));
_size = size / no;
$m.find('> div').css({
width: _size,
height: _size
});
var colors = ["#FFFFFF", "#CC00CC", "#CC6699", "#0099CC", "#FF99FF"];
var rand = Math.floor(Math.random() * colors.length),
randomTotalbox = Math.floor(Math.random() * $('.main_div div').length);
$m.find("div:eq(" + randomTotalbox + ")").css("background-color", colors[rand]);
var rand = Math.floor(Math.random() * colors.length);
});
});
.main_div {
width: 200px;
height: 200px;
background-color: #9F0;
}
.main_div > div {
float: left;
box-shadow: 0 0 1px #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main_div" id="demo">
</div>
Here is a fiddle...Code
so you are saying that the clickable div is added to the DOM whenever you click(for example on a button )
that means that those divs were not there in the beginning so you can use
the Babak Naffas answer and also the .delegate method
example
$('body').delegate('.main_div > div','click',function(){
// here goes your instructions
});
for more details you can check:
jQuery: difference between .click() AND .on("click")
If you're asking for an event to be triggered when the NxN <div>s that make up the matrix are clicked, you could try
$(".main_div > div").on('click', function (evt) { ... } );
This will attach the function (the 2nd parameter) to the click event of the <div> from the matrix just like the CSS class you have with the same selector.
I am working on a wordpress website who's client would like me to adjust our AdSanity plugin to display groups of ads in a rotating image gallery fashion like the ones on this page. The leaderboard ads for sure are AdSanity run. I was able to stem from viewing the source that this is the script I need:
$(function() {
var adsLists = $('.adsanity-group'),
i = 0;
var divs = new Array();
adsLists.each(function() {
divs[i] = $("#" + $(this).attr('id') + " div").not(".clearfix").hide();
i++;
});
var cycle_delay = 12000;
var num_groups = $('.adsanity-group').length;
function cycle(divsList, i) {
divsList.eq(i).fadeIn(400).delay(cycle_delay).fadeOut(400, function() {
cycle(divsList, ++i % divsList.length); // increment i, and reset to 0 when it equals divs.length
});
};
for (var j = divs.length - 1; j >= 0; j--) {
if (divs[0].eq(0).attr('num_ads') > 1)
cycle(divs[j], 0);
else
divs[j].show();
};
//////////
$('#slides').slidesjs({
width: 552,
height: 426,
navigation: false,
play: {
auto: true
}
});
//////////
$('.three_lines_fixed').each(function() {
$clamp(this, {
clamp: 3
});
});
var top_divs = $("#adspace div").not(".clearfix").hide(),
top_i = 0;
var top_num_ads = $('#adspace > div').attr("num_ads");
var top_cycle_delay = 12000;
function top_cycle() {
top_divs.eq(top_i).fadeIn(400).delay(top_cycle_delay).fadeOut(400, top_cycle);
top_i = ++top_i % top_divs.length; // increment i,
// and reset to 0 when it equals divs.length
};
if (top_num_ads > 1) {
top_cycle();
} else {
top_divs.show();
}
var site_url = $("body").attr("site_url");
$("#brpwp_wrapper-2 ul").append("<li style='text-align: center;'><a class='widgetized_read_more' href='" + site_url + "/2013'>Read More</a></li>")
/**/
And some of that I don't believe I need, like the three_lines_fixed or the slides. I also have the CSS used for #adspace:
div.header div#adspace {
float: right;
max-width: 728px;
max-height: 90px; }
div.header div#adspace img {
float: right; }
There is also this CSS:
div#page .main_content ul.widgets li.adspace {
display: none; }
On my site http://dsnamerica.com/eisn/ I want the 300px width ads on the right sidebar to rotate like those on the Vype site. These ads though are not listed with ul and li, they are divs.
So far I've added this to my header.php theme file right before the closing tag:
<script type="text/javascript" src="<?php bloginfo('template_url'); ?>/js/fading-ads.js"></script>
And in that file (js/fading-ads.js), I have this:
function adsanitygroup() {
var adsLists = $('.adsanity-group'),
i = 0;
var divs = new Array();
adsLists.each(function() {
divs[i] = $("#" + $(this).attr('id') + " div").not(".clearfix").hide();
i++;
});
var cycle_delay = 12000;
var num_groups = $('.adsanity-group').length;
function cycle(divsList, i) {
divsList.eq(i).fadeIn(400).delay(cycle_delay).fadeOut(400, function() {
cycle(divsList, ++i % divsList.length); // increment i, and reset to 0 when it equals divs.length
});
};
for (var j = divs.length - 1; j >= 0; j--) {
if (divs[0].eq(0).attr('num_ads') > 1)
cycle(divs[j], 0);
else
divs[j].show();
var top_divs = $("#adspace div").not(".clearfix").hide(),
top_i = 0;
var top_num_ads = $('#adspace > div').attr("num_ads");
var top_cycle_delay = 12000;
function top_cycle() {
top_divs.eq(top_i).fadeIn(400).delay(top_cycle_delay).fadeOut(400, top_cycle);
top_i = ++top_i % top_divs.length; // increment i,
// and reset to 0 when it equals divs.length
};
if (top_num_ads > 1) {
top_cycle();
} else {
top_divs.show();
};
};
}
That is my attempt to define the function and clean out what I didn't need. I don't think, no, I know it's not right. So I'll put my questions in a list, since this post is already wordy.
1) Did I link the js file correctly in the theme's header.php file? It's right before the closing </head> tag.
2) Do I need the second CSS part that says "display: none" and if so, how do I change the CSS to work with divs instead of ul and li? Do I just change div#page .main_content ul.widgets li.adspace {
display: none;}
to
div#page .main_content .widgets .adspace {
display: none; }
then add the class .adspace to the widget?
See, I have been trying to get this to work for a couple days now and I've thought so much on it I'm not making cohesive theories anymore, just shots in the dark. How to solve this?