Chart.js how to rewrite x for webAPP - chart.js

I use chart.js for a webApp, but it is not I want.
How to rewrite this x axle or I should change other js to draw chart,demo:

You could extend the chart to remove the points that you don't need from the x-axis, like so (adapted from https://stackoverflow.com/a/31606933/360067)
Chart.types.Line.extend({
name: "LineAlt",
initialize: function (data) {
Chart.types.Line.prototype.initialize.apply(this, arguments);
if (this.options.every) {
var every = this.options.every;
var xLabels = this.scale.xLabels
xLabels.forEach(function (label, i) {
if (i % every !== 0)
xLabels[i] = '';
})
}
}
});
and you call it like so
var ctx = document.getElementById("chart").getContext("2d");
var myLineChart = new Chart(ctx).LineAlt(data, {
every: 3
});
Adjust every to 2, 3,... to show one in every 2, every 3,... points.
Fiddle - http://jsfiddle.net/3p2ekjyn/

Related

Chart.JS Vertical Line with Moment.JS Horizontal Axis

Is there a way to create vertical lines (event lines, phase changes) using Chart.JS 2.0?
I've seen some examples online (see this related question), HOWEVER, when using Moment.js to create the horizontal axis, it is not possible to give LineAtIndex a moment.js date to create a line at that date.
var originalLineDraw = Chart.controllers.line.prototype.draw;
Chart.helpers.extend(Chart.controllers.line.prototype, {
draw: function() {
originalLineDraw.apply(this, arguments);
var chart = this.chart;
var ctx = chart.chart.ctx;
var index = chart.config.data.lineAtIndex;
if (index) {
var xaxis = chart.scales['x-axis-0'];
var yaxis = chart.scales['y-axis-0'];
ctx.save();
ctx.beginPath();
ctx.moveTo(xaxis.getPixelForValue(undefined, index), yaxis.top);
ctx.strokeStyle = '#ff0000';
ctx.lineTo(xaxis.getPixelForValue(undefined, index), yaxis.bottom);
ctx.stroke();
ctx.restore();
}
}
});
Here's a fiddle demonstrating the problem:
https://jsfiddle.net/harblz/0am8vehg/
I believe my issue is that I don't properly understand this bit of code:
var xaxis = chart.scales['x-axis-0'];
var yaxis = chart.scales['y-axis-0'];
If I am able to figure this out, I'll post a working fiddle here for any future users tackling the same project.
Thanks you for your time reading this :)
I tried multiple plugins, but none could handle Charts with cartesian axes of type time. My rather simple solution:
First register the chart plugin globally:
Chart.plugins.register({
drawLine: function (chart, xValue, color = 'rgba(87,86,86,0.2)') {
const canvas = chart.chart
const context = canvas.ctx
context.beginPath()
context.moveTo(xValue, 6) // top
context.lineTo(xValue, canvas.height - 73) // bottom
context.strokeStyle = color
context.stroke()
},
afterDraw: function (chart) {
const xScale = chart.scales['x-axis-0']
if (chart.options.verticalLine) {
chart.options.verticalLine.forEach((line) => {
const xValue = xScale.getPixelForValue(line)
if (xValue) {
this.drawLine(chart, xValue)
}
})
}
}
})
Then add verticalLine Array to your chart definition:
options: {
scales: { xAxes: [{ type: 'time' }] },
verticalLine: ['2019-04-1', '2019-07-01', '2019-10-01'],
}

how to implement mobile design hamburger side menu with famous?

