I have small angular SPA with couple routes. What I wanted is to have fadein effect only on #/welcome/ page. My jquery works ok but the problem is - its running on all pages and in another pages elements what should be animated just doesnt exist and thats the reason I have errors on my console when user scroll... I tried run script only when route changed and than check if location is /#/welcome but it always running even if not... I tried to put code only to controller which should scoped it to section with animating elements but it also run in another pages... Im confused please help
$scope.$on('$routeChangeSuccess', function() {
if (window.location.hash == '#/welcome') {
function check(element , fadeEffect ) {
$(window).on('scroll' , function(){
var position = $(document).scrollTop() + $(window).innerHeight() ;
var elem = $(element).offset().top + ($(element).innerHeight()) / 2;
if (elem <= position) {
$(element).addClass(fadeEffect);
}
else {
$(element).removeClass(fadeEffect);
}
});
}
check('.tablet' , 'fadeInRight');
check('.padding' , 'fadeInLeft');
}
else {
console.log('another page');
}
});
Your app is SPA, so once you add event to window it will keep until you close the browser tab.
You have to remove the event on destroying welcome page, so remove all those codes and add these to your welcome page controller:
//in welcome page controller
var onScroll = function(){
var queries = [
{elm: '.tablet', effect: 'fadeInRight'},
{elm: '.padding', effect: 'fadeInLeft'}
];
for (var i=0, j=queries.length; i<j; i++) {
var position = $(document).scrollTop() + $(window).innerHeight() ;
var elem = $(queries[i].elm).offset().top + ($(queries[i].elm).innerHeight()) / 2;
if (elem <= position) {
$(queries[i].elm).addClass(queries[i].effect);
}
else {
$(queries[i].elm).removeClass(queries[i].effect);
}
}
}
$(window).on('scroll' , onScroll);
$scope.$on('$destroy', function() {
$(window).off('scroll' , onScroll);
});
Related
I am working on a long one-pager. Yes, I know, we hate one-pagers. At least I promise not to implement any parallax-effect, I promise :)
I have multiple sections I can open/close. This part works fine.
The problem: those sections get pretty long, and when they are being closed/collapsed, the user find himself somewhere in the middle of the one-pager.
So, when collapsing a section, I want it to collapse AND to smooth scroll back to the top/the start of the collapsed section.
Here my script:
// Section-Collapse
//---------------------------------------------------------
$("section a.read-more").click(function() {
if($(this).parents("section").hasClass("expanded")) {
var scrollAnchor = $(this).attr("data-scroll"),
scrollPoint = $(".anchor[data-anchor='" + scrollAnchor + "']").offset().top - 0;
$("body,html").animate({
scrollTop: scrollPoint
}, 1500, function() {
// close/collapse section
$(this).parents("section").addClass("close");
$("section.expanded.close div.expandable-content").slideUp();
$(this).parents("section").removeClass("expanded").removeClass("close");
alert("this test-message is being displayed");
});
} else {
// open section
$(this).parents("section").addClass("expanded");
$("section.expanded div.expandable-content").slideDown();
}
});
The problem: this part is not being executed EXCEPT the alert message, that one works. Although it is trying to open the dialog window multiple times and Firefox offers me to block this behavior.
// einklappen
$(this).parents("section").addClass("close");
$("section.expanded.close div.expandable-content").slideUp();
$(this).parents("section").removeClass("expanded").removeClass("close");
alert("this test-message is being displayed");
It scrolls back to top, to the anchor, but the section will not collapse...
Any ideas why it won't collapse?
Regards,
Milan
---------------------------UPDATE
So, it was a problem with the scope of variable "this".
This code here seems to work fine:
// Section-Collapse
//---------------------------------------------------------
$("section a.read-more").click(function() {
if($(this).parents("section").hasClass("expanded")) {
var scrollAnchor = $(this).attr("data-scroll"),
scrollPoint = $(".anchor[data-anchor='" + scrollAnchor + "']").offset().top - 0;
var global_this = $(this);
$("body,html").animate({
scrollTop: scrollPoint
}, 1500, function() {
// einklappen
global_this.parents("section").addClass("close");
$("section.expanded.close div.expandable-content").slideUp();
global_this.parents("section").removeClass("expanded").removeClass("close");
alert("this test-message is being displayed");
});
// return false;
} else {
// ausklappen
$(this).parents("section").addClass("expanded");
$("section.expanded div.expandable-content").slideDown();
}
});
What is bothering me: why this script tries to open multiple alert dialogs?
I've created a modal service within my Angular app that I can inject into controllers or directives. I'm running into a problem where after opening/closing a modal multiple times, everything within the modal stops workings. The modal works by grabbing content from a hidden div on the page and popping it into the modal. I've been able to determine that at some point, the value of modal.settings changes. If I insert a debugger at the beginning of my modal.open function and save the value of var x = settings in my console, I can see that after a few cycles, x !== settings. I've also tried comparing modal.settings, but the same thing happens. Eventually, after a few cycles, modal.settings changes and things stop working.
I think I need to refactor this service, but I'm not sure where to start and could use some guidance.
Here is the service code:
app.service('modal', ['$compile', function($compile) {
var modal = this;
modal.settings;
modal.contents;
modal.overlay = $('<div id="overlay"></div>');
modal.modal = $('<div id="modal"></div>');
modal.content = $('<div id="content"></div>');
modal.closeBtn = $('<div id="close"><i class="fa fa-times"></div>');
modal.modal.hide();
modal.overlay.hide();
modal.modal.append(modal.content, modal.closeBtn);
$(document).ready(function(){
$('body').append(modal.overlay, modal.modal);
});
modal.open = function (settings) {
if(!modal.settings) {
modal.settings = settings;
}
modal.content.empty().append(modal.settings.content);
if(modal.settings.class) modal.modal.addClass(modal.settings.class);
if(modal.settings.height) modal.modal.css({ height: modal.settings.height });
if(modal.settings.width) modal.modal.css({ width: modal.settings.width });
if(modal.settings.content_height) modal.modal.css({ height: modal.settings.content_height });
if(modal.settings.content_width) modal.modal.css({ width: modal.settings.content_width });
if(modal.settings.fitToWindow) {
modal.settings.width = $(window).width() - 160;
modal.settings.height = $(window).height() - 160;
};
center(modal.settings.top);
$(window).bind('resize.modal', center);
modal.modal.show();
modal.overlay.show();
$(modal.closeBtn).add(modal.overlay).on('click', function(e) {
e.stopPropagation();
modal.close();
});
$(document).on('keyup', function(e) {
if (e.keyCode == 27) {
modal.close();
$(document).unbind('keyup');
}
})
};
modal.close = function() {
debugger;
modal.settings.elem.empty().append(modal.settings.content);
modal.modal.hide();
modal.overlay.hide();
modal.content.empty();
$(window).unbind('resize.modal');
};
function center(top) {
if(!top || !isInt(top)) top = 130;
var mLeft = -1 * modal.modal.width() / 2;
modal.modal.css({
top: top + 'px',
left: '50%',
marginLeft: mLeft
});
function isInt(n) {
return n % 1 === 0;
}
}
}]);
Here is how the modal is opened from the controller or directive:
modal.open({
content: $('#edit_story_' + story.id),
elem: $('#edit_story_' + story.id + '_container')
});
I also tried running my elem through the compiler first like so:
modal.open({
content: $compile($('#edit_story_' + story.id))($scope),
elem: $('#edit_story_' + story.id + '_container')
});
That solved my initial problem, but now after a few cycles my modal contents are duplicated. I get one form stacked upon another.
You shouldn't use DOM elements in controllers. A good idea would be implement a service following this approach or to make something like this. http://ionicframework.com/docs/api/service/$ionicModal/
So this question is not necessarily how to get it to work, because it does. But it is very very buggy. The problem I'm having is that when you scroll down, it sometimes takes a while to load so that the function reactivates or something. Either way the variable is reset and it loads like 5 pages in a row. So it's buggy. I have the code here:
var ldid = 10;
jQuery(
function ($) {
$('#allpostcontainer').bind('scroll', function () {
if ($(this).scrollTop() +
$(this).innerHeight() >= $(this)[0].scrollHeight) {
$("#allpostcontainer").append($("<div>").load("/streampage.php?id=" + ldid, function () {
ldid = ldid + 10;
}));
}
})
}
);
You can use a flag.
If it is loading you can set it to true.
If loading finished you set it back to false
and you make ajax request only if it is false.
var ldid = 10,
isPageLoading = false;
jQuery(
function ($) {
$('#allpostcontainer').bind('scroll', function () {
if ($(this).scrollTop() +
$(this).innerHeight() >= $(this)[0].scrollHeight && !isPageLoading) {
isPageLoading = true;
$("#allpostcontainer").append($("<div>").load("/streampage.php?id=" + ldid, function () {
ldid = ldid + 10;
isPageLoading = false;
}));
}
})
}
);
If you want to set your Div tag at the end of the "allpostcontainer" div then put below script in your page.
(#bottom is Div tag id which you need to display at the bottom. #allpostcontainer is div tag id which is main Div with scroll)
<script>
$(document).ready(function () {
$('#bottom').css('position', 'absolute');
$('#bottom').css('top', $('#allpostcontainer').height() - $('#bottom').height());
});
</script>
Please let me know if you have any query.
Thank you...
I am using this script from: http://pop.seaofclouds.com/
The problem is if you call the script multiple times it causes a cascading effect of a pop-out within a pop-out for as many times as you call the script.
I'm trying to figure out how to prevent it from executing when the popout has already been set. Here's the script:
//
// pop! for jQuery
// v0.2 requires jQuery v1.2 or later
//
// Licensed under the MIT:
// http://www.opensource.org/licenses/mit-license.php
//
// Copyright 2007,2008 SEAOFCLOUDS [http://seaofclouds.com]
//
(function($) {
$.pop = function(options){
// inject html wrapper
function initpops (){
$(".pop").each(function() {
var pop_classes = $(this).attr("class");
if ( $(this).find('.pop_menu').length) {
// do nothing
} else {
$(this).addClass("pop_menu");
$(this).wrap("<div class='"+pop_classes+"'></div>");
$(".pop_menu").attr("class", "pop_menu");
$(this).before(" \
<div class='pop_toggle'></div> \
");
}
});
}
initpops();
// assign reverse z-indexes to each pop
var totalpops = $(".pop").length + 100;
$(".pop").each(function(i) {
var popzindex = totalpops - i;
$(this).css({ zIndex: popzindex });
});
// close pops if user clicks outside of pop
activePop = null;
function closeInactivePop() {
$(".pop").each(function (i) {
if ($(this).hasClass('active') && i!=activePop) {
$(this).removeClass('active');
}
});
return false;
}
$(".pop").mouseover(function() { activePop = $(".pop").index(this); });
$(".pop").mouseout(function() { activePop = null; });
$("body").on("click", ".pop", function(){
closeInactivePop();
});
// toggle that pop
$("body").on("click", ".pop_toggle", function(){
$(this).parent(".pop").toggleClass("active");
});
}
})(jQuery);
now when i load this script on an ajax call the new pop-out menus work but the old ones do not react to the onclick event.
You shouldn't mess with the plugin. It works exactly like it should.
Better show us how you call this on elements that you already have.
Also I don't like this plugin. Better use something from JqueryUI
You can do such thing in much easier way.
[edit]
I tried your first code (the plugin) and it works correctly for me.
[edit]
OK. I get it. You call $.pop(); multiple times. You shouldn't! Calling $.pop(); will pin up the drop down menu to all elements that has class="pop". This is the reason why you have such funny stack.
Just use $.pop(); once.
Plugin doesn't give ability to connect NEW elements that was dynamically created on the page.
Removed pop from ajax call and just called this on success:
$(".pop").each(function() {
var pop_classes = $(this).attr("class");
if ( $(this).find('.pop_menu').length) {
// do nothing
} else {
$(this).addClass("pop_menu");
$(this).wrap("<div class='"+pop_classes+"'></div>");
$(".pop_menu").attr("class", "pop_menu");
$(this).before(" \
<div class='pop_toggle'></div> \
");
}
});
// assign reverse z-indexes to each pop
var totalpops = $(".pop").length + 100;
$(".pop").each(function(i) {
var popzindex = totalpops - i;
$(this).css({ zIndex: popzindex });
});
// close pops if user clicks outside of pop
activePop = null;
function closeInactivePop() {
$(".pop").each(function (i) {
if ($(this).hasClass('active') && i!=activePop) {
$(this).removeClass('active');
}
});
return false;
}
$(".pop").mouseover(function() { activePop = $(".pop").index(this); });
$(".pop").mouseout(function() { activePop = null; });
I'm fairly new to jQuery and I'm using the script below. Basically it uses two unordered lists to create tab functionality (one for tabs, one for content). Right now when you click through the tabs, the output is switched from "display:list-item;" to "display:none;". I'm trying to change this to "position:absolute;left:-10000px;" and "position:relative;left:0;" so that all the content gets rendered but just moves off the page rather than be hidden.
I'm having the issue you see at the bottom of the page here http://jqueryui.com/demos/tabs/ except it's not being controlled in the CSS. It's being controlled in the script below somehow that I'm unfamiliar with. Any help would be appreciated.
//INITIALIZATION
$.featureList(
$(".tabs li a"),
$(".output > li"), {
start_item : 0
}
);
//SCRIPT
(function($) {
$.fn.featureList = function(options) {
var tabs = $(this);
var output = $(options.output);
new jQuery.featureList(tabs, output, options);
return this;
};
$.featureList = function(tabs, output, options) {
function slide(nr) {
if (typeof nr == "undefined") {
nr = visible_item + 1;
nr = nr >= total_items ? 0 : nr;
}
tabs.removeClass('current').filter(":eq(" + nr + ")").addClass('current');
output.stop(true, true).filter(":visible").fadeOut();
output.filter(":eq(" + nr + ")").fadeIn(function() {
visible_item = nr;
});
}
var options = options || {};
var total_items = tabs.length;
var visible_item = options.start_item || 0;
options.pause_on_hover = options.pause_on_hover || true;
options.transition_interval = options.transition_interval || 0;
output.hide().eq( visible_item ).show();
tabs.eq( visible_item ).addClass('current');
tabs.click(function() {
if ($(this).hasClass('current')) {
return false;
}
slide( tabs.index( this) );
});
if (options.transition_interval > 0) {
var timer = setInterval(function () {
slide();
}, options.transition_interval);
if (options.pause_on_hover) {
tabs.mouseenter(function() {
clearInterval( timer );
}).mouseleave(function() {
clearInterval( timer );
timer = setInterval(function () {
slide();
}, options.transition_interval);
});
}
}
};
})(jQuery);
The action in that script is happening with .FadeIn and .Fadeout, which animate opacity. Fadeout applies display:none at the end of the opacity animation. Correspondingly, FadeIn only works on elements that are set to display:none. Fadein just won't work on visibility: hidden or opacity:0. Check out the jquery documentation, it's mostly pretty good.
So you want to substitute a css position change for those two lines of code. There are a bunch of different ways to do this, depending mostly on whether or not you want the elements to animate off the page of just leap there.
Also FYI The easiest way to share this sort of stuff for troubleshooting is to make a jsfiddle with a reduced subset of your code, just the relevant stuff, and then everybody can poke away at it until it works. :)