Question

I'm looking to implement similar functionality to Mailbox (http://www.mailboxapp.com/) where you can swipe an individual item within a list in order to action it, using Famous (http://famo.us).

I tried to add the 'Draggable' modifier to each list item, however it seems that you can't add modifiers to surfaces that are part of a Scrollview.

Anyone (from Famous or otherwise) know how I might do this?

Was it helpful?

Solution

Figured it out. In order to modifiers to surfaces inside a scrollview, they need to be wrapped in a RenderNode.

var Engine     = require("famous/core/Engine");
var Surface    = require("famous/core/Surface");
var Scrollview = require("famous/views/Scrollview");
var RenderNode = require('famous/core/RenderNode');
var Transform = require('famous/core/Transform');
var Draggable = require('famous/modifiers/Draggable');

var mainContext = Engine.createContext();

var scrollview = new Scrollview();
var surfaces = [];

scrollview.sequenceFrom(surfaces);

for (var i = 0, temp; i < 40; i++) {

    draggable = new Draggable( {
        xRange: [-220, 220],
        yRange: [0, 0],
    });

    item = new Surface({
         content: "Surface: " + (i + 1),
         size: [undefined, 200],
         properties: {
             backgroundColor: "hsl(" + (i * 360 / 40) + ", 100%, 50%)",
             lineHeight: "200px",
             textAlign: "center"
         }
    });

    node = new RenderNode(draggable)
    node.add(item);

    item.pipe(draggable);
    item.pipe(scrollview);
    surfaces.push(node);

}

mainContext.add(scrollview);

via @ (markmarijnissen) Famo.us Scrollview height)

OTHER TIPS

Explanation: In a Scrollview, the sequenceFrom method creates a ViewSequence from the array. As long as the items being added can return a getSize(), the rendering will work correctly. The RenderNode meets this criteria. You can also create a custom View because it extends RenderNode also.

Below is a code snippet that uses a custom View that allows the surface to drag and shows a response to the drag direction based on the final position criteria.

define('main', function(require, exports, module) {
  var Engine = require("famous/core/Engine");
  var Scrollview = require("famous/views/Scrollview");
  var DragView = require('DragView');

  var mainContext = Engine.createContext();

  var scrollview = new Scrollview();
  var views = [];

  scrollview.sequenceFrom(views);

  for (var i = 0; i < 40; i++) {

    var view = new DragView({
      size: [undefined, 200],
      content: "Surface: " + (i + 1),
      backgroundColor: "hsl(" + (i * 360 / 20) + ", 100%, 70%)"
    });

    view._eventOutput.pipe(scrollview);
    views.push(view);

  }

  mainContext.add(scrollview);
});

// Custom Drag View Item
define('DragView', function(require, exports, module) {
  var Surface = require("famous/core/Surface");
  var Scrollview = require("famous/views/Scrollview");
  var RenderNode = require('famous/core/RenderNode');
  var Modifier = require('famous/core/Modifier');
  var View = require('famous/core/View');
  var Transform = require('famous/core/Transform');
  var Draggable = require('famous/modifiers/Draggable');
  var TransitionableTransform = require('famous/transitions/TransitionableTransform');
  var RenderController = require('famous/views/RenderController');

  function _updatingDrag(e) {
    var pos = e.position;
    this.surface.setContent('Draggable Position is ' + pos);
  }

  function _endDrag(e) {
    var pos = e.position;
    this.surface.setContent('Draggable End Position is ' + pos);
    this.draggable.setPosition([0, 0], {
      duration: 300
    }, function() {
      this.renderer.hide();
    }.bind(this));

    if (pos[0] > 200) {
      console.log('showing OK');
      this.renderer.show(this.ok);
    }

    if (pos[0] < -200) {
      console.log('showing Not OK');
      this.renderer.show(this.not);
    }
  }

  function DragView() {
    View.apply(this, arguments);

    var draggable = new Draggable({
      xRange: [-220, 220],
      yRange: [0, 0],
    });

    var item = new Surface({
      content: this.options.content,
      size: [undefined, 200],
      properties: {
        backgroundColor: this.options.backgroundColor,
        lineHeight: "200px",
        textAlign: "center"
      }
    });

    var okItem = new Surface({
      content: String.fromCharCode(10004),
      size: [220, 200],
      properties: {
        color: "white",
        backgroundColor: "green",
        lineHeight: "200px",
        fontSize: "100px",
        textAlign: "center"
      }
    });
    var notOkItem = new Surface({
      content: String.fromCharCode(10006),
      size: [220, 200],
      properties: {
        color: "white",
        backgroundColor: "red",
        lineHeight: "200px",
        fontSize: "100px",
        textAlign: "center"
      }
    });

    var renderer = new RenderController();

    draggable.subscribe(item);

    draggable.on('update', _updatingDrag.bind({
      surface: item
    }));

    draggable.on('end', _endDrag.bind({
      surface: item,
      draggable: draggable,
      renderer: renderer,
      ok: okItem,
      not: notOkItem
    }));

    item.pipe(this._eventOutput);
    
    this.add(draggable).add(item)
    this.add(renderer);
  }

  DragView.prototype = Object.create(View.prototype);
  DragView.prototype.constructor = DragView;


  module.exports = DragView;
});

// Start Main App
require(['main']);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://requirejs.org/docs/release/2.1.16/minified/require.js"></script>
<script src="http://code.famo.us/lib/requestAnimationFrame.js"></script>
<script src="http://code.famo.us/lib/classList.js"></script>
<script src="http://code.famo.us/lib/functionPrototypeBind.js"></script>

<link rel="stylesheet" type="text/css" href="http://code.famo.us/famous/0.3.5/famous.css" />

<script src="http://code.famo.us/famous/0.3.5/famous.min.js"></script>

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top