Isotope appended broke remaining jQuery - javascript

I have an instance of Isotope on my website that seems to have broken the remainder of my javascript functions after converting it to use the appended method. When I had all of my images were initially in the markup on my index.html, both isotope's filtering as well as a lightbox plugin I had for each image were working beautifully. Now I have implemented it as follows (using most of Desandro's code for Isotope:
HTML:
<div class="main">
<div id="filters" class="button-group">
<p>FILTER:</p>
<button class="selected" data-filter="*">SHOW ALL</button>
<button class="" data-filter=".photography">PHOTOGRAPHY</button>
<button class="" data-filter=".film">FILM</button>
<button class="" data-filter=".design">DESIGN</button>
</div>
<div class="isotope">
<div class="grid-sizer"></div>
</div>
</div>
Javascript:
$(function() {
var $container = $('.isotope');
$container.isotope({
"itemSelector": ".item",
"columnWidth": ".grid-sizer"
});
function getItemPhotography(i) {
var item = '<div class="item photography"><a class = "fluidbox" href = "img/photography/' + i + 'big.jpg" title = "Click to enlarge"><img src = "img/photography/' + i + '.jpg" class = "image"/></a></div >';
return item;
}
function getItemDesign(i) {
var item = '<div class="item design"><a class = "fluidbox" href = "img/design/' + i + 'big.png" title = "Click to enlarge"><img src = "img/design/' + i + '.png" class = "image"/></a></div >';
return item;
}
var $items = getItems();
// hide by default
$items.hide();
// append to container
$container.append($items);
$items.imagesLoaded().progress(function(imgLoad, image) {
// image is imagesLoaded class, not <img>
// <img> is image.img
var $item = $(image.img).parents('.item');
$item.show();
$container.isotope('appended', $item);
});
function getItems() {
var items = '';
for (var i = 1; i < 38; i++) {
items += getItemPhotography(i);
}
for (var i = 1; i < 4; i++) {
items += getItemDesign(i);
}
// return jQuery object
return $(items);
}
});
This part was broken after adding in the above:
//Filtering for isotope
$(function() {
$('#filters').on('click', 'button', function() {
var filterValue = $(this).attr('data-filter');
$container.isotope({
filter: filterValue
});
});
$("button").click(function() {
// Reset them
$("button").removeClass("selected");
// Add to the clicked one only
$(this).addClass("selected");
});
});
//Fluidbox lightbox plugin
$(function() {
$('.fluidbox').fluidbox();
});
The images are appending to the Isotope container and laying out as expected. However, now filtering is broken for Isotope, and the Fluidbox lightbox instance is not working either.
Thanks so much for any help. I have been struggling with this for the past few hours and am starting to think it may be as simple as my function initializations or a semicolon somewhere.

Resolved. Missing a reference for $container in the function for isotope filters.

Related

JS hover negative space between items

So I have a container with a grid of items and I want to be able to detect hover between rows. Not the individual items.
Its important to remember that the number of items, in the container and per row, will change.
My container of items currently looks like this
<div class="container">
<div class="hover-placeholder"></div>
<div class="row">
<!-- Start : Items -->
<div class="col-md-3">...</div>
<div class="col-md-3">...</div>
<div class="col-md-3">...</div>
<div class="col-md-3">...</div>
...
<div class="col-md-3">...</div>
<!-- End : Items -->
</div>
</div>
Preferably I DO NOT want to put a placeholder element every 4th item. Mainly because on smaller screens the number of items per row will reduce. This is why in my example above I have a single placeholder outside the grid that I want to transform: translateY(..) to the position between the hovered rows.
This is what I have currently: https://jsfiddle.net/0t8c0h4m/
Its nowhere near the result I am after but I have got to the point where I am overthinking it and getting stuck.
Any help would be great!
UPDATE
The goal for this functionality is when the user hovers the negative space, the .hover-placeholder will translate to that position and become visible. And when clicked will add a permanent separator between the rows.
SUCCESS!
I have solved my issue! Thank you all for your help.
Here is my solution: https://jsfiddle.net/0t8c0h4m/9/
I think that you are complicating stuff too much if you are only looking for the hover effect between the elements and nothing else.
Updated:
var offsets;
function get_offsets() {
offsets = {};
$('.card').each(function() {
var $this = $(this);
var card_offset = $this.offset().top;
offsets[card_offset] = {
ele: $this
};
})
}
get_offsets();
function get_last_ele(mouse_location) {
var element;
var previous_key;
$.each(offsets, function(key, obj) {
if (key > mouse_location && previous_key > 0) {
element = offsets[previous_key].ele;
return false;
}
previous_key = key;
})
return element;
}
$('.container').mousemove(function(e) {
if ($(e.target).parents('.row').length == 0) {
var last_item_row = get_last_ele(e.pageY)
console.log(last_item_row.text())
}
});
JSFiddle: https://jsfiddle.net/0t8c0h4m/6/
I'm only providing the code that gets the last item on the row before the space you are hovering. From there you can append the line or transition the placeholder the way you like it.
Please try with following script
(function($) {
'use strict';
// Count items per row
function items_per_row($collection) {
var count = 0;
$collection.each(function() {
var $this = $(this);
if ($this.prev().length > 0) {
if ($this.position().top !== $this.prev().position().top) {
return false;
} else {
count++;
}
} else {
count++;
}
});
var last = count ? $collection.length % count : 0,
rows = count ? Math.round($collection.length / count) : 0;
if (last == 0) {
last = count;
}
return {
count: count,
last: last,
rows: rows
}
};
// On card hover, print current row
$('.card').mouseenter(function() {
var $card = $(this);
var item_count = items_per_row( $('.card') ),
index = $(this).index(),
current_row = Math.floor(index / item_count.count) + 1;
$('pre').text( $card.find('.inner').text() + ' is in row '+ current_row );
});
$('.card').mouseout(function(){
$('pre').text('');
});
})(jQuery);
So I have come up with a solution to show dividers between each row using CSS. I just have been overthinking this issue.
I have added a dividing element after each item and with css nth-child() I can show specific dividers at each break point.
I have also added the grouping functionality I was aiming for.
Updated example: https://jsfiddle.net/0t8c0h4m/9/

