Tindercards.js

I wanted to create a similar experience to those cards that you can swipe left and right in Tinder, but with web technology. So I did. There are already 2 libs that do this but they’re based on Ionic which I didn’t want to have a dependency on. Tindercards.js only requires jQuery and Hammer.js.

The result looks like this:

Video demo

On YouTube: https://youtu.be/LqZ3wqvvZwE

Screenshot

Tindercards.js demo screenshot

Live Demo

Works best on iPhone: http://www.timo-ernst.net/misc/tindercardsjsdemo/

Dependencides

Tested on

  • iOS Safari

API Documentation

There are just two components that you need. A prototype object called Tindercardsjs.card and a method called Tindercardsjs.render. The signatures are like this:

/**
 * Representation of 1 card on the stack.
 * This is a prototype object! Initialize with "new" keyword
 *
 * @param {String} cardid Pass a unique id for each card so you know later which card is which
 * @param {String} name The name of the person on the card
 * @param {String} description The description text of that person
 * @param {String} imgpath The path to the img
 */
Tindercardsjs.card(cardid, name, description, imgpath)
 
/**
 * Renders the given stack into the given jQuery element.
 *
 * This is a method, just call it. Parameter "cards" must be an
 * array of Tindercardsjs.card
 *
 * @param {Array} cards An array of cards (@see Tindercardsjs.card)
 * @param {jQuery} target The target in which the stack should be rendered to
 * @param {function} onSwiped Callback function when swipe has occurred. Will pass an event object as parameter with properties event.cardid (the card id), event.card (The jQuery object that contains the card dom element) and event.direction ('left' or 'right').
 */
Tindercardsjs.render(cards, target, onSwiped)

How to use

  1. Make sure you have hammer.js und jQuery referenced
  2. Then, add tindercards.js from /lib
  3. Initialize like this:
var cards = [
  new Tindercardsjs.card(2, 'Geordi Laforge', 'I like big butts', 'gfx/pics/01.jpg'),
  new Tindercardsjs.card(1, 'Agro Picard', 'Hates Klingons, likes beer.', 'gfx/pics/02.jpg'),
  new Tindercardsjs.card(0, 'Jean-Luc, Worf & William', 'Swipe right if you also like funny hats like us :D', 'gfx/pics/03.jpg')
];

And pass them to Tindercards.js like this:

Tindercardsjs.render(cards, $('#main'), function (event) {
  console.log('Swiped ' + event.direction + ', cardid is ' + event.cardid + ' and target is:');
  console.log(event.card);
});

The stack will then be rendered to a HTML container that has id “main”. You can of course change that to some other name if you want.

Important

The html container (in this case #main) should have either position:absolute or position:relative!

Download lib & example code

Grab it on GitHub

How to hide the address bar on iPhone5 Safari browser

If you created a website with 100% height, you might encounter the problem that iPhone5 doesn’t hide the address bar while iPhone 4/4s and older do hide it.

Existing solutions

There are quite some JavaScript-based solutions on this issue that use scrollTop() and add a margin at the bottom of your page, e.g.:

That’s pretty complicated and I encountered the problem that this approach can lead to whitespace at the bottom of your page.

So I found a really way easier solution.

The better approach

Since you created a website with 100% height, I assume that you applied via css:

html,body{height:100%}

Now, for iPhone5 simply change this to:

html{height:504px}
body{height:100%}

This will tell Safari that your website is just 1px taller than the maximum visible part of your html document and the browser will automatically hide the address bar. That simple :-)

Warning!

Do not apply this to any other phone except for iPhone 5!

If you need to detect iPhone5, I recommend this script: Simple iPhone 5 detection with JavaScript

So you could do:

if (isIphone5()) $("html").css("height", "504px");
else $("html").css("height", "100%");
$("body").css("height", "100%");

Simple iPhone5 detection with JavaScript

It’s really simple, just use this function:

function isIphone5(){
	function iOSVersion(){
		var agent = window.navigator.userAgent,
		start = agent.indexOf( 'OS ' );
		if( (agent.indexOf( 'iPhone' ) > -1) && start > -1)
			return window.Number( agent.substr( start + 3, 3 ).replace( '_', '.' ) );
		else return 0;
	}
	return iOSVersion() >= 6 && window.devicePixelRatio >= 2 && screen.availHeight==548 ? true : false;
} 

