Using jQuery plugins in Meteor - javascript

I have been trying to add a jQuery plugin to Meteor but Meteor refuses to let the plugin work client side.
The example is I have this plugin that allows me to shuffle a bunch of divs around called jQuery Shuffle but when I call the following script in the head or from an external file it does not execute. It could be the plugin not publishing functions but it is client side so that makes no sense. I have verified that javascript and jQuery is working through a few console.log() command tests and those seem to work in external files or in the head wether they are inclosed in a jQuery function or not. Here is the code I am trying to use with jQuery Shuffle:
(do take note that this script also is using a few other plugins that appear not to be working either)
$(document).ready(function () {
var hash = window.location.hash.substr(1);
// Puts hash into search field
if (hash !== "") {
$("#search").val(hash);
$("#search").focus();
$('#search').keyup();
}
/* initialize shuffle plugin */
var $grid = $('#grid');
var $gridn = $('#gridn');
$grid.shuffle({
itemSelector: '.item',
group: 'alll'
});
$gridn.shuffle({
itemSelector: '.item',
group: 'news'
});
/* detects a news post */
if (hash.indexOf("news") > -1) {
$('#alll').removeClass('active');
$('#news').addClass('active');
$('#n-news').addClass('active');
$grid.shuffle('shuffle', 'news');
}
/* reshuffle when user clicks a filter item */
$('#filter a').click(function (e) {
e.preventDefault();
window.scrollTo(0, 0);
// set active class
$('#filter a').removeClass('active');
$(this).addClass('active');
// get group name from clicked item
var groupName = $(this).attr('data-group');
// reshuffle grid
$grid.shuffle('shuffle', groupName);
$gridn.shuffle('shuffle', groupName);
var n_catagories = ["n-v", "n-am", "n-av", "n-gd", "n-d", "comic", "blog"];
n_catagories.forEach(function (n_selectedcat) {
if ($("#" + n_selectedcat).hasClass("active")) {
$('#news').addClass('active');
//console.log(n_selectedcat)
}
});
});
// Sorting options
$('.select-options').on('change', function () {
var sort = this.value,
opts = {};
// We're given the element wrapped in jQuery
if (sort === 'date-created') {
opts = {
reverse: true,
by: function ($el) {
return $el.data('date-created');
}
};
} else if (sort === 'title') {
opts = {
by: function ($el) {
return $el.data('title').toLowerCase();
}
};
}
// Filter elements
$grid.shuffle('sort', opts);
});
// Advanced filtering
$('.search').on('keyup change', function () {
var val = this.value.toLowerCase();
window.scrollTo(0, 0);
$grid.shuffle('shuffle', function ($el, shuffle) {
// Only search elements in the current group
if (shuffle.group !== 'all' && $.inArray(shuffle.group, $el.data('groups')) === -1) {
return false;
}
var text = $.trim($el.find('.item-tags').text()).toLowerCase() + $.trim($el.find('.hidden').text()).toLowerCase();
return text.indexOf(val) !== -1;
});
$gridn.shuffle('shuffle', function ($el, shuffle) {
// Only search elements in the current group
if (shuffle.group !== 'all' && $.inArray(shuffle.group, $el.data('groups')) === -1) {
return false;
}
var text = $.trim($el.find('.item-tags').text()).toLowerCase() + $.trim($el.find('.hidden').text()).toLowerCase();
return text.indexOf(val) !== -1;
});
});
//REMOVE AND HIDE HANDELER
var $nnitems = $('.nnotice');
$(".nnotice-button").click(function () {
Cookies.set('hidennotice', 'true', {
expires: 31557600
});
});
if (Cookies.get('hidennotice') == 'true') {
$grid.shuffle('remove', $nnitems);
}
$(".nnotice").click(function () {
$grid.shuffle('remove', $nnitems);
});
//Auto Shuffle
$(".social-toggle").click(function () {
$(".social-stuffs").slideToggle("slow");
setTimeout(function () {
var catagories = ["alll", "v", "am", "av", "gd", "d", "news", "n-v", "n-am", "n-av", "n-gd", "n-d", "comic", "blog"];
catagories.forEach(function (selectedcat) {
if ($("#" + selectedcat).hasClass("active")) {
$grid.shuffle('shuffle', selectedcat);
}
});
}, 1000);
});
});
When not enclosed in Meteor, this script works as expected.
I have tried loading the JS files for the plugins by calling them normally through <script type="text/javascript" src="directory/somescript.js"></script> and by loading the scripts through the /client directory meteor uses to process files that are going to the client. It automatically loads these files in a <script> when put here. Even with Meteor loading them it seems not to work. I don't know if it is because the functions inside the plugins need to be published or if it is just no possible to use these kinds of plugins/apis with Meteor.
This is a working, unfinished version of the site without Meteor (and that has missing files and an unfinished color scheme)
Edit:
Basically I just need to be able to load a jQuery plugin somehow and then load the script to control it. That is what I am having trouble doing.

