Hi everyone I'm having an issue that I can't seem to wrap my head around. I'll try to keep this as brief as possible.
I'm attempting to set and get cookies in the background switcher I'm using. The switcher works well... It iterates through 7 background themes on click and the cookies seem to be working as well, but still on page refresh it reverts back to to the default "theme". I don't think it's a problem with the cookies because according to the alerts I attached to the cookies, it's returning the correct background (in the alert). It's just not loading the correct theme even though the cookie says it is.
I believe I narrowed it down to a bit of code in my javascript that might be responsible for the wrong background, however I don't know how to adjust it to make it do what I want.
The background (on refresh) will be whatever var current says it will be. Values of 0-6 will be a new background (on refresh) depending on what value it is. But it doesn't remember the user's selection on refresh. I've tried making var current into an array var current = [0,1,2,3,4,5,6],, but that didn't seem to help. When I did that it didn't show any of my 7 themes, and only showed the default color in body tag css.
When I tried the array, I changed this:
if( current < pagesCount - 1 ) {
++current;
alert($.cookie('style', current, { expires: 365, path: '/' }));
}
else {
current = 0;
}
to this:
for(var i = 0; i < current.length; i++){
if( current < pagesCount - 1 ) {
++current;
alert($.cookie('style', current, { expires: 365, path: '/' }));
}
else {
current = 0;
}
}
This is the click function, but I didn't change anything here
$iterate.on( 'click', function() {
if( isAnimating ) {
return false;
}
nextPage( animcursor);
++animcursor;
} );
I'm still pretty inexperienced with javascript so I'm sure there's a better way to do what I'm trying for. Any help would be appreciated! Thanks in advance.
The entire code block:
var changeTheme = (function() {
var $main = $( '#bg-main' ),
$pages = $main.children( 'div.bg-page' ),
$iterate = $( '#iterateEffects' ),
animcursor = 1,
pagesCount = $pages.length,
current = 0,
isAnimating = false,
endCurrPage = false,
endNextPage = false,
animEndEventNames = {
'WebkitAnimation' : 'webkitAnimationEnd',
'OAnimation' : 'oAnimationEnd',
'msAnimation' : 'MSAnimationEnd',
'animation' : 'animationend'
},
// animation end event name
animEndEventName = animEndEventNames[ Modernizr.prefixed( 'animation' ) ],
// support css animations
support = Modernizr.cssanimations;
function init() {
$pages.each( function() {
var $page = $( this );
$page.data( 'originalClassList', $page.attr( 'class' ) );
} );
$pages.eq( current ).addClass( 'bg-page-current' );
$iterate.on( 'click', function() {
if( isAnimating ) {
return false;
}
nextPage( animcursor);
++animcursor;
} );
}
function nextPage( animation ) {
if( isAnimating ) {
return false;
}
isAnimating = true;
var $currPage = $pages.eq( current );
if( current < pagesCount - 1 ) {
++current;
alert($.cookie('style', current, { expires: 365, path: '/' }));
}
else {
current = 0;
}
var $nextPage = $pages.eq( current ).addClass( 'bg-page-current' ),
outClass = '', inClass = '';
outClass = 'bg-page-scaleDown';
inClass = 'bg-page-scaleUpDown bg-page-delay300';
var classes = ['bg-page-0 bg-page-current','bg-page-1 bg-page-current', 'bg-page-2 bg-page-current', 'bg-page-3 bg-page-current', 'bg-page-4 bg-page-current', 'bg-page-5 bg-page-current', 'bg-page-6 bg-page-current'];
$currPage.addClass( outClass ).on( animEndEventName, function() {
$currPage.off( animEndEventName );
endCurrPage = true;
if( endNextPage ) {
onEndAnimation( $currPage, $nextPage );
}
} );
$nextPage.addClass( inClass ).on( animEndEventName, function() {
$nextPage.off( animEndEventName );
endNextPage = true;
if( endCurrPage ) {
onEndAnimation( $currPage, $nextPage );
}
} );
if( !support ) {
onEndAnimation( $currPage, $nextPage );
}
}
function onEndAnimation( $outpage, $inpage ) {
endCurrPage = false;
endNextPage = false;
resetPage( $outpage, $inpage );
isAnimating = false;
}
function resetPage( $outpage, $inpage ) {
$outpage.attr( 'class', $outpage.data( 'originalClassList' ) );
$inpage.attr( 'class', $inpage.data( 'originalClassList' ) + ' bg-page-current' );
}
//Cookies
window.onload = function(e) {
if($.cookie('style') == undefined) {
alert($.cookie('style', current, { expires: 365, path: '/' }));
current = 0;
} else {
current = current;
alert($.cookie('style'));
}
}
init();
return { init : init };
})();
If this hits the 'else' portion of the if statement, current is not defined on page load. I think you'd need do do something like
current = $.cookie('style');
Or is it always reporting as undefined on page load?
I'd just of made a comment, but lack of rep points prevents this.
//Cookies
window.onload = function(e) {
if($.cookie('style') == undefined) {
alert($.cookie('style', current, { expires: 365, path: '/' }));
current = 0;
} else {
current = current;
alert($.cookie('style'));
}
}
Related
I am not sure so I decide to ask here. I have a plugin which uses jquery animate function and then it call complete callback. It works pretty much with dom. After few cycles script starts to be slow. I cant find any issue only local lambda variables. But I dont know why this local variables should remain in memory. It does not make sense. Here is the code:
cEl.el.animate( { left: offset.left - state.cEl.mL, top: offset.top - state.cEl.mT }, 250,
function() // complete callback
{
tidyCurrEl( cEl );
targetEl.after( cEl.el[0] );
targetEl[0].style.display = 'none';
hintStyle.display = 'none';
hintNode.remove();
......
if ( isHintTarget )
{
// This seems to be a problem.
var paretnLi = state.placeholderNode.parent().closest( 'li' )
......
}
else
{
......
}
} );
Am I right the local variables in anonymous function is the problem? Thanks.
Here is full code example
function endDrag( e )
{
var cEl = state.cEl,
hintNode = $( '#s-l-hint', state.rootEl.el ),
hintStyle = hint[0].style,
targetEl = null, // hintNode/placeholderNode
isHintTarget = false, // if cEl will be placed to the hintNode
hintWrapperNode = $( '#s-l-hint-wrapper' );
if ( hintStyle.display == 'block' && hintNode.length && state.isAllowed )
{
targetEl = hintNode;
isHintTarget = true;
}
else
{
targetEl = state.placeholderNode;
isHintTarget = false;
}
offset = targetEl.offset();
cEl.el.animate( { left: offset.left - state.cEl.mL, top: offset.top - state.cEl.mT }, 250,
function() // complete callback
{
tidyCurrEl( cEl );
targetEl.after( cEl.el[0] );
targetEl[0].style.display = 'none';
hintStyle.display = 'none';
// This has to be document node, not hint as a part of documentFragment.
hintNode.remove();
hintWrapperNode
.removeAttr( 'id' )
.removeClass( setting.hintWrapperClass );
if ( hintWrapperNode.length )
{
hintWrapperNode.prev( 'div' ).append( opener.clone( true ) );
}
var placeholderNode = state.placeholderNode;
// Directly removed placeholder looks bad. It jumps up if the hint is below.
if ( isHintTarget )
{
placeholderNode.slideUp( 150, function()
{
var placeholderParent = placeholderNode.parent();
var placeholderParentLi = ( ! placeholderParent.is( state.rootEl.el ) ) ? placeholderParent.closest( 'li' ) : null;
placeholderNode.remove();
tidyEmptyLists();
setting.onChange( cEl.el );
setting.complete( cEl.el ); // Have to be here cause is necessary to remove placeholder before complete call.
state.isDragged = false;
if( setting.maxLevels !== false ) // Has to be after placeholder remove.
{
recountLevels( cEl.el );
if( placeholderParentLi ) recountLevels( placeholderParentLi );
}
});
}
else
{
state.placeholderNode.remove();
tidyEmptyLists();
setting.complete( cEl.el );
state.isDragged = false;
}
} );
scrollStop( state );
state.doc
.unbind( "mousemove", dragging )
.unbind( "mouseup", endDrag );
}
I use a plugin that use this block of statements to display menus,Now I use it in angular js.
(function(window) {
'use strict';
var support = { animations : Modernizr.cssanimations },
animEndEventNames = { 'WebkitAnimation' : 'webkitAnimationEnd', 'OAnimation' : 'oAnimationEnd', 'msAnimation' : 'MSAnimationEnd', 'animation' : 'animationend' },
animEndEventName = animEndEventNames[ Modernizr.prefixed( 'animation' ) ],
onEndAnimation = function( el, callback ) {
var onEndCallbackFn = function( ev ) {
if( support.animations ) {
if( ev.target != this ) return;
this.removeEventListener( animEndEventName, onEndCallbackFn );
}
if( callback && typeof callback === 'function' ) { callback.call(); }
};
if( support.animations ) {
el.addEventListener( animEndEventName, onEndCallbackFn );
}
else {
onEndCallbackFn();
}
};
function extend( a, b ) {
for( var key in b ) {
if( b.hasOwnProperty( key ) ) {
a[key] = b[key];
}
}
return a;
}
function MLMenu(el, options) {
this.el = el;
this.options = extend( {}, this.options );
extend( this.options, options );
// the menus (<ul>´s)
this.menus = [].slice.call(this.el.querySelectorAll('.menu__level'));
// index of current menu
this.current = 0;
this._init();
}
MLMenu.prototype.options = {
// show breadcrumbs
breadcrumbsCtrl : true,
// initial breadcrumb text
initialBreadcrumb : 'all',
// show back button
backCtrl : true,
// delay between each menu item sliding animation
itemsDelayInterval : 60,
// direction
direction : 'r2l',
// callback: item that doesn´t have a submenu gets clicked
// onItemClick([event], [inner HTML of the clicked item])
onItemClick : function(ev, itemName) { return false; }
};
MLMenu.prototype._init = function() {
// iterate the existing menus and create an array of menus, more specifically an array of objects where each one holds the info of each menu element and its menu items
this.menusArr = [];
var self = this;
this.menus.forEach(function(menuEl, pos) {
var menu = {menuEl : menuEl, menuItems : [].slice.call(menuEl.querySelectorAll('.menu__item'))};
self.menusArr.push(menu);
// set current menu class
if( pos === self.current ) {
classie.add(menuEl, 'menu__level--current');
}
});
// create back button
if( this.options.backCtrl ) {
this.backCtrl = document.createElement('button');
this.backCtrl.className = 'menu__back menu__back--hidden';
this.backCtrl.setAttribute('aria-label', 'Go back');
this.backCtrl.innerHTML = '<span class="icon icon--arrow-left"></span>';
this.el.insertBefore(this.backCtrl, this.el.firstChild);
}
// create breadcrumbs
if( self.options.breadcrumbsCtrl ) {
this.breadcrumbsCtrl = document.createElement('nav');
this.breadcrumbsCtrl.className = 'menu__breadcrumbs';
this.el.insertBefore(this.breadcrumbsCtrl, this.el.firstChild);
// add initial breadcrumb
this._addBreadcrumb(0);
}
// event binding
this._initEvents();
};
MLMenu.prototype._initEvents = function() {
var self = this;
for(var i = 0, len = this.menusArr.length; i < len; ++i) {
this.menusArr[i].menuItems.forEach(function(item, pos) {
item.querySelector('a').addEventListener('click', function(ev) {
var submenu = ev.target.getAttribute('data-submenu'),
itemName = ev.target.innerHTML,
subMenuEl = self.el.querySelector('ul[data-menu="' + submenu + '"]');
// check if there's a sub menu for this item
if( submenu && subMenuEl ) {
ev.preventDefault();
// open it
self._openSubMenu(subMenuEl, pos, itemName);
}
else {
// add class current
var currentlink = self.el.querySelector('.menu__link--current');
if( currentlink ) {
classie.remove(self.el.querySelector('.menu__link--current'), 'menu__link--current');
}
classie.add(ev.target, 'menu__link--current');
// callback
self.options.onItemClick(ev, itemName);
}
});
});
}
// back navigation
if( this.options.backCtrl ) {
this.backCtrl.addEventListener('click', function() {
self._back();
});
}
};
MLMenu.prototype._openSubMenu = function(subMenuEl, clickPosition, subMenuName) {
if( this.isAnimating ) {
return false;
}
this.isAnimating = true;
// save "parent" menu index for back navigation
this.menusArr[this.menus.indexOf(subMenuEl)].backIdx = this.current;
// save "parent" menu´s name
this.menusArr[this.menus.indexOf(subMenuEl)].name = subMenuName;
// current menu slides out
this._menuOut(clickPosition);
// next menu (submenu) slides in
this._menuIn(subMenuEl, clickPosition);
};
MLMenu.prototype._back = function() {
if( this.isAnimating ) {
return false;
}
this.isAnimating = true;
// current menu slides out
this._menuOut();
// next menu (previous menu) slides in
var backMenu = this.menusArr[this.menusArr[this.current].backIdx].menuEl;
this._menuIn(backMenu);
// remove last breadcrumb
if( this.options.breadcrumbsCtrl ) {
this.breadcrumbsCtrl.removeChild(this.breadcrumbsCtrl.lastElementChild);
}
};
MLMenu.prototype._menuOut = function(clickPosition) {
// the current menu
var self = this,
currentMenu = this.menusArr[this.current].menuEl,
isBackNavigation = typeof clickPosition == 'undefined' ? true : false;
// slide out current menu items - first, set the delays for the items
this.menusArr[this.current].menuItems.forEach(function(item, pos) {
item.style.WebkitAnimationDelay = item.style.animationDelay = isBackNavigation ? parseInt(pos * self.options.itemsDelayInterval) + 'ms' : parseInt(Math.abs(clickPosition - pos) * self.options.itemsDelayInterval) + 'ms';
});
// animation class
if( this.options.direction === 'r2l' ) {
classie.add(currentMenu, !isBackNavigation ? 'animate-outToLeft' : 'animate-outToRight');
}
else {
classie.add(currentMenu, isBackNavigation ? 'animate-outToLeft' : 'animate-outToRight');
}
};
MLMenu.prototype._menuIn = function(nextMenuEl, clickPosition) {
var self = this,
// the current menu
currentMenu = this.menusArr[this.current].menuEl,
isBackNavigation = typeof clickPosition == 'undefined' ? true : false,
// index of the nextMenuEl
nextMenuIdx = this.menus.indexOf(nextMenuEl),
nextMenuItems = this.menusArr[nextMenuIdx].menuItems,
nextMenuItemsTotal = nextMenuItems.length;
// slide in next menu items - first, set the delays for the items
nextMenuItems.forEach(function(item, pos) {
item.style.WebkitAnimationDelay = item.style.animationDelay = isBackNavigation ? parseInt(pos * self.options.itemsDelayInterval) + 'ms' : parseInt(Math.abs(clickPosition - pos) * self.options.itemsDelayInterval) + 'ms';
// we need to reset the classes once the last item animates in
// the "last item" is the farthest from the clicked item
// let's calculate the index of the farthest item
var farthestIdx = clickPosition <= nextMenuItemsTotal/2 || isBackNavigation ? nextMenuItemsTotal - 1 : 0;
if( pos === farthestIdx ) {
onEndAnimation(item, function() {
// reset classes
if( self.options.direction === 'r2l' ) {
classie.remove(currentMenu, !isBackNavigation ? 'animate-outToLeft' : 'animate-outToRight');
classie.remove(nextMenuEl, !isBackNavigation ? 'animate-inFromRight' : 'animate-inFromLeft');
}
else {
classie.remove(currentMenu, isBackNavigation ? 'animate-outToLeft' : 'animate-outToRight');
classie.remove(nextMenuEl, isBackNavigation ? 'animate-inFromRight' : 'animate-inFromLeft');
}
classie.remove(currentMenu, 'menu__level--current');
classie.add(nextMenuEl, 'menu__level--current');
//reset current
self.current = nextMenuIdx;
// control back button and breadcrumbs navigation elements
if( !isBackNavigation ) {
// show back button
if( self.options.backCtrl ) {
classie.remove(self.backCtrl, 'menu__back--hidden');
}
// add breadcrumb
self._addBreadcrumb(nextMenuIdx);
}
else if( self.current === 0 && self.options.backCtrl ) {
// hide back button
classie.add(self.backCtrl, 'menu__back--hidden');
}
// we can navigate again..
self.isAnimating = false;
});
}
});
// animation class
if( this.options.direction === 'r2l' ) {
classie.add(nextMenuEl, !isBackNavigation ? 'animate-inFromRight' : 'animate-inFromLeft');
}
else {
classie.add(nextMenuEl, isBackNavigation ? 'animate-inFromRight' : 'animate-inFromLeft');
}
};
MLMenu.prototype._addBreadcrumb = function(idx) {
if( !this.options.breadcrumbsCtrl ) {
return false;
}
var bc = document.createElement('a');
bc.innerHTML = idx ? this.menusArr[idx].name : this.options.initialBreadcrumb;
this.breadcrumbsCtrl.appendChild(bc);
var self = this;
bc.addEventListener('click', function(ev) {
ev.preventDefault();
// do nothing if this breadcrumb is the last one in the list of breadcrumbs
if( !bc.nextSibling || self.isAnimating ) {
return false;
}
self.isAnimating = true;
// current menu slides out
self._menuOut();
// next menu slides in
var nextMenu = self.menusArr[idx].menuEl;
self._menuIn(nextMenu);
// remove breadcrumbs that are ahead
var siblingNode;
while (siblingNode = bc.nextSibling) {
self.breadcrumbsCtrl.removeChild(siblingNode);
}
});
};
window.MLMenu = MLMenu;
})(window);
and customized java script :
(function() {
var menuEl = document.getElementById('ml-menu');
mlmenu = new MLMenu(menuEl, {
// breadcrumbsCtrl : true, // show breadcrumbs
// initialBreadcrumb : 'all', // initial breadcrumb text
backCtrl : false, // show back button
// itemsDelayInterval : 60, // delay between each menu item sliding animation
onItemClick: loadDummyData // callback: item that doesn´t have a submenu gets clicked - onItemClick([event], [inner HTML of the clicked item])
});
//mobile menu toggle
var openMenuCtrl = document.querySelector('.action--open'),
closeMenuCtrl = document.querySelector('.action--close');
openMenuCtrl.addEventListener('click', openMenu);
closeMenuCtrl.addEventListener('click', closeMenu);
function openMenu() {
classie.add(menuEl, 'menu--open');
}
function closeMenu() {
classie.remove(menuEl, 'menu--open');
}
// simulate grid content loading
var gridWrapper = document.querySelector('.content');
function loadDummyData(ev, itemName) {
ev.preventDefault();
closeMenu();
gridWrapper.innerHTML = '';
classie.add(gridWrapper, 'content--loading');
setTimeout(function() {
classie.remove(gridWrapper, 'content--loading');
gridWrapper.innerHTML = '<ul class="products">' + dummyData[itemName] + '<ul>';
}, 700);
}
})();
I want convert a part of this below customized script to angular js.
mlmenu = new MLMenu(menuEl, {
// breadcrumbsCtrl : true, // show breadcrumbs
// initialBreadcrumb : 'all', // initial breadcrumb text
backCtrl : false, // show back button
// itemsDelayInterval : 60, // delay between each menu item sliding animation
onItemClick: loadDummyData // callback: item that doesn´t have a submenu gets clicked - onItemClick([event], [inner HTML of the clicked item])
});
I use it as this in angular but it has error .
$scope.menuEl = document.getElementById('ml-menu');
var menuEl = document.getElementById('ml-menu'),
mlmenu = new MLMenu(menuEl, {
// breadcrumbsCtrl : true, // show breadcrumbs
// initialBreadcrumb : 'all', // initial breadcrumb text
backCtrl: false, // show back button
// itemsDelayInterval : 60, // delay between each menu item sliding animation
onItemClick: $scope.loadDummyData // callback: item that doesn´t have a submenu gets clicked - onItemClick([event], [inner HTML of the clicked item])
});
How can I do it ?
I think you should wrap your plugin with AngularJS directive https://docs.angularjs.org/guide/directive
I.e. create directive that uses your plugin and initialize it on marked DOM.
angular.module('yourModule')
.directive('mlMenu', function() {
return {
restrict: 'A',
link: function (scope, element) {
var mlmenu = new MLMenu(element,
...
}
};
});
Than in HTML
<div data-ml-menu></div>
And if you are going to modify scope in plugin listeners do not forget to use scope.$apply() wrapper.
The javascript below enables swipe left/right navigation. For some reason, I would like to call this function using URL such as <a href="javascript:function">. Certain URL will equivalent to left swipe, while another URL will equivalent to right swipe. Is this possible?
(function( window ){
var window = window,
document = window.document,
screen = window.screen,
touchSwipeListener = function( options ) {
// Private members
var track = {
startX: 0,
endX: 0
},
defaultOptions = {
moveHandler: function( direction ) {},
endHandler: function( direction ) {},
minLengthRatio: 0.3
},
getDirection = function() {
return track.endX > track.startX ? "prev" : "next";
},
isDeliberateMove = function() {
var minLength = Math.ceil( screen.width * options.minLengthRatio );
return Math.abs(track.endX - track.startX) > minLength;
},
extendOptions = function() {
for (var prop in defaultOptions) {
if ( defaultOptions.hasOwnProperty( prop ) ) {
options[ prop ] || ( options[ prop ] = defaultOptions[ prop ] );
}
}
},
handler = {
touchStart: function( event ) {
// At least one finger has touched the screen
if ( event.touches.length > 0 ) {
track.startX = event.touches[0].pageX;
}
},
touchMove: function( event ) {
if ( event.touches.length > 0 ) {
track.endX = event.touches[0].pageX;
options.moveHandler( getDirection(), isDeliberateMove() );
}
},
touchEnd: function( event ) {
var touches = event.changedTouches || event.touches;
if ( touches.length > 0 ) {
track.endX = touches[0].pageX;
isDeliberateMove() && options.endHandler( getDirection() );
}
}
};
extendOptions();
// Graceful degradation
if ( !document.addEventListener ) {
return {
on: function() {},
off: function() {}
}
}
return {
on: function() {
document.addEventListener('touchstart', handler.touchStart, false);
document.addEventListener('touchmove', handler.touchMove, false);
document.addEventListener('touchend', handler.touchEnd, false);
},
off: function() {
document.removeEventListener('touchstart', handler.touchStart);
document.removeEventListener('touchmove', handler.touchMove);
document.removeEventListener('touchend', handler.touchEnd);
}
}
}
// Expose global
window.touchSwipeListener = touchSwipeListener;
}( window ));
(function( window ){
var document = window.document,
// Element helpers
Util = {
addClass: function( el, className ) {
el.className += " " + className;
},
hasClass: function( el, className ) {
var re = new RegExp("\s?" + className, "gi");
return re.test( el.className );
},
removeClass: function( el, className ) {
var re = new RegExp("\s?" + className, "gi");
el.className = el.className.replace(re, "");
}
},
swipePageNav = (function() {
// Page sibling links like <link rel="prev" title=".." href=".." />
// See also http://diveintohtml5.info/semantics.html
var elLink = {
prev: null,
next: null
},
// Arrows, which slide in to indicate the shift direction
elArrow = {
prev: null,
next: null
},
swipeListener;
return {
init: function() {
this.retrievePageSiblings();
// Swipe navigation makes sense only if any of sibling page link available
if ( !elLink.prev && !elLink.next ) {
return;
}
this.renderArows();
this.syncUI();
},
syncUI: function() {
var that = this;
// Assign handlers for swipe "in progress" / "complete" events
swipeListener = new window.touchSwipeListener({
moveHandler: function( direction, isDeliberateMove ) {
if ( isDeliberateMove ) {
if ( elArrow[ direction ] && elLink[ direction ] ) {
Util.hasClass( elArrow[ direction ], "visible" ) ||
Util.addClass( elArrow[ direction ], "visible" );
}
} else {
Util.removeClass( elArrow.next, "visible" );
Util.removeClass( elArrow.prev, "visible" );
}
},
endHandler: function( direction ) {
that[ direction ] && that[ direction ]();
}
});
swipeListener.on();
},
retrievePageSiblings: function() {
elLink.prev = document.querySelector( "head > link[rel=prev]");
elLink.next = document.querySelector( "head > link[rel=next]");
},
renderArows: function() {
var renderArrow = function( direction ) {
var div = document.createElement("div");
div.className = "spn-direction-sign " + direction;
document.getElementsByTagName( "body" )[ 0 ].appendChild( div );
return div;
}
elArrow.next = renderArrow( "next" );
elArrow.prev = renderArrow( "prev" );
},
// When the shift (page swap) is requested, this overlay indicates that
// the current page is frozen and a new one is loading
showLoadingScreen: function() {
var div = document.createElement("div");
div.className = "spn-freezing-overlay";
document.getElementsByTagName( "body" )[ 0 ].appendChild( div );
},
// Request the previous sibling page
prev: function() {
if ( elLink.prev ) {
this.showLoadingScreen();
window.location.href = elLink.prev.href;
}
},
// Request the next sibling page
next: function() {
if ( elLink.next ) {
this.showLoadingScreen();
window.location.href = elLink.next.href;
}
}
}
}())
// Apply when document is ready
document.addEventListener( "DOMContentLoaded", function(){
document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
try {
swipePageNav.init();
} catch (e) {
alert(e);
}
}, false );
}( window ));
You cannot do that. However, if it is for organization goals why not have two JavaScript files, each one with its own namespace. If you do this, you call only that namespace expected for the link clicked.
I am using infinite scroll to load posts and tried to integrate a custom like button for every single posts that needs a small jquery script to work. My problem is I added this Jquery directly after the sucess in ajax load posts. But when I load eg the 3. page my jquery script executes twice and on the posts of the 2nd page the lke buttons are not working correctly. How can I handle this? If I dont execute the code after the ajax request and only call this jquery code globally the like buttons do not work in the new loaded posts of the ajax infinite scroll. Maybe I need to stop the sript of before when eg loadin 3. page through the ajax infinite scroll but how? This is my code:
function load_more_posts(selector){
var url = $(selector).attr('href');
var data;
loading = true;
$.ajax({
url: url,
data: data,
success: function( data ) {
var $items = $( '.loading-content .item', data );
$new_anchor = $( selector, data );
$items.addClass('hidden');
if ( $('#cooked-plugin-page .result-section.masonry-layout .loading-content').length ){
$( '.loading-content').isotope( 'insert', $items );
} else {
$( '.loading-content').append($items);
setTimeout(function() {
$items.removeClass('hidden');
}, 200);
}
if($new_anchor.length) {
$(selector).attr('href', $new_anchor.attr('href'));
} else {
$(selector).remove();
}
loading = false;
$('.like-btn').each(function() {
var $button = $(this),
$icon = $button.find('> i'),
likedRecipes = $.cookie('cpLikedRecipes'),
recipeID = $button.attr('data-recipe-id');
cookied = $button.attr('data-cookied');
userLiked = $button.attr('data-userliked');
if ( cookied == 1 && typeof likedRecipes !== 'undefined' && likedRecipes.split(',').indexOf(recipeID) > -1 || userLiked == 1 ) {
$icon.removeClass('fa-heart-o').addClass('fa-heart');
}
});
$('#cooked-plugin-page .like-btn').on('click', function() {
var $button = $(this),
$icon = $button.find('> i'),
$count = $button.find('.like-count'),
count = parseInt($count.text()),
likedRecipes = $.cookie('cpLikedRecipes'),
recipeID = $button.attr('data-recipe-id'),
cookied = $button.attr('data-cookied'),
likeURL = $button.attr('href'),
likeAction;
if ( $icon.hasClass('fa-heart-o') ) {
$icon.removeClass('fa-heart-o').addClass('fa-heart');
count++;
if (cookied == 1){
if ( typeof likedRecipes === 'undefined' ) {
likedRecipes = recipeID;
} else {
likedRecipes = likedRecipes + ',' + recipeID;
}
$.cookie('cpLikedRecipes', likedRecipes, { expires: 365 } );
}
likeAction = 'like';
} else {
$icon.removeClass('fa-heart').addClass('fa-heart-o');
count--;
if (cookied == 1){
if ( typeof likedRecipes === 'undefied' ) {
return false;
}
}
if (cookied == 1){
var likedSplit = likedRecipes.split(','),
recipeIdx = likedSplit.indexOf(recipeID);
if ( recipeIdx > -1 ) {
likedSplit.splice( recipeIdx, 1 );
likedRecipes = likedSplit.join(',');
$.cookie('cpLikedRecipes', likedRecipes, { expires: 365 } );
likeAction = 'dislike';
}
} else {
likeAction = 'dislike';
}
}
$.ajax({
'url' : likeURL,
'data': {
'action' : 'cp_like',
'likeAction': likeAction
},
success: function(data) {
$count.text(data);
}
});
return false;
});
$('#cooked-plugin-page .tab-links a').on('click', function() {
var tab = $(this).attr('href');
if ( !$(this).is('.current') ){
$(this).addClass('current').siblings('.current').removeClass('current');
$('#cooked-plugin-page.fullscreen .tab').removeClass('current');
$(tab).addClass('current');
$win.scrollTop(0);
}
return false;
});
if($('.rating-holder').length) {
$('.rating-holder .rate')
.on('mouseenter', function() {
var $me = $(this);
var $parent = $me.parents('.rating-holder');
var my_index = $me.index();
var rated = $parent.attr('data-rated');
$parent.removeClass(function(index, css) {
return (css.match (/(^|\s)rate-\S+/g) || []).join(' ');
});
$parent.addClass('rate-' + (my_index + 1));
})
.on('mouseleave', function() {
var $me = $(this);
var $parent = $me.parents('.rating-holder');
var my_index = $me.index();
var rated = $parent.attr('data-rated');
$parent.removeClass(function(index, css) {
return (css.match (/(^|\s)rate-\S+/g) || []).join(' ');
});
if(rated !== undefined) {
$parent.addClass('rate-' + rated);
}
})
.on('click', function() {
var $me = $(this);
var $parent = $me.parents('.rating-holder');
var my_index = $me.index();
$('.rating-real-value').val(my_index + 1);
$parent.attr('data-rated', my_index + 1);
$parent.addClass('rate-' + (my_index + 1));
});
}
setTimeout(function() {
masonry();
}, 500);
}
});
}
There's a great plugin for scrolling. He has methods such as bund, unbind, destroy and e.t.c.:
https://github.com/infinite-scroll/infinite-scroll#methods
*Code rewritten
I'm trying to convert antirez's autocompleter to javascript to use it with node.js.
I can't pass the closure Problem. Maybe someone can help me out.
I see where the problems are but can't figure out how to solve them.
The while loop is firing, the break is not correct and won't work etc.
Code:
var acp = {
vars: {
dict : false,
count : false,
prefix : false,
rangeLen : 10,
start : false,
results : false,
range : false,
},
sendResults: function(){
console.log(acp.vars.results);
},
getzrank: function(){
redis.zrank( acp.vars.dict, acp.vars.prefix, function( err, start ){
acp.vars.start = start;
});
},
getzrange: function(){
redis.zrange( acp.vars.dict, acp.vars.start, parseFloat( acp.vars.start+acp.vars.rangeLen-1 ), function( err, range ){
acp.vars.range = range;
});
},
createAutocomplete: function(){
while( acp.vars.results.length != acp.vars.count ){
acp.getzrange();
acp.vars.start+=acp.vars.rangeLen;
if( ! acp.vars.range || acp.vars.range.length == 0 ) { break; }
for ( var i in acp.vars.range ){
var minLen = Math.min(i.length,acp.vars.prefix.length);
if( i.substr( 0, minLen ) != acp.vars.prefix.substr( 0, minLen ) ){
acp.vars.count = acp.vars.results.length;
}
if( i.substr( 0, i.length-1 ) == "*" && acp.vars.results.length != acp.vars.count) {
acp.vars.results.push( i.substr(0,-1) );
}
}
}
acp.sendResults();
},
init: function(dict,prefix,count){
acp.vars.range = false;
acp.vars.dict = dict;
acp.vars.prefix = prefix;
acp.vars.count = count;
acp.vars.results = [];
acp.vars.start = acp.getzrank();
if( ! acp.vars.start ){ acp.sendResults(); }
else{ acp.createAutocomplete(); }
}
}
The break statement is outside the scope of the while loop since its nested in the anonymous function. Not sure if that solves your problem.