AngularJS - Bind to Scroll (Mousewheel, Dragging Bar, and Touch Swiping) - javascript

I made a very shabby "Infinite-Scroll" directive, all other solutions were incompatible with a md-grid-list so I went ahead and made my own alternative workaround.
app.directive('scrollTrigger', function($window) {
return {
link : function(scope, element, attrs) {
var e = angular.element(element[0]);
e.bind('mousewheel', function() {
var parent = e.offsetParent()[0];
if (parent.scrollTop + parent.offsetHeight > (70/100*parent.scrollHeight)) {
scope.$apply(attrs.scrollTrigger);
}
});
}
};
});
You simply put scroll-trigger on the html element that will be scrollable. The code checks if it has been scrolled to atleast 70% down, if it has, then it will trigger whatevers called on the scroll-trigger, for example: scroll-trigger="loadMore()"
This works fine but it ONLY works if you use the Mousewheel, but what if users without a mousewheel try using my website? They cant continue loading more items.
The ways that dont work are:
Manually dragging the scrollbar
Swiping/Dragging Up/Down on a Touch Device
Working ways:
Using the Mousewheel
And yes, I do know why, im only binding with e.bind('mousewheel') this is because "scroll" wouldnt actually work for me at all.
So im kinda unsure where to go from here.

Related

What is the correct way to watch an element's height in AngularJS 1.4.8?

I realize that there are SO posts out there asking similar or even the same thing, but before you mash the duplicate button, be aware I have tried the solution from every single one, and none of them have worked in my target AngularJS version (1.4.8). With that in mind:
HTML:
<div ng-app="app" ng-controller="app">
<textarea size-watch>{{ height }}</textarea>
</div>
JavaScript:
angular.module("app", [])
.controller("app", function() {
})
.directive("sizeWatch", function() {
return {
restrict: "A",
link: function(scope, elem) {
scope.$watch(function() { return elem[0].offsetHeight; }, function(newHeight, oldHeight) {
scope.height = newHeight;
}, true);
}
}
});
Fiddle.
Here's what I'm trying to do: I want to create a directive that watches the height of an element and updates a property on the scope whenever it changes. I can get the value to initially display, so I know the link between the directive and the controller/scope is working. However, I can't get the value to update when the textarea is resized (by dragging the bottom right corner). I put a call to debugger; in the second watch function, and verified that it's only getting called once.
Feel free to update the linked fiddle when you find a working solution.
My choice of element for testing purposes was unfortunate. Apparently textarea doesn't raise resize events the same way as other elements (specifically, like divs). Here's a working fiddle of what I was trying to achieve.

Destroying InfiniteScroll on AJAX page change

