Add class to current page using iScroll - javascript

As the title suggests, I'm trying to add a class to the current 'snapped-to' element. With this:
var verticalScroll;
verticalScroll = new IScroll('#wrapper', {
snap: true
});
verticalScroll.on('scrollEnd', function(){
alert(this.currentPage);
});
I get this alert when the scrolling is done:
[object Object]
So I was thinking I could use something like this to add a class:
verticalScroll.on('scrollEnd', function(){
var newPage = this.currentPage;
$(newPage).addClass('current');
});
But no joy. Done lots of searches to try and find the same situation. It must be something fairly simple.

Yeah, it's a little bit tricky. Some time ago I tried to add an "active" class to the link and the page. I ended up with this:
after scroll ended:
myScroll.on('scrollEnd', function () {
addActiveClass();
});
the function:
function addActiveClass() {
// get current page with iScroll
var currentSection = myScroll.currentPage.pageY;
// get current link and page
var activeLink = $('nav a[href="' + currentSection + '"] span');
var activeSection = $('section[class="' + currentSection + '"]');
// remove active class from all links and pages
$('nav a span, section').removeClass('active');
// add active class to current link and page
$(activeLink).addClass('active');
$(activeSection).addClass('active');
}
Only one thing that annoys me, you have to give every section a page number as a class:
<section class="0"> … <section>
<section class="1"> … <section>
<section class="2"> … <section>
Same with links:
But maybe could be added dynamically somehow.
And don't forget option:
snap: 'section'
jsfiddle demo

var workCase;
function loadcase() {
workCase = new IScroll('#work-case', {
mouseWheel: true,
resizeScrollbars: true,
snap: 'section',
interactiveScrollbars: true,
mouseWheelSpeed: 10,
scrollX: true,
scrollY: false,
momentum: true,
snapSpeed: 800,
scrollbars: 'custom',
wheelAction: 'scroll'
});
workCase.on('scrollEnd', function() {
var sectionIndex = Number(this.currentPage.pageY);
var iScrollConteiner = $('#work-case').children()[0];
var dataNumber = $(iScrollConteiner)[0].children[sectionIndex].className;
var activeSection = $('section[class="' + dataNumber + '"]');
$('section').removeClass('active');
$(activeSection).addClass('active');
});
}

Related

jQuery .map() Issue

I have basically no experience with jQuery, just enough to get by most of the time. However, I recently have been changing some templates around and came across a piece of jQuery that I didn't write, but is throwing an error (Uncaught Error: Syntax error, unrecognized expression: /). I'm not really sure where to start. All I know so far is that I'm fairly certain this piece of code is causing it, and it's choking right at the scrollItems line:
// Cache selectors
var lastId,
topMenu = $(".nav"),
topMenuHeight = topMenu.outerHeight() + 50,
// All list items
menuItems = topMenu.find("a"),
// Anchors corresponding to menu items
scrollItems = menuItems.map(function() {
var item = $($(this).attr("href"));
if (item.length) {
return item;
}
///////////////FANCYBOX
$(".fancybox-media").fancybox({
arrows: true,
padding: 0,
closeBtn: true,
openEffect: 'fade',
closeEffect: 'fade',
prevEffect: 'fade',
nextEffect: 'fade',
helpers: {
media: {},
overlay: {
locked: false
},
buttons: false,
title: {
type: 'inside'
}
},
beforeLoad: function() {
var el, id = $(this.element).data('title-id');
if (id) {
el = $('#' + id);
if (el.length) {
this.title = el.html();
}
}
}
});
});
I have tested the fancybox code separately, and it works, but I thought I'd leave it in to be thorough. There was also some commented out code that I took out. Any help would be very much appreciated!
It's likely that it is this line that is causing the error:
var item = $($(this).attr("href"));
You seem to have a link with href="/" (a link to the start page), so the code will do the same as:
var item = $("/");
jQuery will try to parse the URL as a selector, and you get that exact error message.
Check that the href attribute contains a bookmark and not an URL before you try to use it as a selector:
var href = $(this).attr("href");
if (href.substr(0, 1) == "#") {
var item = $(href);
if (item.length) {
return item;
}
}

jQuery - Wrong technic or a bug