Using plugins like query could be a little tricky on meteor, example you are using
$(document).ready(function () {});
And its ok but i prefer to work with
Meteor.startup(function () {
});
Reference here Stack Question about onReady and Startup
Also some people prefer to use the Template.myTemplate.rendered ) function(){}
and its works (on my case works), and also try to use some Timeouts
You are not getting anything errors on the console, because nothings wrong happens all DOM elements were created, i face this problems many times using Carrousels, dynamic list from codrops etc.
If you have your web/project on some github repo or working in some cloud host Service like nitrous.io i could help you

Safest way is to deliver the plugin as a package and initialise it in template.rendered

I had this problem with a jquery plugin.
My html code was:
<head>
<meta charset="utf-8">
<!-- Plugin JQuery -->
<script src="js/jquery.easing.min.js"></script>
</head>
<body>
{{main}}
</body>
Then I put the script after {{main}} template and it works. The script is loaded after all javascript meteor packages:
<head>
<meta charset="utf-8">
</head>
<body>
{{main}}
<!-- Plugin JQuery -->
<script src="js/jquery.easing.min.js"></script>
</body>

Related

JQuery not updating CSS elements after PHP include

I am loading PHP files with JQuery/Ajax.
This is the index.php file where the webpages are called
<div class = "view-screen">
<?php include('home.php'); ?>
</div>
Depending on which nav link is clicked, that page will display without refreshing.
$(document).ready(function() {
// ...
$navLinks.click( function() {
var $this = $(this)
target = $this.data('target')
toggleMenu()
$viewScreen.load(target + ".php")
$this.data('clicked', true)
if ($this.data('clicked') && target === "about") {
activateAbout()
}
return false
})
function activateAbout() {
console.log('activated')
}
}
The console log works, and displays 'activated'. The pages do load.
All of my scripts compile and link correctly to each other.
However, when I include code that updates the target page CSS in the activateAbout() function, it doesn't work. For example:
$('body').css("background-color", "white")
in activateAbout() works, but calling/updating CSS elements in the chosen .php file doesn't, such as
$('.about p').css("color", "white")
// OR
$('.about').toggleClass('activate')
I have a feeling this has something to do with the order in which these files are loaded, but I'm not sure! Thanks for the help in advance
This is common phenomenon. The reason you are not able to apply the css is because, your content is loading after, you call activateAbout(). I would recommend to call activateAbout() once the $viewScreen.load(target + ".php") loads the data successfully. jQuery.load() supports callback too. Refer to the example usage at https://www.w3schools.com/jquery/jquery_ajax_load.asp. So, it should look like
$(document).ready(function() {
$navLinks.click( function(){
var $this = $(this);
target = $this.data('target');
toggleMenu();
$viewScreen.load(target + ".php", function() {
$this.data('clicked', true);
if ($this.data('clicked') && target === "about") {
activateAbout();
}
});
return false;
});
});
function activateAbout() {
console.log('activated')
}
Also there is a trick using setTimeout which you can execute after certain time, when the view is expected to be loaded like below
if ($this.data('clicked') && target === "about") {
//The timeout period you can change accordingly
setTimeout(activateAbout, 300);
}
The recommended way is first type solution. Hope this helps you!!

Triggering fluffy.js

I'm trying to make a simple tumblr theme using the fluffy plugin (https://github.com/mzdr/fluffy.js) but I've ran into a problem. The plugin only executes once on page load. I'm trying to get it to work with the infinite scroll plugin (http://www.infinite-scroll.com/) and I need the fluffy plugin to trigger whenever new content loads.
I'm fairly new when it comes to JS so I appreciate any help I can get. Thanks.
Edit added code:
<script src="https://code.jquery.com/jquery-2.2.2.min.js"></script>
<script src="https://npmcdn.com/imagesloaded#4.1/imagesloaded.pkgd.min.js"></script>
<script src="http://static.tumblr.com/hpghjri/co2nfnr1j/infinitescroll.min.js"></script>
<script src="http://static.tumblr.com/nxwjyyg/XWUob8gtq/fluffy.min.js"></script>
<script>
$(function(){
app.initInfinite();
app.onImagesLoad();
}); //end document ready
var app = {
'initInfinite' : function() {
var $container = $('.page-index .posts');
$container.infinitescroll({
navSelector:".pagination",
nextSelector:".pagination-next",
itemSelector:".posts__container",
appendCallback:true,
loading:{
finishedMsg:" ",
img:"data:image/gif;base64,R0lGODlhAQABAHAAACH5BAUAAAAALAAAAAABAAEAAAICRAEAOw==",
msg:null,
msgText:" ",
selector:null,
finished:function() {
}
}
},
function(newElements) {
var $newElems = $(newElements).css({opacity:0});
var $newElemsIDs = $newElems.map(function() {
return this.id;
Tumblr.LikeButton.get_status_by_post_ids($newElemsIDs);
}).get();
$newElems.imagesLoaded(function() {
$newElems.animate({opacity: 1});
//what to do when new elems appended
// I need to trigger fluffy here
});
var $newElemsIDs = $newElems.map(function() {
return this.id;
}).get();
Tumblr.LikeButton.get_status_by_post_ids($newElemsIDs);
});
},
'onImagesLoad' : function() {
$('.content .posts').imagesLoaded()
.always( function( instance ) {
console.log('all images loaded');
$('.overlay').addClass('hide');
$('.overlay__preloader').attr('class', '');
})
.done( function( instance ) {
console.log('all images successfully loaded');
});
}
}
</script>
This is your lucky day! I just released v2.1.0 which fixes your problem. Now you can create Fluffy objects on the fly like that:
// Start automatic detection
Fluffy.detect();
// Or provide a DOM node for single creation
var myElement = document.querySelector('#what-ever-you-like');
Fluffy.create(myElement);
// Or use a selector to create one
Fluffy.create('[data-fluffy-container]');
Don't forget to check out the updated docs.

$(document).ready(function() with Meteor JS templates

I have a template I've deeply integrated with Meteor. It uses a scripts.js file that runs a bunch of commands after $(document).ready and $(window).load.
I put scripts.js inside of client/compatibility, and it works only if I do a hard refresh of the template. Otherwise, the template doesn't render and the functions don't execute.
Specifically, this code:
// Append .background-image-holder <img>'s as CSS backgrounds
$('.background-image-holder').each(function() {
var imgSrc = $(this).children('img').attr('src');
$(this).css('background', 'url("' + imgSrc + '")');
$(this).children('img').hide();
$(this).css('background-position', 'initial');
});
Much appreciated if you know how I should take it from here.
If you want a function to fire off when the DOM is loaded and all images, use this: (be forewarned, this is in ES6)
let imgCount;
let imgTally = 0;
Template.myTemplate.onRendered(function () {
this.autorun(() => {
if (this.subscriptionsReady()) {
Tracker.afterFlush(() => {
imgCount = this.$('img').length;
});
}
});
});
Template.myTemplate.events({
'load img': function (event, template) {
if (++imgTally >= imgCount) {
(template.view.template.imagesLoaded.bind(template))();
}
}
});
Then you just need to declare imagesLoaded which will get fired off when all images are done.
Template.myTemplate.imagesLoaded = function () {
// do something
};
Place this stuff in the onRendered function of the template.
Template.<name>.onRendered(function(){
//do your jquery business here!
});
For more info check the docs

excluding a page from javascript

I have a swipe to do back script for my ios web app that I have running across every page but what I want to know how is to exclude from affecting the first page that shows up. The script is this
<script>
$(document).bind('swiperight', function () {
history.back();
});</script>
How would exclude a page that has a hypothetical id of "home"?
I'm assuming you're using jQuery mobile (Apologies if you're not), you could use $.mobile.activePage to check if you're at home:
http://jquerymobile.com/demos/1.2.0/docs/api/methods.html (At the bottom)
<script>
$(document).bind('swiperight', function () {
if ( $.mobile.activePage !== 'home' )
history.back();
});
</script>
The general principle would be this:
<script>
var id = // get your hypothetical id from somewhere;
if(id !== "home") {
$(document).bind('swiperight', function () {
history.back();
});
}
</script>
Without any more information on where the hypothetical id is coming from it's difficult to be more specific than that.
$(document).bind('swiperight', function () {
if (!$('body#home').length === 0) {
history.back();
// ... anything else
}
});
You could also use: if (!$('#page.home').length === 0) if it's going to be a class on a containing element, if ($('#page').hasClass('home')) is a bit more of solid jQuery-y way of doing it too.

ASP.NET WebForms Checking all Checkboxes in a GridView using jQuery v1.9.0 doesn't work

I've a problem with my application regarding jQuery. I tried a code example ( https://web.archive.org/web/20210513220745/http://aspnet.4guysfromrolla.com/articles/120810-1.aspx ) to use a Header CheckBox to check/uncheck all rows inside a GridView. The sample code works with jQuery v1.4.4 but doesn't work with the latest jQuery release v1.9.0.
Here's the code.
<script type="text/javascript">
var allCheckBoxSelector = '#<%=gvFileList.ClientID%> input[id*="chkAll"]:checkbox';
var checkBoxSelector = '#<%=gvFileList.ClientID%> input[id*="chkSelected"]:checkbox';
function ToggleCheckUncheckAllOptionAsNeeded() {
var totalCheckboxes = $(checkBoxSelector),
checkedCheckboxes = totalCheckboxes.filter(":checked"),
noCheckboxesAreChecked = (checkedCheckboxes.length === 0),
allCheckboxesAreChecked = (totalCheckboxes.length === checkedCheckboxes.length);
$(allCheckBoxSelector).attr('checked', allCheckboxesAreChecked);
}
$(document).ready(function () {
$(allCheckBoxSelector).live('click', function () {
$(checkBoxSelector).attr('checked', $(this).is(':checked'));
ToggleCheckUncheckAllOptionAsNeeded();
});
$(checkBoxSelector).live('click', ToggleCheckUncheckAllOptionAsNeeded);
ToggleCheckUncheckAllOptionAsNeeded();
});
</script>
With jQuery v1.4.4 everything works perfect. Using jQuery v1.9.0 every page load I get a "Object doesn't support this property or method: .live" error. If I use the syntax:
$(allCheckBoxSelector).click(function () {...
instead of the one above, I avoid the error but the Header Checkbox works only once. If I click it again nothing appens.
I also tried the .on syntax:
$(allCheckBoxSelector).on('click', function () {...
but it doesn't work too.
I'd like to know if that issue is due to a change or a bug in jQuery v1.9.0.
jQuery live should now be replaced by on. If the code worked before it should just work after you change live by on.
I got to the bottom of the problem: had to use .prop instead of .attr. I made some small modifications in the code too.
Here's a working demo on JS Bin: http://jsbin.com/egopar/4/edit
Here's the working code for jQuery 1.9:
$(document).ready(function () {
var allCheckBoxSelector = $('#chkAll');
var checkBoxSelector = $('input:checkbox:not(#chkAll)');
function ToggleCheckUncheckAllOptionAsNeeded() {
var totalCheckboxes = $(checkBoxSelector),
checkedCheckboxes = totalCheckboxes.filter(":checked"),
noCheckboxesAreChecked = (checkedCheckboxes.length === 0),
allCheckboxesAreChecked = (totalCheckboxes.length === checkedCheckboxes.length);
//console.log(allCheckboxesAreChecked);
$(allCheckBoxSelector).prop('checked', allCheckboxesAreChecked);
}
$(allCheckBoxSelector).on('click', function () {
$(checkBoxSelector).prop('checked', $(this).is(':checked'));
ToggleCheckUncheckAllOptionAsNeeded();
});
$(checkBoxSelector).on('click', function () {
ToggleCheckUncheckAllOptionAsNeeded();
});
});
If you are not using jQuery anywhere else in your page, you can use a very simple javascript to do this. There are many ways to do this, but this works for me and can be attached to buttons, links, etc. checkid is the client id and select being true or false.
function checktoggle(checkid,select){
var check=document.getElementById(checkid);
var numinput=check.getElementsByTagName('input');
for (i=0; i<numinput.length; i++){
numinput[i].checked=select;
}
}
Solved!
Thanks to Leniel Macaferi suggestions I used .on and .prop methods instead of .live and .attr but I make a different implementation of the script that finally works with jQuery v1.9.0 on my application.
<script type="text/javascript">
var allCheckBoxSelector = '#<%=gvFileList.ClientID%> input[id*="chkAll"]:checkbox';
var checkBoxSelector = '#<%=gvFileList.ClientID%> input[id*="chkSelected"]:checkbox';
function ToggleCheckUncheckAllOptionAsNeeded()
{
var totalCheckboxes = $(checkBoxSelector),
checkedCheckboxes = totalCheckboxes.filter(":checked"),
noCheckboxesAreChecked = (checkedCheckboxes.length === 0),
allCheckboxesAreChecked = (totalCheckboxes.length === checkedCheckboxes.length);
$(allCheckBoxSelector).prop('checked', allCheckboxesAreChecked);
}
$(document).ready(function()
{
$(allCheckBoxSelector).on('click', function()
{
$(checkBoxSelector).prop('checked', $(this).is(':checked'));
ToggleCheckUncheckAllOptionAsNeeded();
});
$(checkBoxSelector).on('click', ToggleCheckUncheckAllOptionAsNeeded);
ToggleCheckUncheckAllOptionAsNeeded();
});
</script>

Categories