How to lazy load images in Framework7 with AngularJS

So, you’re using Framework7 with Angular and you enabled lazy load feature as described in the docs but it doesn’t work, eh? :)

Well, that’s no wonder if you bound the image url’s via data binding like this:

<img data-src="{{imgurl}}" class="lazy">
 
<script>
  angularApp.controller('controller', ['$scope',
    function ($scope) {
      $scope.imgurl = 'http://path.to/my/image.jpg';
    }
  ]);
</script>

The reason for this is that the url to the image is not set as plain text in the data-src attribute. Instead, it is bound via Angular to a javascript variable. The problem here is that F7 does not know this and tries to set the string ‘{{imgurl}}’ as the url to the image which of course doesn’t work.

The solution to fix lazy load

So, the solution to this is to let Angular handle lazy load of images instead of using F7’s built-in mechanism. To do this you need to download an additional module for Angular. This one did a good job for me: https://github.com/Pentiado/angular-lazy-img

1) Add it to your project:

<script type="text/javascript" src="lib/angular-lazy-img/angular-lazy-img.js"></script>

2) Then, import the module into your app:

var angularApp = angular.module('angularApp', ['angularLazyImg']);

3) As a next step, modify the html img tag (use lazy-img attribute instead of data-src and also remove “lazy” class):

<img lazy-img="{{imgurl}}">

4) Lastly, you need to check if a user has scrolled and then trigger lazy load feature. So, in your controller do this:

Dom7('.page-content').on("scroll", function () {
  $rootScope.$emit('lazyImg:refresh');
});

That’s pretty much it.

Demo app

Happy coding.

Should I use Angular’s ngRouter in Framework7?

TL;DR

No, you shouldn’t use ngRouter with Framework7. Use ajax pages and set pushState:true instead!


I’m getting quite a lot of questions regarding the implementation of navigation in Framework7 apps with Angular.js. How do I use ajax pages with Angular? Does ngRouter work with F7? How can I get the back button in the browser to work in F7? And so on…

Best practice for ngRouter with F7

I don’t know if there is something like a "best practice" but so far for me it seems like it’s best to let F7 handle navigation as well as content integration. Mixing ngRouter with F7’s navigation system does not work well. There is no real point in using ngRouter anyway. Framework7 does an excellent job of fetching content via ajax pages and display the data at the right spot. You might want to enable the browser’s back button capability though by setting this option when initializing your app:

var myApp = new Framework7({
  pushState: true
});

Learn more about Ajax Pages with Angular

How to use ajax pages with Angular 1.x in Framework7

Since my last screencast about how to use F7 with Angular the most asked question that I got was about ajax pages, something like this:

"In your example you have all your pages in one html file but what if I separated each page into its own file using Framework7’s ajax pages mechanism? (read F7 docs about ajax pages).
If I use it, all the bindings from Angular do not work anymore. How do I fix this, oh mighty Timo?"

(Minor quote inaccuracies might be included)

Well, the problem here is that Framework7 will get each page via ajax (when a link that points to it is clicked) and then inject it into the DOM. Angular does not know anything about this and thus will not update any bindings. Luckily, there is an easy fix for this.

The solution to ajax pages with Angular

When you inject a new HTML snippet into the DOM via Ajax pages, you simply do:

$compile(snippet)($scope);
$scope.$apply();

(See demo source code for an example how to use this)

This will recompile the HTML snippet that got added and then apply the changes and BOOOOM, that’s it.

Note: You don’t want to do this to often as it affects performance quite a bit.

Demo

I also created a quick demo for you to check this out. In order to work you must serve it via http protocol from a web server like Apache or NGINX. Just double-clicking the index.html file and serving it via file:/// will not work because you cannot do ajax calls via file:///.

Get the demo on: Github

Video Screencast: How to use Framework7 with AngularJS

After posting my experiment of using Framework7 with TypeScript and Angular I get quite some questions from people on how to properly use F7 with Angular, so I made a quick screencast:

How to use Framework7 with AngularJS

About using ajax pages

If you use Framework7’s ajax pages mechanism read my blog post about this and how to get this working with Angular.

Should you use Angular UI router with Framework 7?

If you want to find the answer to this, check out this blog post: Should I use Angular’s ngRouter in Framework7?

Links

How to scroll up by tapping status bar in Cordova/PhoneGap

Holy, moly! This issue has been chasing me for more than 3 years! I’ve always been a passionate Cordova/PhoneGap developer, even if many people don’t like it: I personally think it’s not a bad platform if you got experience and you know what you’re doing.

However, since apps built with Cordova/PhoneGap completely rely on webkit and html, scrolling usually feels a little slow which is the reason why many people use a trick: They blow up a div element to 100% width and height and use -webkit-overflow-scrolling:touch to get smooth momentum scrolling within the div.

Now, this works pretty good but the tradeoff is that you loose the ability to easily scroll up in your app by simply tapping the status bar on the top of the screen in iOS. This is a big usability issue and needs to be fixed imho.

So, here’s the fix:

First, you need to install this plugin: cordova-plugin-statusbar
You can do so by simply opening terminal, cd to your project folder an run:

cordova plugin add cordova-plugin-statusbar

This plugin will fire an event when status bar is tapped. You need to listen to this event in JavaScript:

document.addEventListener("deviceready", function () {
    window.addEventListener("statusTap", function () {
        scrollUp(); // Now, let's implement this, shall we? :D
    });
}, false);

You’re almost there! You only need to programmatically scroll up your container. Let’s assume the container you’re scrolling on and which you applied -webkit-overflow-scrolling:touch on has id “wrapper“.

<div id="wrapper">
    Lots of stuff here to scroll..
</div>

So what you want to do is:

var isScrollingUp = false,
    scrollTime = 700; // Adjust scroll speed here. Lower = faster. Higher = slower.
 
function scrollUp () {
    if (!isScrollingUp){
        var $curpage = $('#wrapper'),
            curpage = $curpage.get(0);
        curpage.style.overflow = 'hidden';
        isScrollingUp = true;
        $curpage.animate({scrollTop: 0}, scrollTime);
        setTimeout(function () {
            isScrollingUp = false;
        }, scrollTime + 1);
        $timeout(function () {
            curpage.style.overflow = '';
        }, 10);
    }
}

I know the code ain’t pretty because of all the weird timeout stuff but it magically just works.

Important

I stripped this code snipped off a project of mine and had to do some modifications for this blog post, so I don’t know if everything still works, so please let me know if this did work for you or not.

Why I am still in love with Framework7

Disclaimler: First of all, let me state clear that I am not involved into the Framework7 project. I am not getting paid for this post. This is just my honest, personal opinion as a mobile developer.

Early steps

The first framework I used when I started mobile development was jQueryMobile. I was used to jQuery coming from Desktop programming so I thought: “Hey, it says jQuery, so I guess it must be good”. It sucked balls, just like any other Framework I tried like KendoUI, SenchaTouch or Ionic. They either sucked regarding performance, sucked about look & feel or simply sucked monkey ass ballz! Excuse me for my language but for years I couldn’t believe that it was true that there is no HTML5-framework that can deliver anything close to a native app, so I always believed that it simply wasn’t possible.

And then I discovered Framework7

Oh, boy was I blown away when I saw the first demos for iOS on their website. This was just what I was looking for. The way these apps looked, feeled and performed was 99.9% accurate to what I am used from native apps. I couldn’t believe it and so I tipped my first steps in. I quickly found out that Framework7 was not only easy to use, it just worked™. You create a few lines of HTML markup and boom, that’s it. Framework7 will take care of the rest. The looks, the page transitions all works out of the box. I couldn’t believe it and why hadn’t I heard about it before? I don’t know but since they also released a new Material Design option for Android I am absolutely convinced: This is it. The best framework you could possibly use for mobile app development with HTML5, CSS3 and JavaScript. Throw that all into a PhoneGap/Cordova container and you should be fine.