I have an HTML page where I want to change the text of an H3 tag based on the selected element of a jQuery accordion. A small demo is available at this link.
<div id="acc1" class="basic">
<h3>aaa</h3>
<div></div>
<h3>bbb</h3>
<div></div>
<h3>ccc</h3>
<div></div>
</div>
<h3 class="ui-widget-header">xyz</h3>
$(document).ready(function () {
$("#acc1").accordion({
heightStyle: "fill",
active: false,
autoheight: false,
collapsible: true,
alwaysOpen: false,
activate: function (event, ui) {
var idx = $("#acc1").accordion("option", "active");
var txt = $("#acc1 > h3:nth-child(" + (idx + 1) + ") > a").text();
$("h3.ui-widget-header").text((idx + 1) + " ---> " + txt);
}
});
});
The acc1 is collapsed at beginning and soon an element gets a click, the jQuery function reads its text and assigns it to the H3 tag. But just the first click, after the page was loaded, works fine. After that only wrong values are assigned.
My way to do this is wrong or the jQuery is buggy?
Used stuff: jQuery v1.9.0, jQuery UI v1.9.2
Regards,
grafl
here is my solution :
$(document).ready(function () {
$("#acc1").accordion({
heightStyle: "fill",
active: false,
autoheight: false,
collapsible: true,
alwaysOpen: false,
activate: function (event, ui) {
}
});
$("h3").click(function(){
var txt = $(this).find('a').text();
$(".ui-widget-header").html(txt);
});
});
JSFIDDLE DEMO
:nth-child considers all siblings, not just the ones matching the tag you've qualified. So h3:nth-child(2) (for instance) means "an h3 element that is also the second child in its parent," not "the second h3 element in its parent."
For the latter, you can use jQuery's pseudo-selector :eq (which uses 0-based indexes), or the .eq function (which also does).
So change this line:
var txt = $("#acc1 > h3:nth-child(" + (idx + 1) + ") > a").text();
to:
var txt = $("#acc1 > h3").eq(idx).children("a").text();
Updated Fiddle
or:
var txt = $("#acc1 > h3:eq(" + idx + ") > a").text();
Updated Fiddle

Infinite Scroll with Isotope and filtering in Wordpress

I have searched just about every forum out there and found several ways to make a Isotope masonry layout with filtering work with Infinite Scroll running Wordpress. And none of them seem to be giving me what I'm looking for.
At the moment I got the Masonry layout working, with filtering. When I implement Infinite Scroll it loads the content underneath the other content, a pretty common issue working with Isotope and Infinite scroll. However, when applying the .appended method in order to sort the newly loaded posts into my site, it messes up my whole layout.
I suspect I'm not entering the .appended line at the right place. Here's my js without the .append:
$(function () {
var $page = $('#page')
});
$(function () {
var $container = $('#content'),
filters = {},
// get filter from hash, remove leading '#'
filterSelector = window.location.hash.slice(1);
$container.imagesLoaded(function () {
// bind isotope to window resize
$(window).smartresize(function () {
// jQuery has issues with percentage widths
// so we'll manually calulate it
var colW = Math.floor($container.width() * 0.49);
$container.isotope({
});
// trigger resize so isotope layout is triggered
}).smartresize();
});
$('#nav a').click(function () {
// store filter value in object
// i.e. filters.color = 'red'
var $this = $(this),
name = $this.attr('data-filter-name'),
value = $this.attr('data-filter-value'),
isoFilters = [],
filterName, prop;
filters[ name ] = value;
for (prop in filters) {
isoFilters.push(filters[ prop ]);
}
var filterSelector = isoFilters.join('');
// trigger isotope if its ready
if ($container.data('isotope')) {
$container.isotope({filter: filterSelector});
}
window.location.hash = filterSelector;
// toggle highlight
$this.parents('ul').find('.selected').removeClass('selected');
$this.parent().addClass('selected');
return false;
});
// if there was a filter, trigger a click on the
// corresponding option
if (filterSelector) {
var selectorClasses = filterSelector.split('.').slice(1);
$.each(selectorClasses, function (i, selectorClass) {
$('#nav a[data-filter-value=".' + selectorClass + '"]').click();
});
}
$container.isotope({
itemSelector: '.box',
filter: filterSelector,
animationOptions: {
duration: 750,
easing: 'linear',
queue: false,
}
});
});
#nav being my menu, #content being my container, and .box being my posts.
Could anyone advise me as to where I need to insert the .appended command?

I can't get 2 javascripts to work simultaneously