What's the best way with Famous to implement these well known mobile app design patterns?
!) "hamburger" and side-menu like this jasny example ?
2 )Table-View, transitioning to full-screen details page, a little like:
http://goratchet.com/examples/app-movies/
Thanks!
You should be aware that the famo.us university timbre menu lesson is now available. Here is a version I did long before that came out. It is more of the one file here are the critical issues implementations than the 27 class version. Following this I did eventually produce an abstraction of the menu into a generalized tool. There is actually very little difference between the menu below and a standard (one level deep) menu with the exception of what transitions you use. Here is a drag-to-uncover menu. You could of course trigger the open and/or close with a click as well... you can also see the code and play it live at codefamo.us.
/*globals define*/
define(function(require, exports, module) {
'use strict';
// import dependencies
var Engine = require('famous/core/Engine');
var Surface = require('famous/core/Surface');
var Transform = require('famous/core/Transform');
var StateModifier = require('famous/modifiers/StateModifier');
var Easing = require('famous/transitions/Easing');
var ContainerSurface = require('famous/surfaces/ContainerSurface');
var EventHandler = require('famous/core/EventHandler');
var MouseSync = require('famous/inputs/MouseSync');
var TouchSync = require('famous/inputs/TouchSync');
var Draggable = require('famous/modifiers/Draggable');
var mainContext = Engine.createContext();
// Content Page...
var coverState = true;
var coverPos = 0;
//var coverMod = new StateModifier();
var coverDrag = new Draggable({
projection: 'x'
});
var coverSurface = new Surface({
size:[undefined,undefined],
content:'click to open',
properties:{
color:'white',
backgroundColor:'#44f',
zIndex:'3'
}
});
//mainContext.add(coverMod).add(coverDrag).add(coverSurface);
mainContext.add(coverDrag).add(coverSurface);
coverDrag.activate();
function coverReset() {
coverDrag.setPosition([0,0],
{ duration : 100, curve: 'easeInOut' },
function() {
coverSurface.setContent('drag to open');
coverPos = 0;
}
);
coverState = true;
}
function coverDrawOut() {
coverDrag.setPosition([200,0],
{ duration : 600, curve: 'easeInOut' },
function() {
coverSurface.setContent('drag to close');
coverPos = 200;
}
);
coverState=false;
}
coverDrag.on('update',function(data) {
//console.log(data);
if(data.position[0]>60) {
menuFadeIn();
}
});
coverDrag.on('end',function(data) {
if(data.position[0]<100) {
coverReset();
menuFadeOut();
}else {
coverDrawOut();
menuFadeIn();
}
});
coverSurface.pipe(coverDrag);
// Menu Items...
var todaysSpecials = ['pizza','hamburger','french fries','ice cream'];
var itemSurfs = [];
var itemMod1 = [];
var itemMod2 = [];
// Create menu item surfaces, modifiers, etc.
for (var i=0;i<todaysSpecials.length;i++) {
itemSurfs[i] = new Surface({
size: [150, 30],
content: '<span class="entypo">☰</span>'+todaysSpecials[i],
properties: {
color: 'white',
textAlign: 'center',
backgroundColor: '#FA5C4F',
zIndex:'1'
}
});
itemSurfs[i].menuData = {
id:i,
text: todaysSpecials[i]
};
//console.log(itemSurfs[i]);
itemMod1[i] = new StateModifier();
itemMod2[i] = new StateModifier();
mainContext.add(itemMod1[i]).add(itemMod2[i]).add(itemSurfs[i]);
itemSurfs[i].on('click',function(mouseEventArgs){
alert('Buy some really good '+mouseEventArgs.origin.menuData.text);
});
};
var menuState=true;
// make menu go away
function menuFadeOut() {
if(menuState) {
for (var i=0;i<todaysSpecials.length;i++) {
itemMod1[i].setTransform(Transform.translate(-150, 200+i*40, 0));
itemMod2[i].setTransform(Transform.rotateZ(-Math.PI/5.5));
}
menuState=false;
}
}
// bring menu in
function menuFadeIn() {
if(!menuState) {
for (var i=0;i<todaysSpecials.length;i++) {
itemMod1[i].setTransform(Transform.translate(0,100+i*40, -1),{ duration : 300+i*200, curve: 'easeInOut' });
itemMod2[i].setTransform(Transform.rotateZ(-Math.PI/5.5));
}
menuState=true;
}
}
// app initial conditions...
coverReset();
menuFadeOut();
});

