What is the best pattern for responsive apps in famo.us
Asked Answered
H

2

8

By way of example, in a bootstrap based app I might write markup to make a grid be 8 columns wide for large screens and 2 columns wide for small.

Screen size certainly has an impact on screen design, and I want to know what is a decent pattern to follow before I start trying things in famo.us. Seeing as famo.us is 'opiniated', there should really only be one answer here :)

I'm all for mobile-first design, but what I don't want is a desktop app that is just a mobile app stretched by 400%.

Thanks,

Andrew

Heirdom answered 17/4, 2014 at 17:50 Comment(0)
C
6

Based on the example in the Famo.us Examples on Github..

https://github.com/Famous/examples/blob/master/src/examples/views/GridLayout/example.js

You could very easily do something like this..

var Engine     = require("famous/core/Engine");
var Surface    = require("famous/core/Surface");
var GridLayout = require("famous/views/GridLayout");

var mainContext = Engine.createContext();

var contextSize = mainContext.getSize()

var dimensions;

if (contextSize[0] < 480 || contextSize[1] < 480) {
    dimensions = [2,8];
} else {
    dimensions = [8,2];
};

var grid = new GridLayout({
    dimensions: dimensions
});

var surfaces = [];
grid.sequenceFrom(surfaces);

for(var i = 0; i < 16; i++) {
    surfaces.push(new Surface({
        content: "I am panel " + (i + 1),
        size: [undefined, contextSize[1] / 2.0],
        properties: {
            backgroundColor: "hsl(" + (i * 360 / 16) + ", 100%, 50%)",
            color: "black",
            lineHeight: window.innerHeight / 2 + 'px',
            textAlign: 'center'
        }
    }));
}

mainContext.add(grid);

EDIT:

Being that the end goal is Javascript as a sole development language for modern web applications.. Sometimes you just have to manage things yourself.

This is especially true for a framework like Famo.us, which is strongly dependent on absolute positioning.. Things just don't flow as smoothly as in the box model

To handle all the subtle differences I build a StateHash class that manages the state and returns different values for the same keys based on the current state..

var DESKTOP, MOBILE, StateHash, screen_state, sh;

StateHash = (function() {

  function StateHash(states) {
    this.set_state = __bind(this.set_state, this);

    this.get_state = __bind(this.get_state, this);

    this.set = __bind(this.set, this);

    this.get = __bind(this.get, this);

    var i, _i, _ref;
    if (!states) {
      states = 2;
    }
    this.state = 0;
    this.hash = {};
    for (i = _i = 0, _ref = states - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; i = 0 <= _ref ? ++_i : --_i) {
      this.hash[i] = {};
    }
  }

  StateHash.prototype.get = function(key) {
    return this.hash[this.state][key];
  };

  StateHash.prototype.set = function(state, key, val) {
    return this.hash[state][key] = val;
  };

  StateHash.prototype.get_state = function() {
    return this.state;
  };

  StateHash.prototype.set_state = function(state) {
    return this.state = state;
  };

  return StateHash;

})();

// Usage

MOBILE = 0;
DESKTOP = 1;

screen_state = some_check_mobile_function() ? MOBILE : DESKTOP;

sh = new StateHash();
sh.set_state(screen_state);

sh.set(MOBILE, "top-margin", "10px");
sh.set(DESKTOP, "top-margin", "20px");

sh.get("top-margin");

I will let you know if I learn of any other better way!

Good Luck!

Childbirth answered 17/4, 2014 at 18:10 Comment(3)
That's a neat example, thanks for sharing. It does address my example however I haven't marked it as the answer because I'm not sure including if statements throughout the code to switch on viewport size is a maintainable approach.Heirdom
@AndrewLeith That's fine, I would have used Modernizr of some other way to find out if the device was mobile only once, and then maintain only that variable.. Famo.us is supposed to relieve people of HTML and CSS, though each is still supported. I, for instance am using a grid layout to maintain margins between sequential content and being able to adjust the grid for mobile and desktop has been the easiest way for me. It allows you to not have to adjust every element manually yourself.Childbirth
A shortcoming of GridLayout is that all cells are evenly divided in size. E.g. An 8-wide 400px grid means each cell is 50px. No way to set one cell larger or smaller. As of now the only way to do that is to nest something like a FlexibleLayout in a GridLayout. Clutters up the code IMHO. It'd be convenient if the GridLayout could take column/row size parameters.Mook
F
2

The approach is improvised version of using grids based on window size. Just added a resize listener to observe resize events.

function ResponsiveGridView() {

    View.apply(this, arguments);

    this.rootModifier = new StateModifier({
        align: [.5, .5],
        origin: [.5, .5]
    });

    this.mainNode = this.add(this.rootModifier);

    this.slides = [];

    _createGrid.call(this);
    _createSlides.call(this);

    Engine.on('resize', function(){
        _reflowGrid.call(this);
    }.bind(this));
}
function _createGrid(){
    this.grid = new GridLayout({
         dimensions: window.innerWidth < 490?[1,8]:[4, 2],
         transition: {curve: 'easeInOut',duration: 200}
        });
    this.grid.sequenceFrom(this.slides);
    this.mainNode.add(this.grid);
}
function _reflowGrid(){
    this.grid.setOptions({dimensions: window.innerWidth < 490?[1,8]:[4, 2]});
}
Finally answered 18/9, 2014 at 11:22 Comment(1)
This is exactly what I was looking for. A dynamic way to re-layout on the fly when orientation changes. Thanks!Discompose

© 2022 - 2024 — McMap. All rights reserved.