On a website im building on a Joomla CMS i call inside the head tag these javascripts :
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript" src="js/jquery.history.js"></script>
<script type="text/javascript" src="js/jquery.galleriffic.js"></script>
<script type="text/javascript" src="js/jquery.opacityrollover.js"></script>
<script type="text/javascript">document.write('<style>.noscript { display: none; }</style>');</script>
I have two javascripts inserted on my index.php
One for a slideshow (gallerific) and another one for a dropdown menu.
The slideshow javascript :
<script type="text/javascript">
jQuery(document).ready(function($) {
// We only want these styles applied when javascript is enabled
$('div.content').css('display', 'block');
// Initially set opacity on thumbs and add
// additional styling for hover effect on thumbs
var onMouseOutOpacity = 0.9;
$('#thumbs ul.thumbs li, div.navigation a.pageLink').opacityrollover({
mouseOutOpacity: onMouseOutOpacity,
mouseOverOpacity: 1.0,
fadeSpeed: 'fast',
exemptionSelector: '.selected'
});
// Initialize Advanced Galleriffic Gallery
var gallery = $('#thumbs').galleriffic({
delay: 2500,
numThumbs: 10,
preloadAhead: 10,
enableTopPager: false,
enableBottomPager: false,
imageContainerSel: '#slideshow',
controlsContainerSel: '#controls',
captionContainerSel: '#caption',
loadingContainerSel: '#loading',
renderSSControls: true,
renderNavControls: true,
playLinkText: 'Play Slideshow',
pauseLinkText: 'Pause Slideshow',
prevLinkText: '‹ Previous Photo',
nextLinkText: 'Next Photo ›',
nextPageLinkText: 'Next ›',
prevPageLinkText: '‹ Prev',
enableHistory: true,
autoStart: true,
syncTransitions: true,
defaultTransitionDuration: 900,
onSlideChange: function(prevIndex, nextIndex) {
// 'this' refers to the gallery, which is an extension of $('#thumbs')
this.find('ul.thumbs').children()
.eq(prevIndex).fadeTo('fast', onMouseOutOpacity).end()
.eq(nextIndex).fadeTo('fast', 1.0);
// Update the photo index display
this.$captionContainer.find('div.photo-index')
.html('Photo '+ (nextIndex+1) +' of '+ this.data.length);
},
onPageTransitionOut: function(callback) {
this.fadeTo('fast', 0.0, callback);
},
onPageTransitionIn: function() {
var prevPageLink = this.find('a.prev').css('visibility', 'hidden');
var nextPageLink = this.find('a.next').css('visibility', 'hidden');
// Show appropriate next / prev page links
if (this.displayedPage > 0)
prevPageLink.css('visibility', 'visible');
var lastPage = this.getNumPages() - 1;
if (this.displayedPage < lastPage)
nextPageLink.css('visibility', 'visible');
this.fadeTo('fast', 1.0);
}
});
/**************** Event handlers for custom next / prev page links **********************/
gallery.find('a.prev').click(function(e) {
gallery.previousPage();
e.preventDefault();
});
gallery.find('a.next').click(function(e) {
gallery.nextPage();
e.preventDefault();
});
/****************************************************************************************/
/**** Functions to support integration of galleriffic with the jquery.history plugin ****/
// PageLoad function
// This function is called when:
// 1. after calling $.historyInit();
// 2. after calling $.historyLoad();
// 3. after pushing "Go Back" button of a browser
function pageload(hash) {
// alert("pageload: " + hash);
// hash doesn't contain the first # character.
if(hash) {
$.galleriffic.gotoImage(hash);
} else {
gallery.gotoIndex(0);
}
}
// Initialize history plugin.
// The callback is called at once by present location.hash.
$.historyInit(pageload, "advanced.html");
// set onlick event for buttons using the jQuery 1.3 live method
$("a[rel='history']").live('click', function(e) {
if (e.button != 0) return true;
var hash = this.href;
hash = hash.replace(/^.*#/, '');
// moves to a new page.
// pageload is called at once.
// hash don't contain "#", "?"
$.historyLoad(hash);
return false;
});
/****************************************************************************************/
});
</script>
And the dropdown menu:
<script language="javascript" type="text/javascript">
var axm = {
openMenu: function() {
$('#newmenuheader').stop().animate({ 'height':'140px'}, "fast");
},
closeMenu: function() {
$('#newmenuheader').stop().css({'overflow': 'hidden'}).animate({'height':'55px'}, "fast");
},
};
</script>
I can get only one script run at a time not both. If one runs the other doesn't. I need to have them both.
At the time the javascript for the slideshow is running. Is there a conflict of some sort ?
Thanks in advance.
The second chunk of javascript code with the var axm needs to be added to the
jQuery(document).ready(function($) {}
Otherwise the browser doesn't know to run it. And you should re-write this function, don't use
jQuery(document).ready(function($) {}
just use
$(function(){
//your javascript and jQuery here for binding events, styles, and functions
}
this is a function that will run once the page is ready.

Mootools slider adjustments

I am new to mootools. I have joomla site with MooSlider:
var MooSlider = new Class({
initialize: function(options) {
this.options = Object.extend({
container: null,
slides: null,
navs:null,
transition: Fx.Transitions.Sine.easeOut,
effectDuration: 500,
fromTop: 500,
topDist: 100,
slideDelay: 5000
}, options || {});
if(!$(this.options.container)) return;
this.start();
},
start: function(){
this.elements = $(this.options.container).getElements(this.options.slides);
this.navs = $(this.options.container).getElements(this.options.navs);
this.currentElement = 0;
this.elements.each(function(elem, i){
var nav = this.navs[i];
if(i==this.currentElement){
nav.addClass('selected');
}
elem.setStyles({
'position':'absolute',
'top':0,
'left':0,
'opacity':( i==this.currentElement ? 1 : 0 )
});
this.elements[i]['fx'] = new Fx.Styles(elem, {
duration:this.options.effectDuration,
wait:false,
transition:this.options.transition
});
this.elements[i]['nav'] = nav;
elem.addEvents({
'mouseenter': function(){
$clear(this.period);
}.bind(this),
'mouseleave': function(){
if( this.options.slideDelay )
this.period = this.rotate.periodical(this.options.slideDelay, this);
}.bind(this)
});
nav.addEvent('click', function(event){
if(this.currentElement==i) return;
new Event(event).stop();
$clear(this.period);
this.changeSlide(i);
if( this.options.slideDelay )
this.period = this.rotate.periodical(this.options.slideDelay, this);
}.bind(this));
}.bind(this));
if( this.options.slideDelay )
this.period = this.rotate.periodical(this.options.slideDelay, this);
},
rotate: function(){
var i = this.currentElement+1 < this.elements.length ? this.currentElement+1 : 0;
this.changeSlide(i);
},
changeSlide: function(i){
//$(this.options.navigationContainer).addClass('preload');
var cEl = this.currentElement;
this.elements[this.currentElement]['fx'].start({'opacity':0, 'left':1500});
this.elements[i]['fx'].set({'left':0});
this.elements[i]['fx'].start({'opacity':1, 'top':[500,0]}).chain(function(){
//$(this.options.navigationContainer).removeClass('preload');
}.bind(this));
this.elements[this.currentElement]['nav'].removeClass('selected');
this.elements[i]['nav'].addClass('selected');
this.currentElement = i;
}})
This is how it used on page:
<script language="javascript" type="text/javascript">
window.addEvent('domready', function(){
new MooSlider({
container:'topslider',
slides:'.slide',
navs:'.navigator ul li',
effectDuration: 1000,
fromTop:500,
topDist:500,
slideDelay: 3000 });
})
The page url is http://www.miltonwebsitedesign.ca
You can see slider on top of the page. Each slide consists of picture at the left and description at the right.
What I need is to make slides work the same way, but the left side picture must not appear current way, it needs to fade in, when the slide is loaded, not appear, but fade in.
Description text slides and then at the left picture appears.
The structure of each slide is:
<div class='slide'>
<div class="yjsquare">
<div class="yjsquare_in">
<img src='src here' alt=''/><h1>H1 text here</h1><p>description here</p>
</div>
</div>
</div>
Will be happy to hear solution. Thanks.
this class is not well written as in, it does not allow for events like onStart and onComplete to be passed. the logical approach would be to modify the changeSlide method to fire some events:
// add
var el = this.elements[i]['fx'];
this.fireEvent("start", el);
// use el as reference...
el.start({'opacity':1, 'top':[500,0]}).chain(function(){
//$(this.options.navigationContainer).removeClass('preload');
// add
this.fireEvent("complete", el);
}.bind(this));
Make sure that your class also implements Events (which in 1.12 is done like so, if memory serves):
MooSlider.implement(new Events);
you are using a mix of 1.12 and 1.2+ code which is odd. In any case, if you do have 1.2 (joomla usually is not prior to 1.6) then instead add this into the class declaration:
Implements: [Events],
this allows you to add some callback logic upon instigating the class:
new MooSlider({
container:'topslider',
slides:'.slide',
navs:'.navigator ul li',
effectDuration: 1000,
fromTop:500,
topDist:500,
slideDelay: 3000,
onStart: function(el) {
el.getElement("img").setOpacity(0); // hide it during animation
},
onComplete: function(el) {
el.fade(1); // fade it in when done
}
});
you should really implement Options too and use this.setOptions(options) instead of your current $extend.
p.s. the onStart and onComplete code callbacks are examples, you may need to tweak this to suit your html and UI preferences.

Categories