How to implement Slide to delete in Famo.us with proper event handling

I'm trying to implement a slide to delete. As part of that I have a layer with opacity set to 0 the idea being I'm trying to set several if clauses to gradual change the opacity of the surface so that the word Delete gentle appears as you slide it to the left. At this point I just have it switching at 10pixels for testing. The functions fire but the opacity doesn't change. I think it has something to do with not being piped/event handling being done properly on my part. Any Ideas?
var SnapTransition = require("famous/transitions/SnapTransition");
Transitionable.registerMethod('snap', SnapTransition);
var CSS = require("css/recentActivityCSS");
var Ctrl = require("controllers/recentActivityCtrl");
var homeContentWrap = new Scrollview();
var recentActivities = [];
var ContainerSize = [undefined, 100];
homeContentWrap.sequenceFrom(recentActivities);
for (var i = 0; i < Ctrl.recentActivityList.length; i++) {
var recentActivitiesContainer = new ContainerSurface({
size: ContainerSize,
properties: CSS.recentActivitiesContainer,
});
var redLayer = new Surface({
size: ContainerSize,
content: 'DELETE',
properties: CSS.redLayer,
});
var draggable = new Draggable({
xRange: [-120, 5],
yRange: [0, 0],
});
var textContainer = new ContainerSurface({
size: ContainerSize,
properties: CSS.textContainer,
});
var mod = new Modifier({});
node = new RenderNode(draggable);
node.add(mod).add(textContainer);
textContainer.pipe(draggable);
textContainer.pipe(homeContentWrap);
var opacityMod = new StateModifier({
opacity: 0
});
recentActivitiesContainer.add(node);
recentActivitiesContainer.add(opacityMod).add(redLayer);
recentActivities.push(recentActivitiesContainer);
var trans = {
method: 'snap',
period: 100,
dampingRatio: 0.3,
velocity: 5
};
draggable.on('start', function() {});
draggable.on('update', function() {
var position = this.getPosition();
if (position[0] > (-10)) {
opacityMod.halt();
opacityMod.setOpacity(0, { curve: 'easeOut', duration: 10 });
} else {
opacityMod.halt();
opacityMod.setOpacity(1, { curve: 'easeOut', duration: 10 });
}
});
draggable.on('end', function(){
var position = this.getPosition();
if (position[0] < (-100)) {
alert('delete');
}
this.setPosition([0,0,0], trans);
});
There are a couple of things I did to the draggable 'update' function to achieve what you have described.
1) You need to bind objects to your update function or else you have no real reference to them. When you use opacityMod in your 'update' function, you only alter the last cells opacityMod. Since binding will change the meaning of 'this', I also bind draggable.
2) You say you want a gradual fade. This approach is not going to give you anything gradual. You need to take the position of the draggable and calculate an opacity based on that value. To start, I declare two new variables for fadeStart and fadeEnd, that represent the positions of the draggable X position 0 and 1 opacity respectively.
Also you probably do not need the transition in your setOpacity, but I kept it in anyway.
Here is the updated 'update' function.. Good Luck!
fadeStart = -10;
fadeEnd = -100;
draggable.on('update', function() {
var draggable = this[0];
var opacityMod = this[1];
var position = draggable.getPosition();
if ( position[0] > fadeStart ) {
opacityMod.halt();
opacityMod.setOpacity(0, { curve: 'easeOut', duration: 10 });
} else if ( position[0] > fadeEnd ) {
opacity = (position[0] - fadeStart) / ( fadeEnd - fadeStart );
opacityMod.halt();
opacityMod.setOpacity(opacity, { curve: 'easeOut', duration: 10 });
} else {
opacityMod.halt();
opacityMod.setOpacity(1, { curve: 'easeOut', duration: 10 });
}
}.bind([draggable,opacityMod]));
John has clearly answered this question above, but I wanted to show an alternate approach to the problem. I've seen questions here and in the #famous irc where people are having eventing problems. I've also seen a number of people struggling with binding or the lack of it. And finally, if you work out the whole slide thing here, shouldn't you be able to put that behind you and simply drop it in elsewhere? With that in mind I wrote a program that simply puts several images into a scrollview. Then I wrote a function called createSlidePanel that encapsulated the slide functionality and then to enable the fade-in of the word "delete" I created a second helper function createModifyingView. This approach appears to hit all three points above. I broke the eventing problems down into smaller more manageable units. It completely eliminated the need for this and binding. And finally, the two helper functions can be reused.
Here is my version of "main.js" which contains fundamentally "application" behavior:
/* globals define */
define(function(require, exports, module) {
'use strict';
// import dependencies
var Engine = require('famous/core/Engine');
var ImageSurface = require('famous/surfaces/ImageSurface');
var Surface = require('famous/core/Surface');
var Scrollview = require('famous/views/Scrollview');
var SnapTransition = require('famous/transitions/SnapTransition');
var Transitionable = require('famous/transitions/Transitionable');
var createSlidePanel = require('SlidePanel');
var createModifyingView = require('ModifyingView');
Transitionable.registerMethod('snap', SnapTransition);
var trans = {
method: 'snap',
period: 100,
dampingRatio: 0.3,
velocity: 5
};
var dataSource = [
'http://www.outerspaceuniverse.org/wp-content/uploads/2009/07/outer-space1.jpg',
'http://wallpoper.com/images/00/39/95/84/outer-space_00399584.jpg',
'http://static1.businessinsider.com/image/508c649e69beddb270000005/the-only-reason-private-space-flight-isnt-laughed-at-is-nasas-11-billion-infusion.jpg'
];
var images = [];
var slideOptions = {
drag: {
xRange: [-120, 5],
projection: 'x',
},
view: {
size:[300,300]
}
};
var mainContext = Engine.createContext();
var scrollView = new Scrollview();
mainContext.add(scrollView);
dataSource.forEach(function(url,i,urls) {
var img = new ImageSurface({
content: url,
size: [300,300]
});
var dlt = new Surface({
size:[300,300],
content: 'DELETE',
properties: {
color: 'red',
zIndex: 4,
lineHeight: '200px',
fontSize:'60px'
}
});
var modView = createModifyingView();
modView.modifier.setOpacity(0);
modView.add(dlt);
var elem = createSlidePanel(slideOptions);
elem.addSlide(img)
elem.addStill(modView);
elem._eventOutput.pipe(scrollView);
elem.on('slideupdate',slideUpdateHandler);
elem.on('slideend',slideEndHandler);
images.push(elem);
});
function slideUpdateHandler(eventInfo) {
var ratio = (eventInfo.data.position[0]-slideOptions.drag.xRange[1])/(slideOptions.drag.xRange[0]-slideOptions.drag.xRange[1]);
if(ratio>.2) {
eventInfo.source.stillElements[0].modifier.setOpacity(ratio);
} else {
eventInfo.source.stillElements[0].modifier.setOpacity(0);
}
}
function slideEndHandler(eventInfo) {
if (eventInfo.data.position[0] < (-100)) {
alert('delete');
}
eventInfo.source.modifier.setPosition([0,0,0], trans);
eventInfo.source.stillElements[0].modifier.setOpacity(0);
}
scrollView.sequenceFrom(images);
});
The slide functionality is here in "SlidePanel.js":
/* globals define */
define(function(require, exports, module) {
'use strict';
// import dependencies
var Modifier = require('famous/core/Modifier');
var View = require('famous/core/View');
var Draggable = require('famous/modifiers/Draggable');
function createSlidePanel(options) {
options = options || {};
var slidePanel = new View(options.view);
slidePanel.slideElements = [];
slidePanel.stillElements = [];
slidePanel.modifier = new Draggable(options.drag);
var node = slidePanel._add(slidePanel.modifier);
slidePanel.addSlide = function addSlide(renderable) {
node.add(renderable);
renderable.pipe(slidePanel._eventOutput);
renderable.pipe(slidePanel.modifier);
slidePanel.slideElements.push(renderable);
}
slidePanel.addStill = function addStill(renderable) {
slidePanel.add(renderable);
renderable.pipe(slidePanel._eventOutput);
renderable.pipe(slidePanel.modifier);
slidePanel.stillElements.push(renderable);
}
slidePanel.modifier.on('start',function(data) {
slidePanel._eventOutput.emit('slidestart',{source:slidePanel,data:data});
});
slidePanel.modifier.on('update',function(data) {
slidePanel._eventOutput.emit('slideupdate',{source:slidePanel,data:data});
});
slidePanel.modifier.on('end',function(data) {
slidePanel._eventOutput.emit('slideend',{source:slidePanel,data:data});
});
slidePanel.modifier.activate();
return slidePanel;
}
module.exports = createSlidePanel;
});
And here is the "ModifyingView.js" code:
/* globals define */
define(function(require, exports, module) {
'use strict';
// import dependencies
var Modifier = require('famous/core/Modifier');
var View = require('famous/core/View');
function createModifyingView(options) {
options = options || {};
var view = new View(options);
view.modifier = new Modifier();
var node = view._add(view.modifier);
view.add = function add(renderable) {
node.add(renderable);
view._eventOutput.subscribe(renderable);
};
view.setPosition = function setPosition(/* passthrough */) {
view.modifier.setPosition(arguments);
};
view.setOpacity = function setOpacity(/* passthrough */) {
view.modifier.setOpacity(arguments)
}
//view.modifier.setPosition([0,0,0]);
return view;
}
module.exports = createModifyingView;
});
Several Notes:
Obviously, one of the main changes here is the functional pattern which makes all references explicit and leaves no question of binding.
Yes this is more code than the original, partly because it is complete with all of the require statements and the list of images, but also because it just is. The trade-off here is that you may get more bang for the buck if you reuse the helpers.
The ModifyingView pattern is one I use quite a bit. This comes up so often whether I'm building a login form with eight surfaces interacting in ways the main program need know nothing about, or a simple surface fading in and out, that I have a code snippet which defines a view, a modifier, a statemodifier (one of which I usually delete,) a surface and much of the common code to tie them together.
I'm specifically not recommending the "options" management used in this code, but it suffices for the example.

