Re-apply JQuery in Meteor template - javascript

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!

Related

jquery owl-carousel owl-dots class issue

I get some problem when I use owl-carousel in my Rails project.
when I go back to the cached page of my browsers which is using carousel class, I get too many carousel owl-dot classes in my page,this is my
JS code
function initScrollboxHobby() {
var owl = $(".owl-carousel");
owl.owlCarousel({
// loop: true,
items: 1,
nav: true
});
}
and issue HTML code
How to fix it ?
I guess you are using turboinks and when you go back the page is cached by it and when it loads it reruns the owl carousel init function.
The problem, básically, is that turbolinks doesn't play well with non-idempotent functions https://github.com/turbolinks/turbolinks#making-transformations-idempotent
I've managed to make a workaround for this problem with other js plugins, so it should work for you.
Básically, the idea is:
First, when the user enters the page for the first time, copy the content of the element with class .owl-carousel on itself as a data attribute
carousel = $('.owl-carousel');
carousel.data('originalHtml', carousel.html();
carousel.owlCarousel(....)
Then, when the users goes back, before initializing the carousel, check if it was initialized and cached, in that case, first replace the content with the original and remove classes
carousel = $('.owl-carousel');
if (carousel.hasClass('owl-loaded')) {
carousel.html(carousel.data('originalHTML')).removeClass('owl-theme owl-loaded owl-drag');
}
carousel.owlCarousel(....)
You can mix both steps into one:
$(function() {
const carousel = $('.owl-carousel');
if (carousel.hasClass('owl-loaded')) { //if it has the class then it means it's the cached view
carousel.html(carousel.data('originalHTML')).removeClass('owl-theme owl-loaded owl-drag');
} else { // else it's a fresh load of the page
carousel.data('originalHtml', carousel.html());
}
carousel.owlCarousel(....)
})
It's a little bit hacky, but the only way I found to use plugins that are not prepared to work with turbolinks without going through modifying those plugins.
Another option would be to just disable Turbolinks if you thing you just don't need it.
For arieljuod's help of problem reason and my own trying.
I coded like this now.
var owl = $(".owl-carousel");
var owl_navs = $('.owl-carousel .owl-nav');
var owl_dots = $('.owl-carousel .owl-dots');
var owl_cloned = $('.owl-carousel .owl-stage-outer .owl-stage .cloned');
if(owl.hasClass('owl-loaded'))
{
owl_navs.remove();
owl_dots.remove();
owl_cloned.remove();
}
owl.owlCarousel({
loop: true,
items: 1,
nav: true
});
It's tedious but worked well.
Now,I understanded reason.
When I go back to cached page,because I wrote javascript code in my ERB file,in that way, old HTML code may changed.
And then Turbolinks function will run the JS code in that CHANGED new HTML code,Turbolinks must do that,because when I visit cached page again,it will lose all the event binds.
So the whole carousel items will be messy.

Can't find element using UI hash in Marionette Layout

I'm not sure why I can't get the button element using my UI hash. This is what my Layout looks like:
Layout: App.Base.Objects.BaseLayout.extend({
// Rest of the code left out for brevity
ui: {
btnSave: "#btnSave"
},
events: {
"click #ui.btnSave": "onSave"
},
onInitialize: function () {
this.listenTo(App.vent, "DisableSaveButton", function(val) {
this.disableSaveButton(val);
},this);
},
disableSaveButton: function () {
this.ui.btnSave.prop("disabled",val).toggleClass("ui-state-disabled",val);
},
onSave: function () {
alert("saved!");
}
})
In VS2013, when my breakpoint hits the line inside disableSaveButton method, I entered $("#btnSave") into the Watch window and I was able to get the element back. I could tell because it had a length of 1. From this, I know the button is rendered. However, if I enter this.ui.btnSave into the Watch window, I would get an element with length of 0.
My BaseLayout object is basically a custom object extended from Marionette.Layout
Marionette version: 1.8.8
Any ideas why I can't find the button element using this.ui.btnSave?
Thanks in advance!
Got some help from a coworker and the issue might be because the element is out of scope. Basically, inside the Layout object, 'this' does not contain the element. We were able replace 'this.ui.btnSave' with '$("#btnSave",this.buttonset.el)' and that works fine. buttonset is the region that actually contains the html element.
This seems like an inconsistency because even though the ui hash didn't work, the click event utilizing the ui hash did work.
UPDATE 6/3/2015:
Another coworker of mine provided a better solution. Basically, in my Layout I use a display function to display my view. It looks something like this:
Layout: App.Base.Objects.BaseLayout.extend({
// Rest of the code left out for brevity
display: function() {
$(this.buttonset.el).html(_.template($("#buttonset-view").html(), {"viewType": viewType}));
}
})
Basically, I'm saying to set the html of my region, which is this.buttonset.el, to my template's html. As of now, my layout doesn't know any of the elements inside the region. It just contains a region which displays the elements. So there is some sort of disconnect between my layout and the elements in my region.
The correct solution, as opposed to my earlier workaround, is to simply add the following line of code at the end:
this.bindUIElements();
From Marionette Annotated Source:
This method binds the elements specified in the “ui” hash inside the
view’s code with the associated jQuery selectors.
So this final code looks like this:
Layout: App.Base.Objects.BaseLayout.extend({
// Rest of the code left out for brevity
display: function() {
$(this.buttonset.el).html(_.template($("#buttonset-view").html(), {"viewType": viewType}));
this.bindUIElements();
}
})
With this, I was able to finally able to retrieve my element using this.ui.btnSave.

Popover content not working with angularjs ng-click

I have already read all the posts about this, but unfortunately none of them was helpful: jsfiddle and plunker links appear to be no longer working.
What I am trying to do is to simply put a button inside the bootstrap pop-over which makes a call to a function inside the scope of the directive I've created. The problem is that using jquery to grab the content it does not work since the scope appear to be outside. Also trying to create the content inside the function it won't work because it will be not compiled.
I created an example on jsfiddle, but somehow angularjs is not loaded in the right point and therefore it doesn't work either.
$("#pop-over-link").popover({
'placement': 'top',
'trigger': 'click',
'html': true,
'container': 'body',
'content': function() {
return $("#pop-over-content").html();
}
});
This is the piece of code that opens the pop over, grabs the contents and shows it.
Here the jsfiddle: http://jsfiddle.net/75zLT/2/
And here is the working example on my dropbox: https://dl.dropboxusercontent.com/u/19470623/hatethis/test.html
There were 2 issues your were not including ngRoute in your fiddle and your need to compile the content returned in the popover.
'content': function() {
return $compile($("#pop-over-content").html())(scope);
}
Also you do not need the timeout.
Example: Plunker

jQuery - bxSlider plugin reloadSlider issues

I'm using jQuery with the bxSlider plugin, here is the link to it just incase: http://bxslider.com/
I'm trying to reload the slider and my custom pager after I've removed certain slides from it.
Here is what I have tried:
$(function() {
var slider = $('#slider').bxSlider({
pagerCustom: '#bx-pager'
});
$('.list').on('click', '.delete', function() {
image = $(this).closest('li').find('[type="hidden"]');
// image.attr('id') contains a string: image-0, image-1, image-2, etc.
$('#slider, #bx-pager').find('.' + image.attr('id')).remove();
slider.reloadSlider({
pagerCustom: '#bx-pager'
}); // I have also tried: slider.reloadSlider();
});
});
It works partially. What happens is the slider gets reloaded just fine but it removes the pager completely when it runs the reload.
Thank you very much for any help.
As long as I see, this is a bug in bxSlider, in fact, when you call the reloadSlider method, internally are called the methods destroySlider and init.
In the destroySlider method the pagerEl element is destroyed, this is right if you are not using a custom one, because it is recreated programmatically in the init method, but if you are using a custom one it can't be recreated programmatically.
I ended up modifying the destroySlider method to check if a custom pager is used, in this case it must not be deleted.
Here is the before (line 1294):
if(slider.pagerEl) slider.pagerEl.remove();
And after:
if (slider.settings.pagerCustom === '') {
if(slider.pagerEl) slider.pagerEl.remove();
}
I'll post the bug on GitHub as soon as I have the time.

jQuery mobile 1.1.0 slider: JS-object properties access?

EDIT: This could be seen as a pure javascript objects question. The code can be found here:
jquery.mobile-1.1.0.js
I need to access properties of a jQuery mobile JS-object but is not sure how that is possible. In the jquery.mobile-1.1.0.js and mobile.slider is the following (see extend on line 5967):
$.widget( "mobile.slider", $.mobile.widget, {
...
_create: function() {
...
$.extend( this, {
slider: slider,
handle: handle,
valuebg: valuebg,
dragging: false,
beforeStart: null,
userModified: false,
mouseMoved: false
});
Primarily the property I would like to read is the "dragging".
I know i can execute the methods using:
$("#slider").slider("refresh")
Is there a similair way to access the properties?
Thanks
How to react to user dragging the slider, without having to bind mouse-/tap-events, but instead using the JQM functionallity already in place.
To access the "dragging" variable of the JQM slider object I made an extension to the object as follows:
$(document).bind("mobileinit", function(){
$.mobile.slider.prototype.getDragging = function(){
return this.dragging;
};
});
With that in place, I can choose to react to changes only done by the user:
$("#slider").live('change',function(){
if($("#slider").slider("getDragging"))){
console.log('User is dragging slider to new value');
}
else {
console.log('Program changed value. (or user typed in visible textbox)') ;
}
});
With the slider textbox hidden, this give me the benefit of:
Using the "change"-event to react to user dragging without being triggered when my program change the slider value.
When my program is going to change the slider value, it can first check that the user is NOT currently dragging the slider.

Categories

Resources