sortable and new created content [duplicate] - javascript

So I use jQuery UI sortable plugin to sort photos in a small gallery.
$(function() {
$("#area").sortable({
items: '.sort-wrapper',
cursor: "move",
handle: ".photo-handler",
opacity: 0.5,
scroll: true,
scrollSensitivity: 100,
scrollSpeed: 5,
revert: 100,
tolerance: "pointer",
update : function () {
var order = $('#area').sortable('serialize');
$.ajax({
type : 'POST',
url : '/file.php',
data : order
});
}
}).disableSelection();
On the same page I dynamically add and remove photos. PHP script returns HTML code with div's with image links and buttons "remove" and "move" (sortable handler).
Example:
<div class="sort-wrapper">
<img src="photo001m.jpg" alt="">
<button type="button" class="remove-this-photo">Remove</button>
<button type="button" class="photo-handler">Move</button>
</div>
The problem is sortable stops working when I add new files or remove a file(s) from #area. I've been looking for solution, have found sortable('refresh') method, but it's not working for me.
The script which adds new photos in the #area is quite standard. I use $.ajax({}) and .done, .fail, .always methods.
I managed to use sortable('destroy') method when starting uploading new files and do something like this after uploading is finished:
.always(function() {
$("#area").sortable();
});
The code above makes the #area sortable again, but I must copy all the settings again to configure it my way.
How to bind sortable to make it work after dynamic content is loaded or how to store all the settings outside sortable() and be able to use it again on the same page?

If you add new content to the sortable element you'll need to refresh the initialised instance. To do that, call the refresh option, like this:
.always(function() {
$("#area").sortable('refresh');
});

Related

Make all JavaScript work as normal on ajax content

I am working on a normal bootstrap theme which contains js slider, popup, text-rotation, masonry boxes etc..
The theme contains all relevant js library and main.js
All of these will load new content via ajax on user specified actions.
Here is the js/ajax for text-rotation:
In the example below i have to call the "$('.text-rotation').owlCarousel" in order to make the text-rotation to work properly.
function getCon(type,id)
{
var postData = { id: id, type: type}
$.ajax({
url : 'getcontent.php',
type : 'post',
data : postData,
success : function( resp ) {
var cont = $('#cont', resp).html();
$('#conta').after(cont);
$('.text-rotation').owlCarousel({
loop: true,
dots: false,
nav: false,
margin: 10,
items: 1,
autoplay: true,
autoplayHoverPause: false,
autoplayTimeout: 3800,
animateOut: 'zoomOut',
animateIn: 'zoomIn'
});
}
});
}
When not calling "$('.text-rotation').owlCarousel" it simply displays the text in list format.
In order to make the all the ajax load content work properly on all section i.e the slider, popup, etc.. i'll have to find the relevant theme functions and code them all on the respective ajax functions.
Is there any predefined js code which i may call on ajaxComplete so tha all ajax content works normal as it works on page load ??
I tried to call the main.js from "getScript" function inside the ajax success but not working..
The short answer is: no.
jQuery code acts on the DOM that exists when the code is run; if you add to the DOM later on there isn't any general-purpose way for jQuery code to go back and act on the new elements as though they had been there in the first place.
Your options are
rewrite your code to not depend on event bindings / manipulation of the AJAX-based content -- instead use delegated event bindings on elements that are always present
defer your main code init until after all AJAX calls have completed, so the DOM is already in place when you add your bindings
Write specific code to add necessary event bindings / modify newly added DOM chunks individually, as they're loaded

Why the Ajax content of this jQuery plugin (Tooltipster) is shown only after mouse hover 2 times?

I can't find a solution for this plugin since I cannot find any working demo or documentation for external content via Ajax.
Basically I have a simple div with a mouse hover JS function:
<div onmouseover="myFunct(this,'.$comment['id'].');" >Hover Me</div>
And this is my JS function:
function myFunct(element, id){
$(element).tooltipster({
contentCloning: true,
interactive:true,
maxWidth:250,
contentAsHTML:true,
content: 'Loading...',
// 'instance' is basically the tooltip. More details in the "Object-oriented Tooltipster" section.
functionBefore: function(instance, helper) {
var $origin = $(helper.origin);
// we set a variable so the data is only loaded once via Ajax, not every time the tooltip opens
if ($origin.data('loaded') !== true) {
$.ajax({
type: "POST",
url: baseUrl+"/requests/load_profilecard.php",
data: 'id='+id+"&token_id="+token_id,
cache: false,
success: function(html) {
// call the 'content' method to update the content of our tooltip with the returned data
instance.content(html);
// to remember that the data has been loaded
$origin.html('loaded', true);
}
});
}
}
});
}
Why the tooltip is shown only at the 2nd mouse hover?
Here is a similar Eg. JSFiddle
UPDATE
Thanks to the support this has solved my issue:
<div class="tooltip" data-id="'.$comment['id'].'">Hover me!</div>
<script type="text/javascript">
$(document).ready(function() {
$('.tooltip').tooltipster({
content: 'Loading...',
functionBefore: function(instance, helper){
var $origin = $(helper.origin);
$.ajax({
type: "POST",
url: baseUrl+"/requests/load_profilecard.php",
data: 'id='+ $origin.attr('data-id')+"&token_id="+token_id,
cache: false,
success: function(html) {
// call the 'content' method to update the content of our tooltip with the returned data
instance.content(html);
}
});
},
interactive:true,
contentAsHTML:true,
maxWidth:250
});
});
</script>
Anyway this doesn't work on Ajax dynamic content, and I don't know why (I tried to insert it on Ajax page, no way)
I'd recommend a few things: first, separate your JS from your HTML (this is considered best practice), second, initialize Tooltipster on page load, and last, remove the wrapper function. Once the tooltip is initialized your code will trigger by default on hover.
Separate JS from HTML
<div class="hover-me tool-tip" data-commentId="12345">Hover Me</div>
Initalize Tooltipster on Document Ready
$(document).ready(function() {
$('.tooltip').tooltipster();
});
Trigger Tooltipster with Hover
$('.hover-me').tooltipster({
// all of your code from above
functionBefore: function(){
var commentId = $(this).attr('data-commentId');
}
});
Note:
The default trigger for Tooltipster is hover (as seen in the documentation), however, you could explicitly set it by passing in trigger: hover, which would make your code slightly more readable and as such maintainable.
Tooltipster Support Recommendation (as seen in the comments)
I add this because it reinforces my solution above and adds context for future devs...that, and it might be overlooked in the comments section.
You initialize your tooltip when the mouseover event has already been fired, so Tooltipster cannot "hear" this first event and open the tooltip. You'd better initialize your tooltips at page load and put your comment id in a data-id attribute that you'll retrieve in functionBefore when you prepare your ajax call.

Masonry: Creating a grid on AJAX callback

So I'm pretty familiar with Masonry I'd say, but I haven't had to do this before.
I'm aware of the "appended" method to add items to the grid after page load through ajax, but that's not exactly what I'm trying to do.
My grid structure doesn't exist at all until it's called via ajax.
For example (pseudocode):
Page Loads
User Clicks a Link
AJAX call, HTML string is returned and added to the dom via jQuery.
Need to instantiate the masonry grid based on this HTML.
Basically the HTML that is returned via AJAX looks something like this:
<div class="grid-57">
<a class="item" href="http://www.example.com">
<img src="http://fpoimg.com/350x350"/></a>
</a>
<a class="item" href="http://www.example.com">
<img src="http://fpoimg.com/350x250"/></a>
</a>
<a class="item" href="http://www.example.com">
<img src="http://fpoimg.com/350x450"/></a>
</a>
</div>
So as you can see I'm not adding to an existing grid or masonry, I need to create a new one on successful return of the AJAX.
My JS looks something like this:
$('.get-grid').click(function(e){
var id = $(this).data('id');
$.post(ajaxurl, { action: 'get_grid', id: id }, function(response) {
// Append this html to the area of the site where I have the grids.
$('.all-the-grids').append(response);
// Here is where i need to actually turn this HTML that I just added into a masonry object and lay it out.
var $container = $('.grid-' + id);
msnry = new Masonry( $container[0], {
columnWidth: 188,
itemSelector: '.item',
gutter: 10
});
msnry.on('layoutComplete', function(){
// never making it in here.
});
});
});
Any idea how to do this?
EDIT
It appears my grid is getting laid out correctly, no errors, but it's never reaching the layoutComplete callback here.
Do it the same way as you would usually with Masonry, the fact that you're doing it in a callback doesn't really change anything.
$('.get-grid').click(function(e){
var id = $(this).data('id');
$.post(ajaxurl, { action: 'get_grid', id: id }, function(response) {
// Append this html to the area of the site where I have the grids.
var grids = $('.all-the-grids');
grids.append(response);
var msnry = new Masonry(grids[0], {
});
});
});
When you are using Images in Layout, first thing you have to do is wait till all images loaded in that element and then instantiate. Try below code
$containers = $('.all-the-grids');
$containers.append(response).imagesLoaded(function() {
$containers.masonry({
itemSelector: '. a'
});
});
Note: imagesLoaded is a jQuery plugin

Re-apply JQuery in Meteor template

I have a template with a slick carousel, depending on some JQuery. I add this code to the template as follows:
Template.show_house.rendered = function () {
$('#carousel').slick({
dots: true,
arrows: true
});
};
This template depends on a helper:
Template.show_house.helpers({
house : function() {
return Houses.findOne({_id : Session.get("selectedHouse")});
},
...
When the session changes (user clicking on another item), the data in the template changes, but the JQuery isn't applied again, and the images are just shown as a list rather than a carousel.
I've been playing around with UI.render, but to no avail. What can I do?
I had the same problem, the things for is that i wasnt applying the event Template.foo.rendered to the specific template. Try to apply the jquery event on "rendered" to the proper template and see if it works!

Multiple instances of jQuery plugin (Magnific popup)

I've hit a bit of a wall with this one. My jQuery knowledge outside of just implementation is pretty poor.
I'm building the Magnific Popup (http://dimsemenov.com/plugins/magnific-popup/) jQuery plugin into my WordPress theme as a popup gallery. I've got it all wired up and working. It grabs images dynamically from the backend using custom fields. I can also get multiple instances working on the same page. HOWEVER, when scrolling through images in one popup gallery, it wont end at the end of the first gallery but rather, it will move on into the images in the second gallery. See example: http://www.oftenvisual.com/reset/galleries/.
Unfortunately I can't post the code here as it's too long, but hopefully the demo page helps. Because the galleries are generated dynamically and the client using the backend wont have the knowledge to add container with different classes, I need some way to also dynamically separate out the galleries. Any idea GREATLY appreciated!
Script calling the plugin
// Magnific
$(document).ready(function() {
$('.popup-gallery').magnificPopup({
delegate: 'a',
type: 'image',
tLoading: 'Loading image #%curr%...',
mainClass: 'mfp-img-mobile',
gallery: {
enabled: true,
navigateByImgClick: true,
preload: [0,1] // Will preload 0 - before current, and 1 after the current image
},
image: {
tError: 'The image #%curr% could not be loaded.',
titleSrc: function(item) {
return item.el.attr('title');
}
}
});
});
try to set different id_s on your .popup-gallery div's and then do
$('#popup-gallery1').magnificPopup....
$('#popup-gallery2').magnificPopup....
You may use jQuery contains selector to point "a" tag with specific class name - a[class*='popup-gallery-']. If you have different IDs for you pop-ups it just work as a charm. It just search for all "a" where class contains "popup-gallery-".
And if it matches, it fires up the Magnific Pop Up etc.
jQuery:
$(document).ready(function(){
$("a[class*='popup-gallery-']").magnificPopup({
//your settings goes here
});
});
HTML:
# first div
<a class="popup-gallery-1" href="#popup-1">First popup</a>
<div id="popup-1"> Your content here </div>
# second div
<a class="popup-gallery-2" href="#popup-2">Second popup</a>
<div id="popup-2"> Your content here </div>
You can simply use jquery's each with the same class, for example:
$('.popup-gallery').each(function() {
$(this).magnificPopup({
delegate: 'a', // child items selector, by clicking on it popup will open
type: 'image', // override with class 'mfp-iframe' on delegate or any other supported type
gallery: {enabled:true },
});
});
And now if you have multiple .popup-gallery divs, they all work separately.

Categories

Resources