the title pretty much says everything, I did look into the images plugin from masonry yet I had no luck, I wonder if anyone could help?
The script does many things, it has the filter bit, the animation, show/hide, ajax to get the content etc etc. I'd be happy if anyone could investigate into why it is overlapping and how i could solve it based on the code below:
jQuery(function(){
jQuery('#container').masonry({
itemSelector: '.box',
animate: true
});
});
(function ($) {
// Get all menu items with IDs starting with "filter-" and loop over them
$(".menu li[id|=filter]").each(function () {
// Get the ID add extract the page class name from it (remove "filter-" from it)
var type = $(this).attr("id").replace("filter-", "");
// Get the items in the "webbies" list with that class name
var items = $("#container div[class~=" + type + "]");
// Don't do anything if there aren't any
if (items.length == 0) return;
// Get a list of the other items in the list
var others = $("#container>div:not([class~=" + type + "])");
// Add a click event to the menu item
$("a", this).click(function (e) {
// Stop the link
e.preventDefault();
// Close open item
if (openItem) {
close(openItem);
}
items.removeClass("inactive").animate({opacity: 1});
others.addClass("inactive").animate({opacity: 0.2});
});
});
$(".reset-filter a").click(function (e) {
e.preventDefault();
if (openItem) close(openItem);
$("div.box.inactive").removeClass("inactive").animate({opacity: 1});
});
var openItem;
// Opens an item
var open = function (item) {
// Close open item
if (openItem) close(openItem);
item.addClass("loading");
$("img", item).first().hide();
item.width(340);
item.height(600);
if (!item.data('loaded')) {
$("div.fader", item).load($("a", item).first().attr("href") + " #content", function () {
stButtons.locateElements();
stButtons.makeButtons();
stWidget.init();
$("#container").masonry('reloadItems', function () {
$("div.fader", item).animate({opacity: 1}, function () {
item.removeClass("loading");
$('Close"').appendTo(this).click(function (e) {
e.preventDefault();
close(item);
$(document).scrollTo( $("#navigation-block"), 600, {offset:-50} );
});
$("div.info", item).fadeIn("slow", function () {
$(document).scrollTo( $(".info"), 600, {offset:80} );
});
});
});
item.data('loaded', true);
});
} else {
item.removeClass("loading");
$("#container").masonry('reloadItems', function () {
$("div.fader", item).animate({opacity: 1}, function () {
$("div.info", item).fadeIn("slow", function () {
$(document).scrollTo( $(".info"), 600, {offset:80} );
});
});
});
}
// Set open item
openItem = item;
};
// Closes an item
var close = function (item) {
$("div.fader", item).animate({opacity: 0});
$("div.info", item).hide();
item.animate({width: 150, height: 100}, function () {
$("img", item).first().fadeIn("slow");
$("#container").masonry('reloadItems');
});
// Reset open item
openItem = null;
};
$("#container div.box").each(function () {
var item = $(this);
item.data('loaded', false);
$("div.fader", item).css("opacity", 0);
$("a.close", item).click(function (e) {
e.preventDefault();
close(item);
$(document).scrollTo( $("#navigation-block"), 600, {offset:-50} );
});
$("a.showMe", item).click(function (e) {
e.preventDefault();
if (item.hasClass("inactive")) return;
open(item);
});
});
})(jQuery);
</script>
I've experienced the same problem and I developed 2 methods to combat it. First off reload the container after you have appended the onclick-image.
1. container.masonry('reload');
Second, and probably more important, dynamically correct the height of the surrounding div to match the height of the image:
2. // bricks correct height
var brick = $("#marker #container .brick");
brick.each(function() {
var content = $(this).find(">div");
var img = $(this).find("img");
content.css({
height: img.attr("height")
});
});
So my brick is looking like this:
<div style="height: 284px; position: static; top: -133px;" class="test">
<a class="arrow" href="#" target="_self"><img class="img" src="test.jpg" width="374" height="284"></a>
</div>
Edit: In your code you have the same problem, there is no height in the style.
<div style="position: absolute; left: 330px; top: 280px;" class="box item 3d">
And it seems to me you have a problem with the width, too. I think you need to use a smaller width for the column. A good value would be the width of the small image and some border.
jQuery(function(){
var $container = $('#container');
$container.imagesLoaded( function () {
itemSelector: '.box',
animate: true
});
});
Source: jQuery Masonry Images
Related
I am trying to get Packery.js to work with LazyLoad.js, while having the ability to filter the gallery by tags.
www.temp.fokuspunkt.de
On the initial page load everything works fine:
After clicking throgh the tags and then clicking on the "all" button again, the layout is scrambled, however:
I assume this has to do with the lazy loading, as it can throw off the layout, as described in the documentation here:
https://packery.metafizzy.co/layout.html#imagesloaded
Adding the recommended solution
$grid.imagesLoaded().progress( function() {
$grid.isotope('layout');
});
throws an error, though:
My complete javascript file calling Isotope looks like this, I had tried to copy the above code right beneath the "$(window).on('load',function[...]" function block:
jQuery(function ($) {
var $grid = $('.isotope-list').packery({
layoutMode: 'packery',
filter: '*',
itemSelector: '.isotope-item',
gutter: 0,
});
$(window).on('load',function(){
$grid.packery('layout');
});
imagesLoaded( $grid ).on( 'progress', function() {
pckry.layout();
});
$('.filters li').click(function(){
//css button styling
$('.filters li').removeClass('current');
$(this).addClass('current');
// set isotope filter
var selector = $(this).attr('data-filter');
$grid.isotope({
filter: selector,
animationOptions: {
duration: 750,
easing: 'linear',
queue: false
}
});
$grid.packery('layout');
return false;
});
var $win = $(window),
$imgs = $("img"),
$loadVisible = function($els, trigger) {
$els.filter(function () {
var rect = this.getBoundingClientRect();
return rect.top >= 0 && rect.top <= window.innerHeight;
}).trigger(trigger);
}
$grid.packery('on', 'layoutComplete', function () {
$loadVisible($imgs, 'lazylazy');
$grid.packery('layout');
});
$win.on('scroll', function () {
$loadVisible($imgs, 'lazylazy');
});
$win.on('resize', function () {
$grid.packery('layout');
});
$imgs.lazyload({
effect: "fadeIn",
failure_limit: Math.max($imgs.length - 1, 0),
event: 'lazylazy'
});
});
I am certain I am doing something stupid, would anybody be kind enough to tell me what I am doing wrong? Thank you very much in advance!
So, it took a while, but I wanted to return and share my solution. Maybe it helps out somebody else in the future. My main problem was that I used isotope and packery (which is a standalone library), and not isotope and isotope-packery (which is an addon for isotope). I also changed my lazy loading plugin to "lozad", which makes a lot of thins easier.
In the code below you can also find a solution for using multiple filter terms in combination. In my case I use a row of row of radio buttons below the old button row you can see above.
jQuery(function ($) {
// initialize Packery
var $pckry = $('.isotope-list').isotope({
layoutMode: 'packery',
filter: '*',
itemSelector: '.isotope-item',
packery: {
gutter: 0
},
animationOptions: {
duration: 750,
easing: 'linear',
queue: false
}
});
// layout on first page load, so that the gutter gets set up
$(window).on('load', function () {
$pckry.isotope('layout');
});
// filter items on button click
$('.filters li').click(function () {
$('.filters li').removeClass('current');
$(this).addClass('current');
var combinedFilter = getFilter($('.filters li.current').attr('data-filter')) + getFilter($('input[name="isotope-type-filter"]:checked').val().toLowerCase());
$pckry.isotope({ filter: combinedFilter });
$pckry.isotope('layout');
});
// filter items on radio button change
$('input[name="isotope-type-filter"]').change(function () {
var combinedFilter = getFilter($('.filters li.current').attr('data-filter')) + getFilter($('input[name="isotope-type-filter"]:checked').val().toLowerCase());
$pckry.isotope({ filter: combinedFilter });
$pckry.isotope('layout');
});
function getFilter(buttonGroup) {
var filterValue = '';
if (buttonGroup === '*') {
filterValue = "";
} else {
filterValue = "." + buttonGroup;
}
return filterValue;
};
});
I'm using waypoints to have fadeIn animation when the user scrolled down, and it worked. But as you can see, during the onload, there's a fadeIn too for the first few visible items.
How to not to have that? since I binded all .card to way[point.
My js
$(function() {
var waypoints = $('.card').waypoint(function (direction) {
$(this).addClass("animated fadeIn");
}, {
offset: '90%'
});
});
DEMO : http://jsfiddle.net/ghx49d7x/
Not sure if its exactly what you want, but you can add a variable to indicate if the page has loaded or not and only add fadeIn if it has:
$(function () {
var pageLoaded = false;
var waypoints = $('.card').waypoint(function (direction) {
$(this).addClass("animated"
+ (pageLoaded ? " fadeIn" : ""));
}, {
offset: '90%'
});
pageLoaded = true;
});
Updated Fiddle: http://jsfiddle.net/ghx49d7x/3/
When the blue button is clicked it affects both buttons
http://jsfiddle.net/umbriel/Lwvukzhy/1/
My setup looks like this
var
$window = $(window),
$body = $('body'),
$buttonRight = $('.button .right')
;
$buttonRight.on('click', function( ) {
buttonReveal( $( this ) );
});
function buttonReveal() {
$buttonLeft.css({'width':'25%'});
$buttonRight.css({'width':'75%'});
}
I want to to only affect one of buttons I clicked
Thank you
Use .siblings() to get siblings. Try this:
$buttonRight.on('click', function( ) {
buttonReveal($(this)); //$(this) refers to current clicked element (button)
});
$buttonLeft.on('click', function() {
buttonHide($(this)); //$(this) refers to current clicked element (button)
});
function buttonReveal(element) {
element.siblings($buttonLeft).css({'width':'25%'}); //to apply css to siblings use .siblings()
element.css({'width':'75%'});
}
function buttonHide(element) {
element.css({'width':'0%'});
element.siblings($buttonRight).css({'width':'100%'});
}
DEMO
You need to target the left/right buttons which is related to the clicked button. So you need to pass the clicked button to buttonReveal() and buttonHide().
So
(function (window, $) {
var
$window = $(window),
globalTimeout = null,
$body = $('body'),
$buttonRight = $('.button .right'),
$buttonLeft = $('.button .left');
$buttonRight.on('click', function () {
buttonReveal(this);
});
$buttonLeft.on('click', function () {
buttonHide(this);
});
function buttonReveal(button) {
var $btn = $(button).css({
'width': '75%'
});
$btn.prev('.left').css({
'width': '25%'
});
}
function buttonHide(button) {
var $btn = $(button).css({
'width': '0%'
});
$btn.next('.right').css({
'width': '100%'
});
}
}(window, $));
Demo: Fiddle
I'm trying to code a function that let me toggle in and out all thumbnails in a list depending on their classes.
e.g., if I click "print" on my menu bar, I need all thumbs with the "print" class to be hidden. If I click it a second time, the hidden thumbs are showing up.
Here is what I came up with :
window.addEvent('domready', function(){
$$('.menu_button').toggle(
function() {
this.fade(0.5);
var buttonId = this.id;
$('slider_list').getElements('.'+buttonId).each(function(li) {
li.tween('width','0');
});
},
function() {
this.fade(1);
var buttonId = this.id;
$('slider_list').getElements('.'+buttonId).each(function(li) {
li.tween('width','100');
});
}
);
});
//toggle (emulate JQuery's toggle)
(function() {
var toggled = 0;
Element.implement({
toggle: function(fn1, fn2) {
var fns = [fn1, fn2];
return this.addEvent('click', function(){
fns[toggled].apply(this, arguments);
toggled = toggled == 0 ? 1 : 0;
});
}
});
})();
I've found the toggle function here
Now I experience some issues.
First no matter what I do there will always be a thumb left at the end of the list.
Then some clicks on the menu won't do anything. Generally when I click on a button in a different state (hidden/shown) than the previous one, there will always be a null click...
Anybody ?
I implemented it in a way that allows multiple functions, although not at all MooTools like, it will work. The problem with the code you are using is that each element which uses toggle is toggling the same toggled variable
Element.implement({
toggle: function() {
this.store('toggle_options', {
fn: arguments,
cur: 0
});
this.addEvent('click', function(e) {
e.stop();
var opts = this.retrieve('toggle_options');
console.log(opts.fn.length, opts.cur);
opts.fn[opts.cur++].apply(this);
if(opts.cur >= opts.fn.length) opts.cur = 0;
});
}
});
$('button').toggle(
function() {
this.set('text', 'foo 1');
},
function() {
this.set('text', 'bar 2');
}
);
fiddle here: http://jsfiddle.net/94FFj/
Although I would recommend you implemented your code as this:
$$('.menu_button').each(function(button) {
button.store('toggle_active', 0);
button.addEvent('click', function(e) {
e.stop();
var active = this.retrieve('toggle_active');
var opts = [{opacity: 1, width: 0}, {opacity: 0.5, width: 100}];
this.fade(opts[active].opacity);
$$('slider_list .' + this.get('id')).tween('width', opts[active].width);
this.store('toggle_active', active ? 0 : 1);
});
})
I have two jquery.ui draggables. I am constraining their movement to the y-axis. If one is dragged to a certain y-position, I want the other to automatically move to the same y-position and vice versa. Has anyone ever linked two of these together before?
Updated: Script and demo updated so it is no longer restricted to the y-axis while dragging.
This script looks for the class "group" followed by a number to drag/drop these combined objects. I posted a demo here.
HTML
<div class="demo">
<div id="draggable">
<p>Drag from here</p>
<div class="dragme group1"><img src="image1.jpg"><br>Group 1</div>
<div class="dragme group1"><img src="image2.jpg"><br>Group 1</div>
<div class="dragme group2"><img src="image3.jpg"><br>Group 2</div>
<div class="dragme group2"><img src="image4.jpg"><br>Group 2</div>
</div>
<div id="droppable">
<p>Drop here</p>
</div>
</div>
Script
$(document).ready(function() {
// function to get matching groups (change '.group' and /group.../ inside the match to whatever class you want to use
var getAll = function(t) {
return $('.group' + t.helper.attr('class').match(/group([0-9]+)/)[1]).not(t);
};
// add drag functionality
$(".dragme").draggable({
revert: true,
revertDuration: 10,
// grouped items animate separately, so leave this number low
containment: '.demo',
stop: function(e, ui) {
getAll(ui).css({
'top': ui.helper.css('top'),
'left': 0
});
},
drag: function(e, ui) {
getAll(ui).css({
'top': ui.helper.css('top'),
'left': ui.helper.css('left')
});
}
});
$("#droppable").droppable({
drop: function(e, ui) {
ui.draggable.appendTo($(this));
getAll(ui).appendTo($(this));
}
});
});
I haven't done this before, but I suggest using the drag event to adjust the position of the respective other element:
$('.selector').draggable({
...,
drag: function(event, ui) {
},
...
});
The ui object will contain information (in the property ui.offset) you can use to manually reposition the other element.
https://forum.jquery.com/topic/dragging-a-group-of-items-alsodrag-like-alsoresize
I found an extension for UI draggable(). It works in the same way as 'alsoResize' for UI resizable(), i.e.
$('.selector').draggable({ alsoDrag: '.selected' });
Add the plugin code after main jquery-ui library.
$.ui.plugin.add( 'draggable', 'alsoDrag', {
start: function() {
var that = $(this).data("ui-draggable"),
o = that.options,
_store = function (exp) {
$(exp).each(function() {
var el = $(this);
el.data("ui-draggable-alsoDrag", {
top: parseInt(el.css("top"), 10),
left: parseInt(el.css("left"), 10)
});
});
};
if (typeof(o.alsoDrag) === "object" && !o.alsoDrag.parentNode) {
if (o.alsoDrag.length) { o.alsoDrag = o.alsoDrag[0]; _store(o.alsoDrag); }
else { $.each(o.alsoDrag, function (exp) { _store(exp); }); }
}else{
_store(o.alsoDrag);
}
},
drag: function () {
var that = $(this).data("ui-draggable"),
o = that.options,
os = that.originalSize,
op = that.originalPosition,
delta = {
top: (that.position.top - op.top) || 0,
left: (that.position.left - op.left) || 0
},
_alsoDrag = function (exp, c) {
$(exp).each(function() {
var el = $(this), start = $(this).data("ui-draggable-alsoDrag"), style = {},
css = ["top", "left"];
$.each(css, function (i, prop) {
var sum = (start[prop]||0) + (delta[prop]||0);
style[prop] = sum || null;
});
el.css(style);
});
};
if (typeof(o.alsoDrag) === "object" && !o.alsoDrag.nodeType) {
$.each(o.alsoDrag, function (exp, c) { _alsoDrag(exp, c); });
}else{
_alsoDrag(o.alsoDrag);
}
},
stop: function() {
$(this).removeData("draggable-alsoDrag");
}
});
You would have to explicitly set the Y-Axis of both the elements.
For this either in the event handler functions of both the elements you will have to set Y-Axis or bind both the elements with same function.
Happy coding.
Here is a simplified version of the code mentioned in the marked answer(for dummies like me):
In HTML
<div id="div1" class="group">...</div>
<div id="div2"class="group">...</div>
In Script tag
$(document).ready(function(){
//to get the group
var getGroup = function() {
return $(".group");
}; // add drag functionality
$(".group").draggable({
revertDuration: 10,
// grouped items animate separately, so leave this number low
containment: "window",
scroll: false,
stop: function(e, ui) {
getGroup(ui).css({
'top': ui.helper.css('top'),
});
},
drag: function(e, ui) {
getGroup(ui).css({
'top': ui.helper.css('top'),
'left': ui.helper.css('left')
});
}
});
});