How do I write a findMany that will get in chunks?

Ember 1.5.1
Ember-Data 1.0 beta 7
I've tried to modify the DS.ActiveModelAdapter's findMany so it'll get in chunks of 40... this is because I can't use the links feature and it seems to be generating 400 errors because it has too many ids in the URL its creating.
I tried using this adapter, but I keep getting error messages that look like this:
Error: Assertion Failed: Error: no model was found for 'super'
Here's my Adapter:
App.ApplicationAdapter = DS.ActiveModelAdapter.extend({
findMany: function(store, type, ids) {
self = this;
return new Ember.RSVP.Promise(function(resolve, reject) {
var idsPerRequest = 40;
var totalIdsLength = ids.length;
var numberOfBins = Math.ceil( totalIdsLength / idsPerRequest ); // number per bin
var bins = [];
ids.forEach( function(someId, index) {
var thisBinIndex = index % numberOfBins;
var thisBin = Ember.A( bins[thisBinIndex] );
thisBin.pushObject(someId);
bins[thisBinIndex] = thisBin;
});
var requestPromises = bins.map(function(binOfIds) {
return self.ajax(self.buildURL(type.typeKey), 'GET', { data: { ids: binOfIds } });
});
Ember.RSVP.all(requestPromises).then(function(resolvedBinRequests) {
var resolvedObjects = Em.A([]);
resolvedBinRequests.forEach(function(resolvedBin) {
resolvedObjects.addObjects(resolvedBin);
});
resolve(resolvedObjects);
}, function(error) {
reject(error);
});
});
}
});
Can anyone help me out with this? It'd be really appreciated. Am I just missing something obvious or have I perhaps done something silly?
Thanks in advance!
[edit] Okay so further to this I've figured out why it's not working, and that's because the response that's coming back is a promise for the JSON payload, but what I'm doing is joining multiples of these into an array and returning that... which obviously won't be right... but what I need to do is merge the arrays inside the objects returned into one, I think (in concept)... I'm not really sure how to do this in actuality, though... I've tried various things, but none of them seem to work well... :(
I'm not sure how much control you have over the back-end, but this seems like a perfect use case for using links instead of returning all of the ids.
App.Foo = DS.Model.extend({
bars: DS.hasMany('bar', {async:true})
});
App.Bar = DS.Model.extend({
name: DS.attr()
});
Then when you query for foo your json returns a link instead of a list of ids
{
foo: {
id:1,
links: {
bars: '/foo/1/bars' // or anything, you could put /bars?start=1&end=9000
}
}
}
Here's an example with 1000 relationship records hitting a simple endpoint:
http://emberjs.jsbin.com/OxIDiVU/579/edit
Okay so I finally worked out how to make this work.
I'll share my answer here for future posterity ;-)
Of interest is that the required response had to be a promise and it had to contain a straight up JS object, so I "munged" all the responses into one JS object and manually built the pluralized camelized type key... I wasn't sure how else to do this. So... sorry it's so hacky, but this actually works and lets me fix my app for now until the "links" feature is working again.
App.ApplicationAdapter = DS.ActiveModelAdapter.extend({
findMany: function(store, type, ids) {
self = this;
return new Ember.RSVP.Promise(function(resolve, reject) {
var idsPerRequest = 40;
var totalIdsLength = ids.length;
var numberOfBins = Math.ceil( totalIdsLength / idsPerRequest ); // number per bin
var bins = [];
ids.forEach( function(someId, index) {
var thisBinIndex = index % numberOfBins;
var thisBin = Ember.A( bins[thisBinIndex] );
thisBin.pushObject(someId);
bins[thisBinIndex] = thisBin;
});
// build an array of promises, then resolve using Ember.RSVP.all
var requestPromises = bins.map(function(binOfIds) {
return self.ajax(self.buildURL(type.typeKey), 'GET', { data: { ids: binOfIds } });
});
// build the required return object, which is a promise containing a plain JS object
// note this can't be an Ember object
Ember.RSVP.all(requestPromises).then(function(resolvedBinRequests) {
var pluralizedDecamelizedTypeKey = type.typeKey.decamelize().pluralize();
var resolvedObjects = Em.A([]);
var returnObject = {};
returnObject[pluralizedDecamelizedTypeKey] = resolvedObjects;
resolvedBinRequests.forEach(function(resolvedBin) {
var theArray = resolvedBin[pluralizedDecamelizedTypeKey];
resolvedObjects.addObjects(theArray);
});
var responsePromise = Ember.RSVP.Promise.cast(returnObject);
resolve(responsePromise);
}, function(error) {
reject(error);
});
});
}
});
After some feedback I updated this response to attempt to extract the response payloads in the serializer instead of attempting to mimic the store's logic in the adapter.
http://emberjs.jsbin.com/wegiy/60/edit
App.ApplicationAdapter = DS.ActiveModelAdapter.extend({
findMany: function(store, type, ids) {
// build an array of promises, then resolve using Ember.RSVP.all
var idsPerRequest = 40;
var totalIdsLength = ids.length;
var numberOfBins = Math.ceil( totalIdsLength / idsPerRequest ); // number per bin
var bins = [];
ids.forEach( function(someId, index) {
var thisBinIndex = index % numberOfBins;
var thisBin = Ember.A( bins[thisBinIndex] );
thisBin.pushObject(someId);
bins[thisBinIndex] = thisBin;
});
var requestPromises = bins.map(function(binOfIds) {
return self.ajax(self.buildURL(type.typeKey), 'GET', { data: { ids: binOfIds } });
});
return Ember.RSVP.all(requestPromises);
}
});
App.ApplicationSerializer = DS.ActiveModelSerializer.extend({
extractFindMany: function(store, type, responsePayloads) {
// responsePayloads is the resolved value from the Ember.RSVP.all(requestPromises) promise
var serializer = this;
var extractedResponses = responsePayloads.map(function(payload) {
return serializer.extractArray(store, type, payload);
});
// extractedResponses is an array of arrays. We need to flatten it into 1 array.
return [].concat.apply([], extractedResponses);
}
});

How to implement swipe action in ScrollView Famous

I'm trying to implement the typical swipe left event to trigger some custom action using a scrollview in famo.us. The thing is that I missing something and I can't get it done. I manage to implement a Draggable modifier in each scrollview item, so the items can be dragged (X axis), but now I can't be able to capture the event of the draggable modifier in order to trigger the actions.
Here is my ListView class:
define(function(require, exports, module) {
// Imports
var View = require('famous/core/View');
var Surface = require('famous/core/Surface');
var Utility = require('famous/utilities/Utility');
var ScrollView = require('famous/views/ScrollView');
var ViewSequence = require('famous/core/ViewSequence');
var Draggable = require('famous/modifiers/Draggable');
var RenderNode = require('famous/core/RenderNode');
var EventHandler = require('famous/core/EventHandler');
function ListView() {
View.apply(this, arguments);
this.items = [];
this.scrollView = new ScrollView({
direction: Utility.Direction.Y,
margin: 100000
});
this.viewSequence = new ViewSequence(this.items);
this.scrollView.sequenceFrom(this.viewSequence);
this._add(this.scrollView);
};
ListView.prototype = Object.create(View.prototype);
ListView.prototype.constructor = ListView;
ListView.prototype.setContent = function(data) {
for (var i = 0; i < data.length; i++) {
var item = new Surface({
size: [undefined, 60],
content: 'Item ' + data[i],
classes: ['listview-item']
});
var draggable = new Draggable({
xRange: [-100, 100],
yRange: [0, 0]
});
var node = new RenderNode(draggable);
node.add(item);
draggable.on('click', function() {
console.log('emit swipe')
this._eventOutput.emit('swipe');
}.bind(this)); // This Doesn't work
item.on('click', function() {
console.log('emit swipe')
this._eventOutput.emit('swipe');
}.bind(this)); // Neither this
item.pipe(draggable);
item.pipe(this.scrollView);
this.items.push(node);
}
};
module.exports = ListView;
});
Now App Class where I include my ListView:
define(function(require, exports, module) {
...
// Custom Views
var ListView = require('views/ListView');
function App() {
View.apply(this, arguments);
this.layout = new HeaderFooterLayout({
headerSize: 70,
});
...
this.list = new ListView();
this.list.pipe(this._eventInput);
this._eventInput.on('swipe', this.swipeListItem.bind(this)) // Trying to captute swipe event
this.list.setContent([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]);
this.layout.content.add(this.list);
....
this._add(this.layout);
};
App.prototype = Object.create(View.prototype);
App.prototype.constructor = App;
App.DEFAULT_OPTIONS = {};
App.prototype.swipeListItem = function() {
console.log('Item Swiped!');
};
module.exports = App;
});
I don't know what I missing or if there is a better way to implement a swipe gesture in famo.us, if someone knows something about it would be helpful.
Thanks in advance. =)
It looks like you want to use the 'start' event for the draggable modifier..
draggable.on('start', function() {
console.log('emit drag start')
this._eventOutput.emit('swipe');
}.bind(this));
Draggable also emits 'update', and 'end' and each of these handlers take a parameter that returns the position of the draggable
draggable.on('update', function(e) {
// Do something on update
var pos = e.position;
});
draggable.on('end', function(e) {
// Do something on end
var pos = e.position;
});
Hope this helps!