jquery dynamic content generated by dynamic content

(function(){
if (typeof $(".grid") === "undefined") {
return false;
} else {
var count = 0;
var images_to_place_container = ".grid";
for (var image in images_to_place) {
$(images_to_place_container).prepend("<div class = grid-item><div class=grid-item-hover></div></div>");
count++;
}
}
})();
I have this code that is dynamically generating images for a site, now what I want is that when I hover over one of these elements, I want to dynamically generate a div that is the same size and in the same position as the dynamically generated object I hovered over . Also, all elements are absolutely positioned using CSS. Thanks.
<body>
<div class='container'>
</div>
</body>
<script>
$(document).ready(function(){
//this dynamically "creates" the images...
$(".container").append("<img src='something.png' class='abc'>");
//this watches for click triggers on dynamically created elements
$(".container").on("click", "img.abc", function(){
var pos_top = $(this).css("top");
var pos_left = $(this).css("left");
var obj = "<div class='def'></div>";
$(obj).css("top", pos_top);
$(obJ).css("left", pos_left);
$(".container").append(obj);
});
});
</script>
Give classes abc and def the necessary css rules such as position, margin etc.

jQuery script that replaces every dom element with a custom tag

I am working on a script that queries all the dom elements from a div and replaces them with some custom markup - the script should work... but obviously it doesn't and I have no idea why.
Here is the js:
var data = {
SPAN: function(content) {
return '|span|' + content + '|span|'
},
DIV: function(content) {
return '|div|' + content + '|div|'
},
P: function(content) {
return '|p|' + content + '|p|'
},
H2: function(content) {
return '|h2|' + content + '|h2|'
},
}
$(document).ready(function() {
// Iterate through each element of the dom.
$('#result *').each(function () {
var type = $(this)[0].tagName;
var content = $(this).html();
if (data[type]) var result = data[type](content);
if (result) $(this).replaceWith(result);
});
console.log($('#result').html())
});
This is the html I target:
<div id="result">
<div id="wrap">
<div class="about">
<p>Hello, I am a web dev, <span class="italicStyle">the best!</span></p>
</div>
<div class="evenMore">
<h2>Yes, I am a big heading 2.</h2>
</div>
</div>
</div>
I should be seeing every div, span, p replaced accordingly... why doesn't it work?
The code replaces only the first dom elm... here is the result:
|div|
Hello, I am a web dev, the best!
Yes, I am a big heading 2.
|div|
This is because you start from the bottom to the top and rewrite the entire HTML. You see, you first iteration is on the div and you do $(this).replaceWith(result).
This means you are changing all of its children, so the second div in the iterations no longer exists in the first one.
You can achieve what you want by reverse looping. It means starting from the last element:
var $elements = $('#result *');
for(var i = $elements.length - 1; i >= 0; i--)
(function() {
var type = $(this)[0].tagName;
var content = $(this).html();
if (data[type]) var result = data[type](content);
if (result) $(this).replaceWith(result);
}).call($elements[i]);
Fiddle : http://jsfiddle.net/nHjCE/

Click based upon value of hash on url