We have a website that is running jQuery Infinite Scroll Plugin. The plugin is no longer maintained but it is the only one that really serves our purpose properly. However, the problem I have is that our site is ajax based. On page change the pg-changed trigger is fired against the window, which allows us to check if the Infinite Scroll container is there and enable Infinite Scroll. If the Infinite Scroll container isn't there but $.infscr exists, we will attempt to destroy the previous instance.
The problem I am having is that when changing to another page, it doesn't seem to be getting destroyed properly and sometimes AJAX calls will be made, along with the infscr loading bar displaying. Here is the code I am using to instantiate and destroy the plugin:
$(window).on('pg-changed', function () {
// delete our infinite scroll
if(typeof $.infscr !== 'undefined') {
$('.snap-inner, .infscr').data('infinitescroll', null);
$('.snap-inner, .infscr').infinitescroll('unbind');
$('.snap-inner, .infscr').infinitescroll('destroy');
$('#infscr-loading').remove();
$.infscr.data('infinitescroll', null);
$.infscr.infinitescroll('unbind');
$.infscr.infinitescroll('destroy');
delete $.infscr;
}
// setup our infinite scroll
if($('.infscr').length) {
$.infscr = $('.infscr').infinitescroll({
// define our navigation selectors
navSelector : 'div.infscr-navigation',
nextSelector : 'div.infscr-navigation A:first',
itemSelector : '.infscr-item',
// allow scrolling an overflowed element
behavior : 'local',
bufferPx : 120,
binder : $('.snap-inner'),
dataType : 'html',
loading : {
msg : null,
selector : '.snap-content',
img : 'data:image/gif;base64,TRIMMED',
msgText : '<span class="infscr-loading">Loading...</span>',
}
}, function (arrayOfNewElems) {
// render background images on our new elements
$(this).renderBgImages();
});
}
});
I really hope you can help with this as it has become quite a problem now, firing on scroll, making AJAX calls and displaying the loading bar.
I guess the problem might be that the plugin binds events on elements external to itself. It's hard to say without further debugging (is the plugin deleted or does it fail to do so?). If it does, why would it fail to unbind the events? etc.
When you say, 'on another page', I suppose you are not loading a whole new page (which would 'reset' the javascript.
Though, depending on wether this could work for you, you might want to try unbinding ALL events on the document, and starting fresh.
$(document).add('*').off();
should do so. If it does, you could try to pinpoint what elements/events you need to unbind manually. Let me know if this works or not.

Topcoat Side Menu on swipe

So I'm working on a phonegap app using topcoat and implemented a fly out menu as seen here. I'm using this script to open/close the menu
$(function () {
var slideMenuButton = document.getElementById('slide-menu-button');
slideMenuButton.onclick = function (e) {
var cl = document.body.classList;
if (cl.contains('left-nav')) {
cl.remove('left-nav');
} else {
cl.add('left-nav');
}
};
});
Now everything is working fine but what I want to add on is the ability to swipe to close the panel and to open it as well. I've seen touch library for jquery that seem to offer a solution (such as TouchSwipe) but I want to try to get this as close as possible to a 1:1 touch movement interaction.
Anyone have an idea on what direction I should go in to get this going or have any ideas? Any help is appreciated.
Found this and with some renaming of classes, I got a touch slide out menu that works how I want. Its called Bamboo.js
Here's a demo of it

Liquid Slider (Link to another page at end of scroll, rather than scroll back to first tab?) jQuery

jQuery / Javascript / PHP
I am using the Liquid Slider as a pagination mechanism on a website, how I use it is I basically have it smoothly scroll through the pages left-right & vice versa.
What I'm trying to accomplish right now is: to have the dynamic arrows link to an external page at the end of the scroll (once it detects it is at its last page/tab), rather than to have it scroll back to where it first began.
Since such option variety is not originally supported from the author website, I am wondering if anyone from here would have an idea how to accomplish this?
A snippet of my dynamic arrows with their callback functions (functions not included):
$('#slider-id').liquidSlider({
continuous:false,
dynamicArrows:true,
dynamicTabs: false,
callbackFunction: function(){ drawLines() }
});
$('.liquid-nav-right-arrow').click(function(){
simRefresh(), simRefresh2();
});
$('.liquid-nav-left-arrow').click(function(){
simRefresh(), simRefresh2();
});
You can set conditionals based on the current panel (tab).
callbackFunction: function () {
var sliderObject = $.data( $('#slider-id)[0], 'liquidSlider');
if ( (sliderObject).currentTab === 4 ) {
//turn off click event
//update link
}
Then if you want to reset the events again, you can try sliderObject.registerArrows(), although I haven't tested this out.

appcelerator orientationchange navbar image hide / show

I'm building an app with some tabs for the iPhone.
rephrased the question in the appcelerator website here
When i change from portrait to landscape i want to hide the navbar.
it works fine if i don't switch to another tab.
But when i view 1 tab in portrait,
switch to another tab, change to landscape view,
switch back to the first tab,
and then change to back portrait
the navbar (window.barImage) is all stretched out ( to the size of a landscape navBar )
Also when i remove all my code for hiding the navbar the same problem occurs.
I've tried setting the barImage again on orientationchange but that does not help either.
a site note: I'm using the same image on every tab for the navBar could that be the problem?
I marked in green the navbar image, the blue part is where the image normally should be.
Also note that the image is the right size for a portrait view of the navbar.
code:
var windowWidth = Ti.Platform.displayCaps.platformWidth;
var catWin = Ti.UI.createWindow({
title:'',
barImage: 'images/barImage.png',
url:'vacancies/categories.js',
width: windowWidth
});
catWin.orientationModes = [
Titanium.UI.PORTRAIT,
Titanium.UI.LANDSCAPE_LEFT,
Titanium.UI.LANDSCAPE_RIGHT
];
Titanium.Gesture.addEventListener('orientationchange', function(e) {
if(e.orientation == Titanium.UI.LANDSCAPE_RIGHT){
catWin.hideNavBar();
} else if(e.orientation == Titanium.UI.LANDSCAPE_LEFT){
catWin.hideNavBar();
} else if(e.orientation == Titanium.UI.PORTRAIT){
catWin.showNavBar();
}
});
You really need to post more code, for example I have no idea if you are using Ti.UI.currentWindow.hideNavBar(); or if you are using just the .hide(); and .show();?
From what I can tell you're problem however possibly lies with the the width. Trying setting it to '100%' instead of using the platformWidth. Once again without all the relevant code such as your orientationchange event this is best advice I can give. Hope it helps.
THIRD COMMENT: possibly
Titanium.Gesture.addEventListener('orientationchange', function(e) {
if(e.source.isLandscape()){
catWin.hideNavBar();
} else {
catWin.barImage = 'images/barImage.png';
catWin.showNavBar();
}
});
Just somewhere in there or the tab events. I would play around with that idea and see if it gets you any further?
While this is not the best solution because it still looks a bit odd ( but way better then before, ) this is the best solution until now.
I have found some kind of solution by using the following code:
I've set the barImage in the createWindow code so at least at the beginning it looks OK:
var jbWin = Ti.UI.createWindow({
title: '',
url:'homePage.js',
barImage: 'images/jobbroker_bar.png'
});
Then on orientationchange I unset the barImage and start using the titleImage:
Titanium.Gesture.addEventListener('orientationchange', function(e){
if(e.source.isLandscape()){
catWin.titleImage = '';
catWin.barImage = '';
catWin.hideNavBar();
else if( e.orientation != Ti.UI.FACE_UP && e.orientation != Ti.UI.FACE_DOWN ) {
catWin.titleImage = 'images/jobbroker_bar.png';
catWin.showNavBar();
}
}
have you tried using the "titleControl" on the Navbar to set the image instead of the barImage control?
also can you post a small apps.js file with the associated image somewhere? it is difficult to full grasp the problem without running the project

Categories

Resources