Now simply call isIphone5() which will return true if:

  • The device is an iPhone
  • and if iOS version is at least 6
  • and if the device has a retina display
  • and if the screen has a height of 548px

These conditions (currently) only apply to iPhone5.

If the user is not on iPhone5 the method will return false.

Proper JavaScript OOP with inheritance for Java developers

Coming from a Java background, I really miss keywords like class or extends when I write JavaScript. Yes, I know. You can write OO-code in JavaScript but it’s really a mess using the prototype property. So I’ve been looking for a best practice for this for quite a while now. Reading through various tutorials I stumbled over some “hacks” (looked hackish to me at least) which never seemed to be really professional. Even the two JavaScript books I have here suggest two different ways of creating “class-like” constructs. However, after years of writing JavaScript now I think that I’ve found the best way to create class-like constructs including the idea of inheritance and overriding super methods which I would like to share with you.

I’ll demonstrate it with a simple

Example

Let’s say we’d wanted to create a class “Vehicle” and a subclasses “Car”. The class “Vehicle” should provide a method “bringMeTo(Location location)” which “Car” should inherit and override..

In Java it’d probably look something like this (not tested):

public class Vehicle{

  int topSpeed;

  public Vehicle(int topSpeed){
    this.topSpeed = topSpeed;
  }

  public void bringMeTo(Location location){
    // ... do what ever you want to do here
  }
}

public class Car extends Vehicle{

  public String manufacturer;
  public String color;

  public Car(int topSpeed, String manufacturer, String color){
    super(topSpeed);
    this.manufacturer = manufacturer;
    this.color = color;
  }

  @Override
  public void bringMeTo(Location location){
    // Use an engine and 4 wheels to get to location  
  }
}

Now in JavaScript

Let’s see how we can transform into JavaScript, shall we? :-)

1. Preparation

First you’ll need a little helper function from CoffeeScript. It’s very handy since there is no extends keyboard in JavaScript, so add this to the very top of your JS code. Dont’ worry if you don’t understand the code, it’ll simply do all the funky JS OOP magic for you. All you need to know is that this basically does what Java’s extends keyword would do in a similar way.

var __hasProp = {}.hasOwnProperty;
var __extends = function(child, parent){
  for(var key in parent){
    if (__hasProp.call(parent, key)) child[key] = parent[key];
  }
  function ctor(){
    this.constructor = child;
  }
  ctor.prototype = parent.prototype;
  child.prototype = new ctor();
  child.__super__ = parent.prototype;
  return child;
};

2. Class definition, inheritance and method overriding

After adding our __extends script, we’ll write our two classes. You’ll be surprised how simple, clean and a little Java-like this’ll look:

// Class Vehicle
var Vehicle = (function() {

  // Constructor
  function Vehicle(topSpeed) {
    this.topSpeed = topSpeed;
  }

  Vehicle.prototype.bringMeTo = function(location) {
    // doSomething(location);
  };

  return Vehicle;

})();

// Class Car
var Car = (function(_super) {
  __extends(Car, _super); // Cool, eh? :-)

  // Constructor
  function Car(topSpeed, manufacturer, color) {

    // Setup public properties
    this.manufacturer = manufacturer;
    this.color = color;

    // Call super constructor
    return Car.__super__.constructor.apply(this, arguments);
  }

  // Override super method
  Car.prototype.bringMeTo = function(location) {

    // Call super method if you want
    Car.__super__.bringMeTo.call(this, location);
		
    // doSomethingElse();
  };

  return Car;

})(Vehicle);

There you go. Really simple.

Create instances by calling:

var v = new Vehicle(30);
var c = new Car(200, "Jaguar", "white");

Final notes

  • In Car, you can access the super class anytime by just using Car.__super__.
  • Override methods by adding a new function to Car.prototype
  • Don’t forget to set all public properties you need within the constructor (as shown above).

That’s it. Happy coding.

ZK user group conference in Mannheim, Germany

I’ll be speaking on the upcoming ZK user group conference in Mannheim, Germany on December 6th, 2011 (what’s ZK?).

If you enjoy developing rich internet applications with the power of Java, I highly recommend to be there.
If you want to join, just sign up for the event on zkoss.org for free and see three exciting presentations including ones from ZK head Timothy Clare and me.
Also, this is a great opportunity to meet other ZK developers and share some ideas and latest news in the community.

As a little teaser, here is the title sheet for my presentation.