I have used masonry layout in grid class and grid-items are the column. I am loading masonry on load event like below
$(window).load(function () {
$('.grid').masonry({
// options
itemSelector: '.grid-item',
horizontalOrder: true,
isAnimated: true,
animationOptions: {
duration: 1000,
easing: 'linear',
queue: false
}
});
});
and my HTML is below, I'm loading items via ajax. some times it is load proper and sometimes overlaps my footer content or div. as shown in the below screenshot.
<div class="grid">
<div class="grid-item">
<img src="images/grid1.jpg" alt="Banner"></a>
</div>
</div>
The Masonry is firing before images are fully loaded. You can use imagesLoaded (which is being loaded on your page) to determine when the images are loaded into a container. Then fire off Masonry. Something like:
var $container = $('#masonry-grid');
$container.imagesLoaded(function(){
runMasonry();
});
I just found out an alternative fix: I created a canvas element with the correct sizes instead of only loading and placing the images. This »canvas« is used as a placeholder for ratio calculations. The images sits with position absolute on top.
Caveat: you need to know the image sizes/ratio. In my wordpress case they are embedded in the json call.
It even works in Internet Explorer 11.
What fixed the issue for me was just appending the elements in a setTimeout function.
$.ajax({
url: ajaxURL,
type: 'post',
data: {
page: page,
action: 'load_more'
},
success: function(response) {
let el = $(response)
that.data('page', newPage);
setTimeout(function() {
$('#masonry').append(el).masonry('appended', el, true);
}, 1000);
},
error: function(response) {
console.log(response);
}
});
Related
I am using TippyJS to show a tooltip but for some reason when first click the tooltip it is positioned way too much to the right, and if you have a small screen it will even go outside of view.
Example:
While after I scroll a bit, or resize the page it gets positioned correctly.
Example:
What could be causing this behaviour?
Example codepen (shopping cart is empty but still has the same behaviour when clicking/scrolling): https://codepen.io/twan2020/pen/ZEBvYXv
I've tried setting boundary:viewport in the options like this:
$( ".carttip" ).each(function( i ) {
tippy(this, {
theme: 'blue',
trigger: 'click',
allowHTML: true,
animation: 'scale-subtle',
maxWidth: 400,
boundary: 'viewport',
interactive: true,
content: function (reference) {
return reference.querySelector('.tooltipcontent');
},
onShow(instance) {
refreshcart(true);
}
});
});
But this changed nothing.
As Stavros Angelis points out, the tippy instance positioning is already calculated when the content is applied. To reposition the tooltip when the ajax call resolves, you could pass the tippy instance into the refreshcart() function and then accessing the popper instance inside it to refresh the tooltip:
function refreshcart(force, tippyInstance) {
$.ajax({
type: 'post',
url: 'includes/refreshcart.php',
data: ({}),
success: function(data){
$('body #headercart').empty().append(data);
tippyInstance.popperInstance.update(); // Here, the tippy positioning is updated
}
});
}
// other code...
$( ".carttip" ).each(function( i ) {
tippy(this, {
theme: 'blue',
trigger: 'click',
allowHTML: true,
animation: 'scale-subtle',
maxWidth: 400,
boundary: 'viewport', // This has been dropped in tippy#6
interactive: true,
content: function (reference) {
return reference.querySelector('.tooltipcontent');
},
onShow(instance) {
refreshcart(true, instance);
}
});
});
As for the boundary: seems like tippy#6 (which your example uses) has dropped this prop, so it can be removed here.
More on the popper instance here: https://github.com/atomiks/tippyjs/issues/191
The problem comes from the onShow function. The way your code works is that first you open the popup, then you do an ajax call and fetch some html to append in the tippy box. At that point the tippy box has already rendered and calculated the position of the box with a 0 width and 0 height. Then the ajax call completes and the container changes dimensions and ends up outside the viewport.
The tippyjs documentation covers that here with a very clean example: https://atomiks.github.io/tippyjs/v6/ajax/
I'm building a fancybox modal(v3) with inside it two owl carousels(v2). It's used as a product quick view function.
The problem I'm facing is that the second carousel (used for the thumbs) doesn't have core css styles applied, while the carousel is actually initialized.
So the two carousels are initialized but one just won't use styling from the actual owl-carousel.css stylesheet.
I'm completly confused.
I've created a fiddle here with the actual problem.
My html
<div id="quick-shop-modal" class="cd-quick-view" style="display:none;">
<div class="product-images-slider">
<div class="slider-container"></div>
<div class="thumbnail-slider-container"></div>
</div>
</div>
Quick shop
Jquery
$(document).ready(function() {
$(".quick_view").on('click', function() {
var url = 'some-url'
$.fancybox.open({
touch: false,
src: '#quick-shop-modal',
type: 'inline',
beforeShow: function() {
quick_shop(url)
}
});
});
});
function quick_shop(url) {
var $modal = $('#quick-shop-modal');
$.getJSON(url, function(data) {
$modal.data('product', data.product);
var product = data.product;
var images = '';
$.each(product.images, function(index, image_id) {
images += '<div class="item"><div class="content"><img src="https://via.placeholder.com/350x150" class="img-responsive"></div></div>';
});
$modal.find('.slider-container').html('<div id="slider" class="slider owl-carousel">' + images + '</div>')
$modal.find('.thumbnail-slider-container').html('<div id="thumbnailSlider" class="thumbnail-slider">' + images + '</div>')
$modal.find('.slider').owlCarousel({
loop: false,
nav: false,
items: 1
}).on('changed.owl.carousel', function(e) {
$modal.find('.thumbnail-slider').trigger('to.owl.carousel', [e.item.index, 300, true]);
});
$modal.find('.thumbnail-slider').owlCarousel({
loop: false,
margin: 10,
nav: false,
items: 3,
stagePadding: 40
}).on('click', '.owl-item', function() {
$modal.find('.slider').trigger('to.owl.carousel', [$(this).index(), 300, true]);
}).on('changed.owl.carousel', function(e) {
$modal.find('.slider').trigger('to.owl.carousel', [e.item.index, 300, true]);
});
});
}
1) I do not think that anyone would be able to help you without seeing live demo and probably no-one will spend time to create it for you.
2) From you code, it seems that changing one slider would trigger change callback on both sliders. IF that is true, than that could cause the issues.
3) It is not possible to tell what role of fancybox is here just by looking at those pieces of code (e.g., what is webdinge_quick_shop doing; if #webdinge-quick-shop-modal exists, then fancybox should work fine)
Edit & Answer to updated question -
Your 2nd own carousel is missing owl-carousel classname, simply add .owl-carousel to .thumbnail-slider element, see http://jsfiddle.net/zLfnmrx1/
I have a website the uses bootstrap and the news that I have created with masonry, I used the Infinite Ajax Scroll, that call other news in a different div instead the pre-default. Very often, however, if one scrolls the page quickly, or if you have a slow connection, the elements overlap and do not return to their place, and I think this is due to the fact that it can't load images.
I tried to integrate Imagesloaded but it seems not work properly... and I don't know what to do...
Here is the source as I have proceeded,
HTML:
<div class="row masonry_base altre">
{$news}
</div>
<div class="row masonry altre">
<div class="col-lg-4 col-md-6 col-xs-12 post-grid">
{$news_scroll}
</div>
</div>
JS:
<script>
(function($) {
"use strict";
var $container = $('.masonry_base');
$($container).imagesLoaded( function(){
$($container).masonry({
itemSelector: '.post-grid',
columnWidth: '.post-grid'
});
});
})(jQuery);
</script>
<script type="text/javascript">
var container = document.querySelector('.masonry');
var msnry = new Masonry( container, {
itemSelector: '.post-grid',
gutterWidth: 20
});
msnry.reloadItems()
var $container = $('.masonry');
$($container).imagesLoaded( function(){
$($container).masonry({
itemSelector: '.post-grid',
columnWidth: '.grid',
gutterWidth: 20
});
});
var ias = $.ias({
container: ".masonry",
item: ".post-grid",
pagination: "#pagination",
next: ".next a",
delay: 1200
});
ias.on('render', function(items) {
$(items).css({ opacity: 0 });
});
ias.on('rendered', function(items) {
msnry.appended(items);
});
ias.extension(new IASSpinnerExtension());
ias.extension(new IASNoneLeftExtension({
html: '<div class="btn btn-info btn-block btn-icon-left ias-noneleft" style="text-align:center"><p><em>No news</em></p></div>'
}));
</script>
This code :
$($container).imagesLoaded( function(){
$($container).masonry({
itemSelector: '.post-grid',
columnWidth: '.grid',
gutterWidth: 20
});
});
Only applies imagesLoaded to whatever $container happens to be at its execution. It doesn't apply to dynamically added content. You should call this function again to the dynamic content added. Perhaps in your rendered callback.
Also, you should just call msnry.layout() to adjust content after the images had been loaded (It's not necessary to call $.masonry again)
Hope it helps
So if you check out: http://uniplaces.micrositesonline.info/blog/cities/ you'll see the isotope masonry plugin in action. The entire theme is from https://themetrust.com/demos/swell/. The issue is, on our site, the isotope plugin loads in a strange manner, the div that contains the masonry images fails to adjust the height properly and thus, it sometimes gets cut off. You can typically replicate this by reloading the page once it has loaded.
The code containing the js is in 'themetrust.js':
///////////////////////////////
// Project Filtering
///////////////////////////////
function projectFilterInit() {
if( jQuery('#filter-nav a').length > 0 ) {
jQuery('#filter-nav a').click(function(){
var selector = jQuery(this).attr('data-filter');
jQuery('#projects.thumbs').isotope({
filter: selector,
hiddenStyle : {
opacity: 0,
scale : 1
}
});
if ( !jQuery(this).hasClass('selected') ) {
jQuery(this).parents('#filter-nav').find('.selected').removeClass('selected');
jQuery(this).addClass('selected');
}
return false;
});
} // if() - Don't have this element on every page on which we call Isotope
}
///////////////////////////////
// Project thumbs
///////////////////////////////
function isotopeInit() {
setColumns();
gridContainer.isotope({
resizable: true,
layoutMode: 'masonry',
masonry: {
columnWidth: colW
}
});
jQuery(".thumbs .small").css("visibility", "visible");
}
///////////////////////////////
// Isotope Grid Resize
///////////////////////////////
function setColumns()
{
var columns;
var gw = gridContainer.width();
var ww = jQuery(window).width()
if(ww<=700){
columns = 1;
}else if(ww<=870){
columns = 2;
}else{
columns = 3;
}
colW = Math.floor(gw / columns);
jQuery('.thumbs .small').each(function(id){
jQuery(this).css('width',colW+'px');
});
jQuery('.thumbs .small').show();
}
function gridResize() {
setColumns();
gridContainer.isotope({
resizable: false,
layoutMode: 'masonry',
masonry: {
columnWidth: colW
}
});
}
///////////////////////////////
// Center Home Banner Text
///////////////////////////////
function centerHomeBannerContent() {
var bannerContent = jQuery('.home #banner-content');
var bannerContentTop = (windowHeightAdjusted/2) - (jQuery('.home #banner-content').actual('height')/2);
bannerContent.css('margin-top', bannerContentTop+'px');
bannerContent.show();
}
///////////////////////////////
// Initialize
///////////////////////////////
jQuery.noConflict();
jQuery(document).ready(function(){
jQuery(".content-area").fitVids();
mmenu_nav();
jQuery('#video-background').height(windowHeight);
video_resize();
if(!isMobile()){
getVideoBGs();
}
jQuery('body').imagesLoaded(function(){
projectFilterInit();
isotopeInit();
centerHomeBannerContent();
});
jQuery(window).smartresize(function(){
gridResize();
//full_width_images();
video_resize();
mmenu_nav();
centerHomeBannerContent()
});
//Set Down Arrow Button
jQuery('#down-button').click(function(){
jQuery.scrollTo( ".middle", {easing: 'easeInOutExpo', duration: 1000} );
});
//pull_out_the_quote();
//full_width_images();
});
We've tried modifying it to no avail, removing and tweeking, but nothing seems to work. At this point we think it make be the css transition initialized by the class isotope-item, so we removed it, which seems to work but we are not entirely sure why. Is it possible to retain the transitions and get the isotope plugin to behave with them reliably?
WOOOO that theme is mental to say the least.
There are so many HTTP request's it's not surprising it's failing to load some scripts within the exec time.
Right because this is a theme and we don't want to mess about with stuff to much for updating sake's I would recommend using autoptomize
It will compress and conjoin all your scripts and css files into one nice neat and easy to download file so that no render blocking or partial loading occur's
Just reviewed your site on http://uniplaces.micrositesonline.info/blog/cities/, probably "jquery.isotope.js" file is missing on your directly. Make sure the presence of "jquery.isotope.js" at JS folder. lets try
Currently I'm using AJAX to pull in data from our webservice. The issue I'm having is that it doesn't want to load the data into the masonry layout, everything in .social_block floats left one under the next (and I haven't set any float for these). So masonry isn't working :(
I wanted the following to happen: Load initial items from webservice in the masonry layout and on "infinite" scroll it would make the paged request from the webservice to append new items into the masonry layout.
So the questions are as follows:
- Why aren't my webservice items loading using masonry and just loading to the left of page?
- How can I use infinite scroll with my existing AJAX request so it pulls in new data into the masonry layout using the paging code I have in place as (first request load http://example.com/ automatically, second request load http://example.com/1 on first infinite scroll, third request http://example.com/2 on second infinite scroll, etc.)?
As an added note, if I add in an alert rather than console.log before line $container.imagesLoaded(function(){ it seems to slow things down but then loads the initial request into masonry format - weird!
<div id="container">
</div>
<p id="loadmore">
<button id="more">'Load More!</button>
</p>
<script src="js/vendors/jquery/jquery-1.10.0.min.js"></script>
<script src="js/vendors/masonry/jquery.masonry.min.js"></script>
<script src="js/vendors/jquery/jquery.infinitescroll.min.js"></script>
<script>
$(function(){
var $container = $('#container');
//alert('Masonry loads items in the nice layout if I do this');
$container.imagesLoaded(function(){
$container.masonry({
itemSelector: '.block',
columnWidth: 100
});
});
$container.infinitescroll({
navSelector : '#loadmore', // selector for the paged navigation
nextSelector : '#more', // selector for the NEXT link (to receive next results)
itemSelector : '.block', // selector for all items to retrieve
loading: {
finishedMsg: 'No more pages to load.',
img: 'http://i.imgur.com/6RMhx.gif'
}
},
// trigger Masonry as a callback
function( newElements ) {
// hide new items while they are loading
var $newElems = $( newElements ).css({ opacity: 0 });
// ensure that images load before adding to masonry layout
$newElems.imagesLoaded(function(){
// show elems now they're ready
$newElems.animate({ opacity: 1 });
$container.masonry( 'appended', $newElems, true );
});
}
);
// set here so it is in reach
var page = 0;
// this will call the required url with new json data.
function loadPage(page) {
var url = 'http://example.com/' + page;
$.getJSON(url, function(data) {
var cont = $('#container');
$.each(data.data, function(index, obj) {
var item = obj.Message;
cont.append(
$('<li>', {"class": "block"}).append(
$('<span>', {"class": item.Type}).append(
$('<span>', {"class":"post_image"}).append(
$('<img>', {src:item.postImageLarge})
)
)
)
)
)
});
//$.each(data.data, function(key, val) { console.log('Data key: ', key, ', Value: ', val)});
});
}
// load more handler
$('#more').click(function(){
page = page + 1;
loadPage(page); //load more items
});
// initial run with page empty
loadPage('');
});
</script>