Screenshot

framework7 demo screenshot

Demos

For iPhone open this.
On Android open this.

The future

The biggest problem I see with Framework7 is that it doesn’t get enough attention. For years I didn’t hear anything about it and when I talk to other devs they never saw it before until I show em and they’re all completely blown away.

Also, if you search for “best html5 mobile framework” on Google you will get shitloads of so called comparison websites like “Top 10 mobile frameworks” and barely I see F7 mentioned or even find their main website in the search results. So, if you like F7 and you’d like to support, go tweet about it right now!

I just hope that developers haven’t given up on HTML5 for apps yet. Since the hype of Facebook’s React framework many people seem to transition there.

Oh, boy I need to go back coding. This is so much fun <3

How to set user agent for file_get_html() in dom.php

The problem with file_get_html ()

I really like the Simple HTML DOM Parser for PHP cause of its simplicity but today I encountered the problem of grabbing different HTML for different devices, so I checked the docs but couldn’t find any option how to do it.

So, I dugg into the lib code myself, ready for some manual patching, when I found out that there is actually a way to do this the proper way.

The solution

Let’s assume, you open a connection like this:

$html = file_get_html ($url);

In order to set a user agent for iPhone 5 for example, simply do this:

$opts = array(
  'http'=>array(
    'header'=>"User-Agent:Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53\r\n"
  )
);
 
$context = stream_context_create($opts);
$html = file_get_html($url, false, $context);

As you can see, you can even set more headers if you want.

Damn, that was easy, wasn’t it? :-)

How to add dots every 3 digits in currency values with JavaScript

If you’re European like me, you’re probably used to this notation:
€ 366.432 instead of 366,432 or 366432.
In order to get this done in JavaScript you want to do the following:

// Number
var money = 366432;
 
// Convert to String and add dots every 3 digits
var moneyDots = money.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1.");
 
// Set in HTML
$('.anywhere').text('€ ' + moneyDots);

Keep in mind that moneyDots is a String from now on! It’s not a number anymore!

Upscroller for Framework7

Wait! Read this first!

There is a better, more generic solution described here: How to scroll up by tapping status bar in Cordova/PhoneGap apps on iOS

If you still want to checkout the Upscroller plugin, feel free to read on :-)

Plugin description

I created a tiny little plugin for Framework7 that fixes the problem that users cannot scroll up a large list by simply tapping the top of the screen. To work around this, my plugin checks if the user has scrolled down a bit and then displays a nice looking blue button at the top of the screen which let the user scroll up with a cool looking slide animation.

Demo

Check out the demo here.

Download

Grab the plugin on Github if you like.

Screenshot

Upscroller Screenshot

How to fix getting stuck when scrolling up in Framework7

The problem in Framework7

In most webapps for iOS (not only Framework7) that use -webkit-overflow-scrolling:touch for scrolling within elements instead of the whole body you will experience the following issue:

You scroll up to the very top of the document and then you scroll down immediately when you get the bounce back. You will notice that you’re stuck. The only way to escape from this is to release the screen, wait 1-2 seconds and then scroll.

The solution

So, here is the magic fix for you:

$scroller = $(".page-content");
$scroller.each(function (i, el) {
  var $scrollContainer = $(el);
  $scrollContainer.bind('touchstart', function (ev) {
	var $this = $(this),
	  scroller = $scrollContainer.get(0),
	  scrollTop,
	  scrollHeight,
	  offsetHeight,
	  contentHeight;
 
	if ($this.scrollTop() === 0) {
	  $this.scrollTop(1);
	}
	scrollTop = scroller.scrollTop;
	scrollHeight = scroller.scrollHeight;
	offsetHeight = scroller.offsetHeight;
	contentHeight = scrollHeight - offsetHeight;
	if (contentHeight === scrollTop) {
	  $this.scrollTop(scrollTop - 1);
	}
  });
});