I'm new to working with JS/jQuery, I've been currently trying to figure out how to make this work, by trying many different ways that I've found here and on different sites, and am unable to get this working.
I have a website that has tabs, that changes a div's content when the click on the buttons in the menu. This all works fine, but I want to be able to link to each separate "page" using hash tags example.com/#tab-1
HTML:
<div class="tabWrapper">
<div class="tabContent">
<div class="label">TAB 1</div>
<?php include 'tab1.php'; ?>
</div>
<div class="tabContent">
<div class="label">TAB 2</div>
<?php include 'tab2.php'; ?>
</div>
tabWrapper looks like this after being generated
<div class="tabWrapper">
<ul class="tabs">
<li class="tab-1">TAB 1</li>
<li class="tab-2">TAB 2</li>
</ul>
JS :
// Generate tab navigation
if ($('div.tabWrapper').length != 0)
{
$('div.tabWrapper').each(function()
{
// Prepare tab output
var printTabs = '<ul class="tabs">';
var tabContent = $(this).find('.tabContent');
var tabCount = tabContent.length;
$(tabContent).each(function(key)
{
// Hide tab if it is not the first
if (key != 0)
{
$(this).hide();
}
// Get label for tab
var label = $(this).find('.label').text();
// Use a number if no label was given
if (!label)
{
label = 'Tab ' + (key + 1);
}
// Add id to tab content
$(this).addClass('tab-' + key);
printTabs+= '<li class="tab-' + key + '">' + label + '</li>';
});
// Add tabs
$(this).prepend(printTabs + '</ul>');
$(this).find('li:first').addClass('active');
});
}
// Handle click on tabs
$('.tabWrapper').delegate('ul.tabs li', 'click', function()
{
// Deny click on active element
if ($(this).is('.active'))
{
return false;
}
// Get tab id
var id = $(this).attr('class').split('-');
id = id[1];
// Display and animate new tab content
var parent = $(this).parent().parent();
parent.find('ul.tabs li').removeClass('active');
$(this).addClass('active');
parent.find('.tabContent').hide()
parent.find('.tab-' + id).animate({ opacity: 'show' }, animationSpeed);
});
Here is what I was trying to add, which I don't think is correct
function hash() {
if(window.location.hash){
var hash = window.location.hash.substring(1);
$("." + hash).click();
}
}
which I added in the js file just above
$('.tabWrapper').delegate('ul.tabs li', 'click', function()
I'm not sure how far I'm off with that code, as it doesn't seem to work at all. I just want it to see if there is a hash tag in the url, and if there is then run the click function to change the content.
I hope I explained what I was looking for clear enough. I'd very much appreciate any help with this.
Thank you.
UPDATE:
I updated the code with setInterval as per chiliNUT's suggestion, however it still doesn't appear to be working.
setInterval(hash,1000);
function hash() {
if(window.location.hash){
var hash = window.location.hash.substring(1);
$("." + hash).click();
}
}
UPDATE 2:
Still unable to get this working, anyone able to help?
Thanks.
My tip is using anchor tags as well.
Link
That will open example.com#tab1
The control on page load:
$( document ).ready(function() {
if(window.location.hash == "#tab1"){
$("#someId").click();
}
});
Why not just use anchor tags?
Button to open tab 1

Iterate through array elements one by one when clicking on button

How can I have it so that each time the button is clicked the array is iterated through once? If I click it a second time, it should display the second array element, etc. until it iterates through the entire array.
JavaScript:
var images = [
"<img src='first.png' />",
"<img src='second.png' />",
"<img src='third.png' />",
"<img src='kitten.png' />"
];
var button = document.getElementsByClassName("btn-lg")[0];
button.addEventListener("click", function(){
for(i = 0; i < 5; i++) {
jQuery('.row.text-center').append(images[i]);
}
});
HTML:
<div class="row text-center">
<button type="submit" class="btn btn-lg btn-info">Click Here!</button>
</div>
jsfiddle: http://jsfiddle.net/KVs6S/1/
Thanks!
Since you are using jQuery then you may try (don't mix up vanilla js liike addEventListener)
$(function(){
var images = [
"http://imageshack.us/a/img9/6564/3qv9.png",
"http://imageshack.us/a/img9/4521/3dmc.png",
"http://imageshack.us/a/img28/3608/1x6h.png",
"http://imageshack.us/a/img850/1713/5i6g.png"
];
$(".btn-lg").on("click", function(){
if(images.length) {
var img = $('<img/>', { 'src':images.pop() });
$('.row.text-center').append(img);
}
});
});
Also, Array.pop() is enough for this and just keep the urls instead of images in the array.
DEMO. (Images are getting appended but for your big button these are not visible.)
Externalize the counter :
var i=0, images = [
"<img src='first.png' />",
"<img src='second.png' />",
"<img src='third.png' />",
"<img src='kitten.png' />"
];
jQuery('.btn-lg').on("click", function(){
if (i>=images.length) return;
jQuery('.row.text-center').append(images[i++]);
});
Make i a variable starting from 0 and increment it resp. when lenght is greather than images count - restart:
var i = 0;
var button = document.getElementsByClassName("btn-lg")[0];
button.addEventListener("click", function(){
if (i == 4) { i = 0; /* OR return; to stop */ }
jQuery('.row.text-center').append(images[i++]);
});
Use a closure:
function yield(lenArray) {
var i=0;
console.log("outer",lenArray);
return function() {
if (i<lenArray) {
console.log("inner",i);
jQuery('.row.text-center').append(images[i++]);
}
}
}
button.addEventListener("click", yield(5));
How do JavaScript closures work?

Categories

Resources