5 | Nothing visible should be on this page (except this message).
6 | This is just to show that a module that has a lot of 'weird'
7 | files (like dotfiles, etc.) compiles successfully.
8 |
9 | `
10 | });
11 | /////HELLO
12 | ///
13 | ///
14 | ///
15 | ///sdf
--------------------------------------------------------------------------------
/lib/core-components/famous/adapter/google-finance/google-finance.js:
--------------------------------------------------------------------------------
1 | var API_URL = "http://finance.google.com/finance/info?client=ig&q={tickers}";
2 |
3 | /**
4 | * A service component used to connect to the Google finance api.
5 | * It leverages the justinsmith:service:http service component to make the web requests.
6 | */
7 | FamousFramework.scene('famous:adapter:google-finance', {
8 |
9 | behaviors: {
10 |
11 | 'famous:service:http': {
12 |
13 | 'url': API_URL,
14 | 'parse-json': false,
15 |
16 | 'request': function(tickers) {
17 |
18 | //create the request whenever tickers are updated using
19 | //url parameters + token since the url is defined above
20 | return {
21 |
22 | //i'm not actually checking the token in the response,
23 | //but i put it in here anyways to show usage
24 | 'token': "googlefinance-" + Math.random(),
25 |
26 | 'parameters': {
27 | 'tickers':tickers.join(',')
28 | }
29 | };
30 | }
31 | }
32 | },
33 |
34 | events: {
35 |
36 | 'famous:service:http': {
37 |
38 | 'response': function($payload, $event, $dispatcher) {
39 |
40 | $event.stopPropagation();
41 |
42 | var response = $payload.response;
43 |
44 | try {
45 | //need to do some funny business cuz Google adds some comments to the result???
46 | //not sure why...but just parse it out
47 | var data = JSON.parse(response.data.substring(3));
48 |
49 | if(data.cod && data.message) {
50 | $dispatcher.emit("error", data.message);
51 | return;
52 | }
53 |
54 | //send the response event with our parsed data
55 | $dispatcher.emit("response", data);
56 | }
57 | catch(ee) {
58 | $dispatcher.emit("error", ee);
59 | }
60 | },
61 |
62 | 'error': function($payload, $dispatcher) {
63 | console.warn("Error: ", $payload);
64 | $dispatcher.emit("error", $payload);
65 | }
66 | },
67 |
68 | '$public': {
69 |
70 | 'query': function($dispatcher, $state, $payload) {
71 |
72 | //dont' do anything if a null query was made
73 | if(!$payload) {
74 | return;
75 | }
76 |
77 | //otherwise set our tickers
78 | $state.set("tickers", $payload);
79 | }
80 | }
81 | },
82 |
83 | tree: ''
84 | });
85 |
--------------------------------------------------------------------------------
/lib/core-components/famous/layouts/flexible/flexible.js:
--------------------------------------------------------------------------------
1 | FamousFramework.component('famous:layouts:flexible', {
2 | behaviors: {
3 | '$self' : {
4 | 'direction' : '[[identity]]',
5 | 'ratios' : '[[identity]]',
6 | 'transition' : '[[identity]]'
7 | },
8 | '.flexible-layout': {
9 | // HACK: force creating a layout wrapper container
10 | 'style': {}
11 | },
12 | '.flexible-layout-item': {
13 | '$yield': true
14 | }
15 | },
16 | events: {
17 | '$public': {
18 | 'direction': '[[setter]]',
19 | 'ratios': '[[setter]]',
20 | 'transition': '[[setter]]',
21 | 'update-layout': ($famousNode) => {
22 | $famousNode.updateLayout();
23 | }
24 | },
25 | '$private' : {
26 | 'direction': ($famousNode, $payload) => {
27 | if ($payload === 0) {
28 | $famousNode.direction = FlexibleLayout.Direction.X;
29 | } else if ($payload === 1) {
30 | $famousNode.direction = FlexibleLayout.Direction.Y;
31 | } else if ($payload === 2) {
32 | $famousNode.direction = FlexibleLayout.Direction.Z;
33 | }
34 | },
35 | 'ratios': ($famousNode, $payload) => {
36 | $famousNode.ratios = $payload;
37 | },
38 | 'transition': ($famousNode, $payload) => {
39 | $famousNode.transition = $payload;
40 | }
41 | }
42 | },
43 | states: {
44 | direction: 0,
45 | ratios: [],
46 | transition: null
47 | },
48 | tree: `
49 |
50 |
51 |
52 | `
53 | }).config({
54 | famousNodeConstructorName: 'FlexibleLayout',
55 | includes: ['_constructor.js']
56 | });
57 |
--------------------------------------------------------------------------------
/lib/core-components/famous/layouts/header-footer/header-footer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/lib/core-components/famous/layouts/header-footer/header-footer.js:
--------------------------------------------------------------------------------
1 | FamousFramework.module('famous:layouts:header-footer', {
2 | tree: 'header-footer.html',
3 | behaviors: {
4 | '#header' : {
5 | /*
6 | $yield is a special type of "control-flow behavior". It is at the core of
7 | what enables components in the Famous Framework to be composable. Setting $yield
8 | on a component tells the system that it is ok for a parent component to inject
9 | components inside of a child component. Values for $yield are either a boolean,
10 | which signifies that the parent component can add any component into the child,
11 | or a String, which signifies that the parent component can add components into
12 | the child if those components match the CSS selector given by String.
13 |
14 | In this example, the parent can include the header-footer component and inject
15 | its own content into the header/body/footer nodes like so:
16 | header-footer
17 | a#header
18 | b#body
19 | c#footer
20 |
21 | Component `a` will end up being slotted into the 'header' nodes, and as such will
22 | be sized according to the behavior specified bellow.
23 | */
24 | '$yield' : '#header',
25 | 'size-absolute-y' : '[[identity|headerHeight]]'
26 | },
27 | '#body' : {
28 | '$yield' : '#body',
29 | 'position' : function(headerHeight) {
30 | return [0, headerHeight]
31 | },
32 | 'size-differential-y' : function(headerHeight, footerHeight) {
33 | return -headerHeight - footerHeight;
34 | }
35 | },
36 | '#footer' : {
37 | '$yield' : '#footer',
38 | 'size-absolute-y' : function(footerHeight) {
39 | return footerHeight;
40 | },
41 | 'position-y': function(footerHeight) {
42 | return -footerHeight;
43 | },
44 | align: [0, 1],
45 | }
46 | },
47 | events: {
48 | '$public' : {
49 | 'header-height' : '[[setter|headerHeight]]',
50 | 'footer-height' : '[[setter|footerHeight]]'
51 | }
52 | },
53 | states: {
54 | 'headerHeight' : 100,
55 | 'footerHeight' : 100
56 | }
57 | });
58 |
--------------------------------------------------------------------------------
/lib/core-components/famous/layouts/scroll-view/scroll-view.js:
--------------------------------------------------------------------------------
1 | FamousFramework.scene('famous:layouts:scroll-view', {
2 | behaviors: {
3 | '$self': {
4 | position: '[[identity|scrollViewPosition]]',
5 | size: '[[identity|scrollViewSize]]',
6 | style: function(border) {
7 | var style = {};
8 | style.overflow = 'scroll';
9 | if (border) style.border = border;
10 | return style;
11 | }
12 | },
13 | '.item' : {
14 | '$yield' : '.scroll-view-item',
15 | 'size' : function(itemHeight) {
16 | return [undefined, itemHeight];
17 | },
18 | 'position' : function($index, itemHeight) {
19 | return [0, $index * itemHeight];
20 | }
21 | }
22 | },
23 | events: {
24 | $public: {
25 | 'item-height' : '[[setter|itemHeight]]',
26 | 'scroll-view-position' : '[[setter|scrollViewPosition]]',
27 | 'scroll-view-size' : '[[setter|scrollViewSize]]',
28 | }
29 | },
30 | states: {
31 | itemHeight: 100,
32 | scrollViewSize: [400, 800],
33 | scrollViewPosition: [0, 0],
34 | border: '3px solid #40b2e8'
35 | },
36 | tree: `
37 |
38 | `
39 | });
40 |
--------------------------------------------------------------------------------
/lib/core-components/famous/layouts/sequential/sequential.js:
--------------------------------------------------------------------------------
1 | FamousFramework.component('famous:layouts:sequential', {
2 | behaviors: {
3 | '$self' : {
4 | 'direction' : '[[identity]]',
5 | 'transition' : '[[identity]]'
6 | },
7 | '.sequential-layout': {
8 | // HACK: force creating a layout wrapper container
9 | 'style': {}
10 | },
11 | '.sequential-layout-item': {
12 | '$yield': true
13 | }
14 | },
15 | events: {
16 | '$public': {
17 | 'direction': '[[setter]]',
18 | 'transition': '[[setter]]',
19 | 'update-layout': ($famousNode) => {
20 | $famousNode.updateLayout();
21 | }
22 | },
23 | '$private' : {
24 | 'direction': ($famousNode, $payload) => {
25 | if ($payload === 0) {
26 | $famousNode.direction = SequentialLayout.Direction.X;
27 | } else if ($payload === 1) {
28 | $famousNode.direction = SequentialLayout.Direction.Y;
29 | } else if ($payload === 2) {
30 | $famousNode.direction = SequentialLayout.Direction.Z;
31 | }
32 | },
33 | 'transition': ($famousNode, $payload) => {
34 | $famousNode.transition = $payload;
35 | }
36 | }
37 | },
38 | states: {
39 | direction: 0,
40 | transition: null
41 | },
42 | tree: `
43 |
44 |
45 |
46 | `
47 | }).config({
48 | famousNodeConstructorName: 'SequentialLayout',
49 | includes: ['_constructor.js']
50 | });
51 |
--------------------------------------------------------------------------------
/lib/core-components/famous/service/location/location.js:
--------------------------------------------------------------------------------
1 | /**
2 | * The amount of time (in milliseconds) to wait
3 | * for the browser to return geo coordinates of
4 | *
5 | * the user's location.
6 | * @type {number}
7 | */
8 | var TIMEOUT = 10000;
9 |
10 | /**
11 | * A service component used to get the users
12 | * geographic location from the browser.
13 | * Originally justinsmith:service:location, moved into core.
14 | */
15 | FamousFramework.component('famous:service:location', {
16 |
17 | events: {
18 |
19 | '$lifecycle': {
20 |
21 | /**
22 | * Trigger the location-requested event on load.
23 | *
24 | * @param $dispatcher The event dispatcher
25 | */
26 | 'post-load': function($dispatcher) {
27 | $dispatcher.trigger("location-requested");
28 | }
29 | },
30 |
31 | '$public': {
32 |
33 | /**
34 | * Requests the geographic location from the browser (if supported).
35 | * If the browser doesn't respond within 10 seconds, an error event
36 | * is dispatched.
37 | *
38 | * @param $state
39 | * @param $dispatcher
40 | */
41 | 'location-requested': function($state, $dispatcher) {
42 |
43 | //quick exit if the browser doesn't support geolocation
44 | if(!navigator.geolocation) {
45 | var message = "Geolocation is not supported by this browser."
46 | console.warn(message);
47 | $dispatcher.emit("error", message);
48 | return
49 | }
50 |
51 | //timeout after 10 seconds
52 | //TODO: maybe make this configurable???
53 |
54 | var isTimedOut = false;
55 | var timeout = setTimeout(function() {
56 | isTimedOut = true;
57 | $dispatcher.emit("error", "Geolocation request timed out or permission was not granted.");
58 | }, TIMEOUT);
59 |
60 | /**
61 | * The callback handler for the geolocation api.
62 | *
63 | * @param position The geographic position of the user's browser.
64 | */
65 | function callback(position) {
66 |
67 | clearTimeout(timeout);
68 |
69 | //if the callback actually DOES return
70 | //but we've exceeded the timeout, ignore the result.
71 | if(isTimedOut) {
72 | return;
73 | }
74 |
75 | //save our data and dispatch an event
76 | $state.set("location", position.coords);
77 | $dispatcher.emit("location", position.coords);
78 | };
79 |
80 | //call the geolocation api
81 | navigator.geolocation.getCurrentPosition(callback);
82 | }
83 | }
84 | },
85 |
86 | //TODO: if all I'm doing is just emitting events, do i really NEED the state?
87 | //TODO: probably not, but leaving it in here anyways
88 | states: {
89 | location: null
90 | }
91 | });
92 |
--------------------------------------------------------------------------------
/lib/core-components/famous/service/timer/timer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Workaround due to the inability to save
3 | * the interval timer function as a state.
4 | *
5 | * It's a map because anything in this space is defacto singleton.
6 | */
7 | var intervalMap = {};
8 |
9 | /**
10 | * A service component used to periodically fire a 'time' event.
11 | * To use, include in your tree and set the 'period' behavior
12 | * to a numerical (milliseconds) value.
13 | * Originally justinsmith:service:timer, moved into core.
14 | */
15 | FamousFramework.component('famous:service:timer', {
16 |
17 | events: {
18 |
19 | '$public': {
20 |
21 | /**
22 | * The interval period in milliseconds.
23 | *
24 | * @param $payload The period in milliseconds
25 | * @param $state The state manager.
26 | * @param $dispatcher The event dispatcher
27 | * @param $famousNode A reference to the Node this component belongs to.
28 | */
29 | 'period': function($payload, $state, $dispatcher, $famousNode) {
30 |
31 | //save our period state
32 | var period = $payload;
33 | $state.set("period", period);
34 |
35 | //get a reference to the famous engine clock
36 | var clock = FamousFramework.FamousEngine.core.FamousEngine.getClock();
37 | var nodeId = $famousNode.getId();
38 |
39 | //reset the timer interval for this component (if it exists)
40 | if(intervalMap.hasOwnProperty(nodeId)) {
41 | clock.clearTimer(intervalMap[nodeId]);
42 | }
43 |
44 | //create an interval to periodically
45 | //trigger a 'time' event
46 | intervalMap[nodeId] = clock.setInterval(function() {
47 |
48 | //set the new time
49 | var time = new Date().getTime();
50 | $state.set("time", time);
51 | $dispatcher.emit("tick", time);
52 |
53 | }, period);
54 | }
55 | }
56 | },
57 |
58 | states: {
59 |
60 | /**
61 | * Default timer update period 100 milliseconds
62 | */
63 | period: 100
64 | }
65 | });
66 |
--------------------------------------------------------------------------------
/lib/core-components/famous/ui/config-panel/assets/plus.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
--------------------------------------------------------------------------------
/lib/events/injector.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var FamousConnector = require('./../famous-connector/famous-connector');
4 | var DataStore = require('./../data-store/data-store');
5 |
6 | var PAYLOAD_KEY = '$payload';
7 | var STATE_MANAGER_KEY = '$state';
8 | var TIMELINES_KEY = '$timelines';
9 | var FRAMEWORK_COMPONENT_KEY = '$component';
10 | var FAMOUS_NODE_KEY = '$famousNode';
11 | var FRAMEWORK_DOM_NODE_KEY = '$domNode';
12 | var DISPATCHER_KEY = '$dispatcher';
13 | var DOM_ELEMENT_KEY = '$DOMElement';
14 | var MESH_KEY = '$mesh';
15 | var INDEX_KEY = '$index';
16 | var REPEAT_PAYLOAD_KEY = '$repeatPayload';
17 | var ROUTE_KEY = '$route';
18 | var EVENT_KEY = '$event';
19 | var GESTURE_HANDLER_KEY = '$GestureHandler';
20 |
21 | function getArgs(paramNames, payload, uid) {
22 | var component = DataStore.getComponent(uid);
23 | var args = [];
24 | for (var i = 0; i < paramNames.length; i++) {
25 | switch (paramNames[i]) {
26 | case PAYLOAD_KEY: args.push(payload); break;
27 | case FRAMEWORK_COMPONENT_KEY: args.push(component); break;
28 | case FAMOUS_NODE_KEY: args.push(component.famousNode); break;
29 | case FRAMEWORK_DOM_NODE_KEY: args.push(component.tree.getRootNode()); break;
30 | case STATE_MANAGER_KEY: args.push(component.states.getStateManager()); break;
31 | case TIMELINES_KEY: args.push(component.timelines); break;
32 | case DISPATCHER_KEY: args.push(component.events.dispatcher); break;
33 | case INDEX_KEY: args.push(component.states.get(INDEX_KEY)); break;
34 | case REPEAT_PAYLOAD_KEY: args.push(component.states.get(REPEAT_PAYLOAD_KEY)); break;
35 | case ROUTE_KEY: args.push(component.states.get(ROUTE_KEY)); break;
36 | case DOM_ELEMENT_KEY: args.push(FamousConnector.decorateComponent(component, 'DOMElement')); break;
37 | case MESH_KEY: args.push(FamousConnector.decorateComponent(component, 'Mesh')); break;
38 | case EVENT_KEY: args.push(null); break; // `$event` gets overwritten with event object if one exists
39 | case GESTURE_HANDLER_KEY: args.push(FamousConnector.GestureHandler); break;
40 | default:
41 | throw new Error('No such object `' + paramNames[i] + '`');
42 | }
43 | }
44 | return args;
45 | }
46 |
47 | module.exports = {
48 | getArgs: getArgs
49 | };
50 |
--------------------------------------------------------------------------------
/lib/helpers/helpers.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var piecewise = require('./piecewise');
4 | var clone = require('./../utilities/object').clone;
5 |
6 | function formatStyle(styleObj) {
7 | var styleStr = '';
8 | for (var name in styleObj) {
9 | styleStr += name + ':' + styleObj[name] + '; ';
10 | }
11 | return styleStr;
12 | }
13 |
14 | module.exports = {
15 | piecewise: piecewise,
16 | clone: clone,
17 | formatStyle: formatStyle
18 | };
19 |
--------------------------------------------------------------------------------
/lib/helpers/piecewise.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var FamousConnector = require('./../famous-connector/famous-connector');
4 | var Curves = FamousConnector.Curves;
5 |
6 | var linear = function(x) {
7 | return x;
8 | };
9 |
10 | var ADD = 'ADD';
11 | var SUBTRACT = 'SUBTRACT';
12 | var MULTIPLY = 'MULTIPLY';
13 |
14 | var operations = {
15 | ADD: function(a, b) {
16 | return a + b;
17 | },
18 | SUBTRACT: function(a, b) {
19 | return a - b;
20 | },
21 | MULTIPLY: function(a, b) {
22 | return a * b;
23 | }
24 | };
25 |
26 | function polymorphicOperation(operationName, a, b) {
27 | if (typeof a === 'number') {
28 | return operations[operationName](a, b);
29 | }
30 | else {
31 | var isArray = Array.isArray(b);
32 | return a.map(function(value, i) {
33 | return operations[operationName](value, isArray ? b[i] : b);
34 | });
35 | }
36 | }
37 |
38 | function scale(time, easingCurve, t1, t2, v1, v2) {
39 | var standardizedTime = (time - t1) / (t2 - t1); // value from 0 to 1
40 | var timeScale = easingCurve(standardizedTime); // adjusted with easing curve
41 |
42 | var valueSpan = polymorphicOperation(SUBTRACT, v2, v1);
43 | var valueProgess = polymorphicOperation(MULTIPLY, valueSpan, timeScale);
44 | var value = polymorphicOperation(ADD, valueProgess, v1);
45 | return value;
46 | }
47 |
48 | // Store timeline by UID
49 | var timelines = {};
50 |
51 | function piecewise(points) {
52 | var timelineUID = JSON.stringify(points);
53 |
54 | if (timelines[timelineUID]) {
55 | return timelines[timelineUID];
56 | }
57 | else {
58 | timelines[timelineUID] = function(t) {
59 | if (t <= points[0][0]) {
60 | return points[0][1];
61 | }
62 | else {
63 | for (var i = 0; i < points.length - 1; i++) {
64 | if (points[i][0] <= t && t < points[i + 1][0]) {
65 | return scale(
66 | t,
67 | Curves[points[i][2]] || linear,
68 | points[i][0],
69 | points[i + 1][0],
70 | points[i][1],
71 | points[i + 1][1]
72 | );
73 | }
74 | }
75 | }
76 | return points[points.length - 1][1];
77 | };
78 | return timelines[timelineUID];
79 | }
80 | }
81 |
82 | module.exports = piecewise;
83 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | require('./polyfills/custom-event');
4 |
5 | var DataStore = require('./data-store/data-store');
6 | var Deployer = require('./deployer/deployer');
7 | var helpers = require('./helpers/helpers');
8 | var Messenger = require('./messenger/messenger');
9 |
10 | var deployer = new Deployer();
11 |
12 | function register(name, tag, options, definition) {
13 | return DataStore.registerModule(name, tag, options, definition);
14 | }
15 |
16 | module.exports = {
17 | attach: deployer.attach.bind(deployer),
18 | component: register, // alias for 'register'
19 | deploy: deployer.deploy.bind(deployer),
20 | execute: deployer.execute.bind(deployer),
21 | FamousEngine: require('./famous-connector/famous-connector').FamousEngine,
22 | getComponentByUID: DataStore.getComponent,
23 | helpers: helpers,
24 | includes: deployer.includes.bind(deployer),
25 | markComponentAsReady: deployer.markComponentAsReady.bind(deployer),
26 | message: Messenger.message,
27 | module: register, // alias for 'register'
28 | register: register,
29 | registerCustomFamousNodeConstructors: DataStore.registerCustomFamousNodeConstructors,
30 | scene: register // alias for 'register'
31 | };
32 |
--------------------------------------------------------------------------------
/lib/logger/logger.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var MAP = {
4 | 2: 'INFO',
5 | 1: 'WARN',
6 | 0: 'FAIL'
7 | };
8 |
9 | var LOG_LEVEL = 0;
10 |
11 | var LOG = {};
12 | LOG[MAP[0]] = [];
13 | LOG[MAP[1]] = [];
14 | LOG[MAP[2]] = [];
15 | LOG.ALL = [];
16 |
17 | function log(msg, level) {
18 | if (level <= LOG_LEVEL) {
19 | if (level === 0) {
20 | console.error(msg);
21 | }
22 | else if (level === 1) {
23 | console.warn(msg);
24 | }
25 | else {
26 | console.log(msg);
27 | }
28 | }
29 |
30 | var info = {
31 | message: msg,
32 | timestamp: Date.now()
33 | };
34 |
35 | LOG.ALL.push(info);
36 | LOG[MAP[level]].push(info);
37 | }
38 |
39 | function setLevel(level) {
40 | if (level < 0 || level > 2) {
41 | throw new Error('Log level must be set to an integer between 0 and 2');
42 | }
43 | LOG_LEVEL = level;
44 | }
45 |
46 | function getLevel() {
47 | return LOG_LEVEL;
48 | }
49 |
50 | function getLog() {
51 | return LOG;
52 | }
53 |
54 |
55 | module.exports = {
56 | log: log,
57 | getLog: getLog,
58 | setLevel: setLevel,
59 | getLevel: getLevel
60 | };
61 |
--------------------------------------------------------------------------------
/lib/messenger/messenger.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var VirtualDOM = require('./../virtual-dom/virtual-dom');
4 | var DataStore = require('./../data-store/data-store');
5 |
6 | var ROOT_SELECTOR = '$root';
7 |
8 | function message(domSelector, componentSelector, key, value) {
9 | var rootComponent = DataStore.getExecutedComponent(domSelector);
10 | var targetComponent;
11 | if (componentSelector === ROOT_SELECTOR) {
12 | targetComponent = rootComponent;
13 | targetComponent.sendMessage(key, value);
14 | }
15 | else {
16 | var targets = VirtualDOM.query(rootComponent.getRootNode(), componentSelector);
17 | for (var i = 0; i < targets.length; i++) {
18 | targetComponent = DataStore.getComponent(VirtualDOM.getUID(targets[i]));
19 | targetComponent.sendMessage(key, value);
20 | }
21 | }
22 | }
23 |
24 | module.exports = {
25 | message: message
26 | };
27 |
--------------------------------------------------------------------------------
/lib/polyfills/custom-event.js:
--------------------------------------------------------------------------------
1 | var CustomEvent = function(event, params) {
2 | var evt;
3 |
4 | params = params || {
5 | bubbles: false,
6 | cancelable: false,
7 | detail: undefined
8 | };
9 |
10 | evt = document.createEvent("CustomEvent");
11 | evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
12 |
13 | return evt;
14 | };
15 |
16 | CustomEvent.prototype = window.Event.prototype;
17 |
18 | window.CustomEvent = CustomEvent;
19 |
--------------------------------------------------------------------------------
/lib/state-manager/operator.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function handleArrayInput (operator, a, b) {
4 | if (Array.isArray(b)) {
5 | for (var i = 0; i < b.length; i++) {
6 | if (b === a.length) return undefined;
7 | a[i] = operations[operator](a[i], b[i]);
8 | }
9 | }
10 | else {
11 | for (var j = 0; j < a.length; j++) {
12 | a[j] = operations[operator](a[j], b);
13 | }
14 | }
15 |
16 | return a;
17 | }
18 |
19 | // Check for number/string/array
20 | function isTypeValid(input) {
21 | return !isNaN(input) || typeof(input) === 'string' || Array.isArray(input);
22 | }
23 |
24 | // Convenient state operators.
25 | var operations = {
26 | '+': function(a, b) {
27 | return a + b;
28 | },
29 | '-': function(a, b) {
30 | return a - b;
31 | },
32 | '*': function(a, b) {
33 | return a * b;
34 | },
35 | '/': function(a, b) {
36 | return a / b;
37 | },
38 | 'pow': function(a, b) {
39 | return Math.pow(a, b);
40 | },
41 | 'sqrt': function(a) {
42 | return Math.sqrt(a);
43 | },
44 | 'abs': function(a) {
45 | return Math.abs(a);
46 | },
47 | 'sin': function(a) {
48 | return Math.sin(a);
49 | },
50 | 'cos': function(a) {
51 | return Math.cos(a);
52 | },
53 | 'tan': function(a) {
54 | return Math.tan(a);
55 | },
56 | 'ceil': function(a) {
57 | return Math.ceil(a);
58 | },
59 | 'floor': function(a) {
60 | return Math.floor(a);
61 | },
62 | 'concat': function(a, b) {
63 | return a.concat(b);
64 | },
65 | 'substring': function(a, b) {
66 | return a.substring(b[0], b[1]);
67 | },
68 | 'toLower': function(a) {
69 | return a.toLowerCase();
70 | },
71 | 'toUpper': function(a) {
72 | return a.toUpperCase();
73 | },
74 | 'flip': function(a) {
75 | return !a;
76 | },
77 | 'toInt': function(a) {
78 | return a ? 1 : 0;
79 | }
80 | };
81 |
82 | module.exports = {
83 | operate: function(operator, currentValue, newValue) {
84 | if (newValue) {
85 | if (!(isTypeValid(currentValue) && isTypeValid(newValue))) {
86 | console.warn(' or is not a valid input type');
87 | throw new Error('Invalid input');
88 | }
89 | else if (!Array.isArray(currentValue) && Array.isArray(newValue)) {
90 | if (typeof(currentValue) !== 'string') { // special case for 'substring' operation
91 | console.warn('An array can not be used as input to operate on a non-array');
92 | throw new Error('Invalid input');
93 | }
94 | }
95 | }
96 |
97 | if (Array.isArray(currentValue)) {
98 | return handleArrayInput(operator, currentValue, newValue);
99 | }
100 | else {
101 | return operations[operator](currentValue, newValue);
102 | }
103 | },
104 | addOperation: function(name, func) {
105 | operations[name] = func;
106 | }
107 | };
108 |
109 |
110 |
--------------------------------------------------------------------------------
/lib/states/states.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var EventHandler = require('./../utilities/event-handler');
4 | var FamousConnector = require('./../famous-connector/famous-connector');
5 | var StateManager = require('./../state-manager/state-manager');
6 |
7 | var STATE_AUTOTRIGGER_RE = /^[a-zA-Z0-9$].*/i;
8 |
9 | function States(famousNode, initialState) {
10 | EventHandler.apply(this);
11 | var Transitionable = FamousConnector.Transitionable;
12 | this.stateManager = new StateManager(initialState, famousNode, Transitionable);
13 | }
14 |
15 | States.prototype = Object.create(EventHandler.prototype);
16 | States.prototype.constructor = States;
17 |
18 | States.prototype.handleStateChange = function handleStateChange(behaviorDefinition) {
19 | this.emit('behavior-update', behaviorDefinition);
20 | };
21 |
22 | States.prototype.createBehaviorListener = function createBehaviorListener(behaviorDefinition) {
23 | var params = behaviorDefinition.params;
24 | if (!params || params.length < 1) {
25 | this.stateManager.subscribeToGlobalChange(
26 | this.handleStateChange.bind(this, behaviorDefinition)
27 | );
28 | }
29 | else {
30 | for (var i = 0; i < params.length; i++) {
31 | this.stateManager.subscribeTo(
32 | params[i],
33 | this.handleStateChange.bind(this, behaviorDefinition)
34 | );
35 | }
36 | }
37 | };
38 |
39 | States.prototype.getStateManager = function getStateManager() {
40 | return this.stateManager;
41 | };
42 |
43 | States.prototype.set = function set(key, value, transition) {
44 | this.stateManager.set(key, value, transition);
45 | };
46 |
47 | States.prototype.get = function get(key) {
48 | return this.stateManager.get(key);
49 | };
50 |
51 | States.prototype.subscribeTo = function subscribeTo(key, observer) {
52 | this.stateManager.subscribeTo(key, observer);
53 | };
54 |
55 | States.prototype.unsubscribeFrom = function unsubscribeFrom (key, observer) {
56 | this.stateManager.unsubscribeFrom(key, observer);
57 | };
58 |
59 | States.prototype.unsubscribeAllFromKey = function unsubscribeAllFromKey (key) {
60 | this.stateManager._unsubscribeAllFromKey(key);
61 | };
62 |
63 | States.prototype.triggerGlobalChange = function triggerGlobalChange(whiteList, blackList) {
64 | whiteList = whiteList || STATE_AUTOTRIGGER_RE;
65 | this.stateManager.triggerGlobalChange(whiteList, blackList);
66 | };
67 |
68 | States.prototype.getValues = function getValues(names) {
69 | var result = [];
70 | for (var i = 0; i < names.length; i++) {
71 | result.push(this.stateManager.get(names[i]));
72 | }
73 | return result;
74 | };
75 |
76 | States.prototype.getNames = function getNames() {
77 | return Object.keys(this.stateManager._state);
78 | };
79 |
80 | module.exports = States;
81 |
--------------------------------------------------------------------------------
/lib/tree/tree.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var VirtualDOM = require('./../virtual-dom/virtual-dom');
4 |
5 | var CONTROL_FLOW_ACTION_KEY = 'control-flow-action';
6 | var EMPTY_STRING = '';
7 | var REPEAT_INFO_KEY = 'repeat-info';
8 |
9 | function Tree(rootNode, treeString, dependencies, parentNode) {
10 | this.rootNode = rootNode;
11 | VirtualDOM.addNode(this.rootNode, parentNode);
12 |
13 | this.blueprint = VirtualDOM.clone(this.rootNode);
14 | var blueprintChildrenWrapper = VirtualDOM.parse(treeString || EMPTY_STRING);
15 |
16 | VirtualDOM.transferChildNodes(blueprintChildrenWrapper, this.blueprint);
17 | VirtualDOM.assignChildUIDs(this.blueprint);
18 | Tree.assignDependencyTags(this.blueprint, dependencies);
19 |
20 | this.expandedBlueprint = null; // Set via event after $if/$repeat
21 | this.childrenRoot = null; // Set via event after $yield
22 | }
23 |
24 | Tree.prototype.getBlueprint = function getBlueprint() {
25 | return this.blueprint;
26 | };
27 |
28 | Tree.prototype.setExpandedBlueprint = function setExpandedBlueprint(expandedBlueprint) {
29 | this.expandedBlueprint = expandedBlueprint;
30 | };
31 |
32 | Tree.prototype.getExpandedBlueprint = function getExpandedBlueprint() {
33 | return this.expandedBlueprint;
34 | };
35 |
36 | Tree.prototype.setChildrenRoot = function setChildrenRoot(childrenRoot) {
37 | this.childrenRoot = childrenRoot;
38 | };
39 |
40 | Tree.prototype.getChildrenRoot = function getChildrenRoot() {
41 | return this.childrenRoot;
42 | };
43 |
44 | Tree.prototype.getRootNode = function getRootNode() {
45 | return this.rootNode;
46 | };
47 |
48 | Tree.prototype.eachChild = function eachChild(cb) {
49 | for (var i = 0; i < this.childrenRoot.children.length; i++) {
50 | cb(this.childrenRoot.children[i]);
51 | }
52 | };
53 |
54 | Tree.assignDependencyTags = function assignDependencyTags(node, dependencies) {
55 | var allNodes = VirtualDOM.query(node, '*');
56 | for (var i = 0; i < allNodes.length; i++) {
57 | var subNode = allNodes[i];
58 | var tagName = subNode.tagName.toLowerCase();
59 | if (dependencies[tagName]) {
60 | VirtualDOM.setTag(subNode, dependencies[tagName]);
61 | }
62 | }
63 | };
64 |
65 | Tree.removeAttributes = function removeAttributes(nodes, attrName) {
66 | for (var i = 0; i < nodes.length; i++) {
67 | VirtualDOM.removeAttribute(nodes[i], attrName);
68 | }
69 | };
70 |
71 | Tree.prototype.stripExpandedBlueprintMessages = function stripExpandedBlueprintMessages() {
72 | var targets;
73 | targets = VirtualDOM.queryAttribute(this.expandedBlueprint, CONTROL_FLOW_ACTION_KEY);
74 | Tree.removeAttributes(targets, CONTROL_FLOW_ACTION_KEY);
75 | targets = VirtualDOM.queryAttribute(this.expandedBlueprint, REPEAT_INFO_KEY);
76 | Tree.removeAttributes(targets, REPEAT_INFO_KEY);
77 | };
78 |
79 | module.exports = Tree;
80 |
--------------------------------------------------------------------------------
/lib/utilities/array.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var ObjectUtils = require('./object');
4 |
5 | // Iterate over the array, passing each element to the given function.
6 | function each(a, cb) {
7 | for (var i = 0; i < a.length; i++) {
8 | cb(a[i]);
9 | }
10 | }
11 |
12 | // Return the set of elements that appear in both arrays `a` and `b`.
13 | function union(a, b) {
14 | var set = {};
15 | var maxLength = Math.max(a.length, b.length);
16 | var result = [];
17 | var i, key;
18 |
19 | for (i = 0; i < maxLength; i++) {
20 | if (i < a.length) set[a[i]] = true;
21 | if (i < b.length) set[b[i]] = true;
22 | }
23 |
24 | for (key in set) {
25 | result.push(key);
26 | }
27 | return result;
28 | }
29 |
30 | /**
31 | * Iterates over each element in a pair of arrays and returns a result array
32 | * signifying whether elements at a shared index are equal.
33 | * @param {Array} a
34 | * @param {Array} b
35 | * @return {Array} Array of booleans; 'true' signifies that the elements that share
36 | * that index are equal, 'false' signifies that the elements at that
37 | * index are not equal.
38 | */
39 | function checkElementEquality(a, b) {
40 | var maxLength = Math.max(a.length, b.length);
41 | var result = [];
42 | var isEqual;
43 |
44 | for (var i = 0; i < maxLength; i++) {
45 | isEqual = (a.length > i && b.length > i) ? ObjectUtils.isEqual(a[i], b[i]) : false;
46 | result.push(isEqual);
47 | }
48 | return result;
49 | }
50 |
51 | /**
52 | * Checks to see if two arrays share a given value.
53 | * @param {Array} a
54 | * @param {Array} b
55 | * @return {Boolean}
56 | */
57 | function shareValue(a, b) {
58 | for (var i = 0; i < a.length; i++) {
59 | if (b.indexOf(a[i]) !== -1) {
60 | return true;
61 | }
62 | }
63 | return false;
64 | }
65 |
66 | module.exports = {
67 | each: each,
68 | union: union,
69 | checkElementEquality: checkElementEquality,
70 | shareValue: shareValue
71 | };
72 |
--------------------------------------------------------------------------------
/lib/utilities/converter.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Converter
5 | *
6 | * Converts between 'sweet' (FamousFramework timeline)
7 | * and 'salty' (piecewise timeline) representations
8 | * for easier interfacing of the two timelines.
9 | */
10 |
11 | /**
12 | * Converts FamousFramework timeline
13 | * to piecewise timeline representation.
14 | */
15 | function sweetToSalty(sweetTimeline, options) {
16 | var saltyTimeline = {};
17 |
18 | options = options || {};
19 | var duration = options.duration || 0;
20 |
21 | for (var selector in sweetTimeline) {
22 | var selectorBehaviors = sweetTimeline[selector];
23 |
24 | for (var behavior in selectorBehaviors) {
25 | var flexframes = selectorBehaviors[behavior];
26 |
27 | var name = selector + '|' + behavior;
28 | if (!saltyTimeline[name]) saltyTimeline[name] = [];
29 |
30 | for (var frame in flexframes) {
31 | var change = flexframes[frame];
32 |
33 | var time = percentToNumber(frame, duration) || 0;
34 | var value = change.value || 0;
35 | var curve = change.curve || 'linear';
36 |
37 | saltyTimeline[name].push([time, value, curve]);
38 | }
39 | }
40 | }
41 |
42 | return saltyTimeline;
43 | }
44 |
45 | /**
46 | * Converts piecewise timeline
47 | * to FamousFramework timeline representation.
48 | */
49 | function saltyToSweet(saltyTimeline, options) {
50 | var sweetTimeline = {};
51 |
52 | options = options || {};
53 | var duration = options.duration || 5000;
54 |
55 | for (var selectorBehavior in saltyTimeline) {
56 | var flexframes = saltyTimeline[selectorBehavior];
57 |
58 | var selector = selectorBehavior.split('|')[0];
59 | var behavior = selectorBehavior.split('|')[1];
60 |
61 | if (!sweetTimeline[selector]) sweetTimeline[selector] = {};
62 | sweetTimeline[selector][behavior] = {};
63 |
64 | for (var i = 0; i < flexframes.length; i++) {
65 | var change = flexframes[i];
66 |
67 | var time = numberToPercent(change[0], duration);
68 | var value = change[1];
69 | var curve = change[2];
70 |
71 | sweetTimeline[selector][behavior][time] = {};
72 | sweetTimeline[selector][behavior][time].value = value;
73 |
74 | if (curve !== 'linear')
75 | sweetTimeline[selector][behavior][time].curve = curve;
76 | }
77 | }
78 |
79 | return sweetTimeline;
80 | }
81 |
82 | function percentToNumber(percentStr, total) {
83 | return (percentStr.split('%')[0] / 100) * total;
84 | }
85 |
86 | function numberToPercent(number, total) {
87 | return (number / total * 100) + '%';
88 | }
89 |
90 | module.exports = {
91 | sweetToSalty: sweetToSalty,
92 | saltyToSweet: saltyToSweet
93 | };
94 |
--------------------------------------------------------------------------------
/lib/utilities/function-parser.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Returns an array of the passed-in function's arguments.
5 | */
6 |
7 | var LPAREN = '(';
8 | var RPAREN = ')';
9 | var REGEXP = /([^\s,]+)/g;
10 |
11 | function getParameterNames(fn) {
12 | var fnString = fn.toString();
13 | var matches = fnString.slice(fnString.indexOf(LPAREN) + 1, fnString.indexOf(RPAREN)).match(REGEXP);
14 | return matches || [];
15 | }
16 |
17 | module.exports = {
18 | getParameterNames: getParameterNames
19 | };
20 |
--------------------------------------------------------------------------------
/lib/utilities/http.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // Make an HTTP GET request to the given URL, returning
4 | // the results to the given callback.
5 | function get(url, cb) {
6 | var xhr = new XMLHttpRequest();
7 | xhr.onreadystatechange = function() {
8 | if (xhr.readyState === 4 && xhr.status === 200) {
9 | cb(xhr.responseText);
10 | }
11 | };
12 | xhr.open('GET', url, true);
13 | xhr.send();
14 | }
15 |
16 | // GET request all of the given URLs, returning the
17 | // collection of results when all have completed.
18 | function join(urls, cb) {
19 | var total = 0;
20 | var length = urls.length;
21 | var out = [];
22 | if (length < 1) {
23 | return cb(out);
24 | }
25 | for (var i = 0; i < length; i++) {
26 | (function(idx) {
27 | var url = urls[idx];
28 | get(url, function(data) {
29 | total += 1;
30 | // Important! We guarantee that results are returned
31 | // in the same order the URLs were given in, hence
32 | // assigning via index rather than pushing.
33 | out[idx] = data;
34 | if (total === length) {
35 | cb(out);
36 | }
37 | });
38 | }(i));
39 | }
40 | }
41 |
42 | module.exports = {
43 | get: get,
44 | join: join
45 | };
46 |
--------------------------------------------------------------------------------
/lib/utilities/uid.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var BLANK_STR = '';
4 | var GLOBAL_PREFIX = '*';
5 | var DELIMITER = '-';
6 | var COUNTS = {};
7 |
8 | function counter(prefix) {
9 | if (COUNTS[prefix] === undefined) {
10 | COUNTS[prefix] = 0;
11 | return 0;
12 | }
13 | else {
14 | COUNTS[prefix] += 1;
15 | return COUNTS[prefix];
16 | }
17 | }
18 |
19 | function generate(group) {
20 | var prefix = (group || GLOBAL_PREFIX) + BLANK_STR;
21 | var count = counter(prefix) + BLANK_STR;
22 | var now = Date.now().toString();
23 | var rand = Math.random().toString(36).slice(2);
24 | return [prefix, count, now, rand].join(DELIMITER);
25 | }
26 |
27 | module.exports = {
28 | generate: generate
29 | };
30 |
--------------------------------------------------------------------------------
/lib/utilities/utilities.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var DataStore = require('./../data-store/data-store');
4 | var FunctionParser = require('./function-parser');
5 | var VirtualDOM = require('./../virtual-dom/virtual-dom');
6 |
7 | var FUNC_TYPE = 'function';
8 |
9 | function getParameterNames(obj) {
10 | if (typeof obj === FUNC_TYPE) {
11 | return FunctionParser.getParameterNames(obj);
12 | }
13 | else {
14 | return null;
15 | }
16 | }
17 |
18 | function getComponent(node) {
19 | return DataStore.getComponent(VirtualDOM.getUID(node));
20 | }
21 |
22 | function getParentComponent(node) {
23 | if (!node.parentNode) {
24 | throw new Error('Cannot get a parent component for a virtual dom node that does not have a parent');
25 | }
26 |
27 | return DataStore.getComponent(VirtualDOM.getParentUID(node));
28 | }
29 |
30 | function camelCase(input) {
31 | return input.toLowerCase().replace(/-(.)/g, function(match, group1) {
32 | return group1.toUpperCase();
33 | });
34 | }
35 |
36 | module.exports = {
37 | camelCase: camelCase,
38 | getComponent: getComponent,
39 | getParameterNames: getParameterNames,
40 | getParentComponent: getParentComponent
41 | };
42 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "famous-framework",
3 | "version": "0.12.1",
4 | "description": "A modern take on building reusable components and maintainable applications",
5 | "keywords": [
6 | "famous",
7 | "framework"
8 | ],
9 | "license": "MIT",
10 | "repository": "Famous/framework",
11 | "bugs": "https://github.com/Famous/framework/issues",
12 | "main": "lib/index.js",
13 | "authors": [
14 | "Zack Brown ",
15 | "Matthew Trost ",
16 | "Arkady Pevzner ",
17 | "Imtiaz Majeed ",
18 | "Jordan Papaleo ",
19 | "Larry Gordon "
20 | ],
21 | "bin": {
22 | "famous-framework": "bin/famous-framework.js"
23 | },
24 | "browser": {
25 | "jsdom": "./dev/build-pipeline/shims/jsdom.js"
26 | },
27 | "scripts": {
28 | "dev": "node bin/famous-framework.js local-only-bootstrap --sourceFolder=lib/core-components --destinationFolder=dev/local-workspace/build --servedFolder=dev/local-workspace --port=1618",
29 | "browserify-build-pipeline": "browserify dev/build-pipeline/index.js -t brfs",
30 | "test-build-pipeline": "node test/build-pipeline/index.spec.js",
31 | "test-runtime": "browserify test/runtime-tests/**/*.spec.js | tap-closer | smokestack",
32 | "test-state-manager": "browserify test/state-manager-tests/*.spec.js | tap-closer | smokestack",
33 | "test-utilities": "browserify test/utilities-tests/*.spec.js | tap-closer | smokestack",
34 | "lint": "eslint --ignore-path .eslintignore ."
35 | },
36 | "dependencies": {
37 | "async": "1.2.1",
38 | "babel": "5.5.8",
39 | "brfs": "^1.4.0",
40 | "browserify": "10.2.4",
41 | "chokidar": "1.0.3",
42 | "clone": "1.0.2",
43 | "commander": "2.8.1",
44 | "escodegen": "1.6.1",
45 | "esprima": "2.2.0",
46 | "estraverse": "4.1.0",
47 | "express": "4.12.4",
48 | "famous": "Famous/engine#v0.6.2",
49 | "jsdom": "3.1.2",
50 | "livereload": "0.3.7",
51 | "lodash.assign": "^3.2.0",
52 | "lodash.clone": "^3.0.2",
53 | "lodash.debounce": "^3.1.1",
54 | "lodash.defaults": "^3.1.2",
55 | "lodash.filter": "^3.1.1",
56 | "lodash.find": "^3.2.1",
57 | "lodash.first": "^3.0.0",
58 | "lodash.foreach": "^3.0.3",
59 | "lodash.last": "^3.0.0",
60 | "lodash.map": "^3.1.4",
61 | "lodash.pairs": "^3.0.1",
62 | "lodash.uniq": "^3.2.2",
63 | "mkdirp": "0.5.1",
64 | "ncp": "2.0.0",
65 | "pubsub-js": "^1.5.2",
66 | "recursive-readdir": "1.2.1",
67 | "rimraf": "^2.4.0",
68 | "watchify": "3.2.2"
69 | },
70 | "devDependencies": {
71 | "babel-eslint": "3.1.15",
72 | "eslint": "0.23.0",
73 | "jsdoc": "3.3.2",
74 | "smokestack": "3.3.0",
75 | "tap-closer": "1.0.0",
76 | "tape": "4.0.0"
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/test/build-pipeline/index.spec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Path = require('path');
4 | var Test = require('tape');
5 |
6 | var LocalAssistant = require('./../../dev/local-assistant/local-assistant');
7 |
8 | var COMPONENTS_BASE_FOLDER = Path.join(__dirname, '..', '..', 'lib', 'core-components');
9 | var DESTINATION_FOLDER = Path.join(__dirname, '..', '..', 'dev', 'local-workspace', 'build');
10 |
11 | Test('build pipeline', function(t) {
12 | t.plan(3);
13 |
14 | var la = new LocalAssistant({
15 | sourceFolder: COMPONENTS_BASE_FOLDER,
16 | destinationFolder: DESTINATION_FOLDER
17 | });
18 |
19 | var componentFolder = Path.join('famous-demos', 'clickable-square');
20 |
21 | la.buildSingle(COMPONENTS_BASE_FOLDER, componentFolder, function(buildSingleErr, moduleName, files, data) {
22 | if (buildSingleErr) {
23 | return console.error(buildSingleErr);
24 | }
25 |
26 | t.ok(moduleName, 'module name was output');
27 | t.ok(files, 'files were output');
28 | t.ok(data, 'data was output');
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/test/runtime-tests/helpers/virtual-dom-stub.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /*
4 | Virtual DOM Stub One:
5 |
6 | wrapper
7 | parent:element#PARENT
8 | child:element.FIRST_CHILD(uid=0)
9 | grandchild:element
10 | greatgrandchild:element
11 | child:element(uid=1)
12 | grandchild:element
13 | child:element(uid=2)
14 | grandchild:element
15 | child:element(uid=3)
16 | child:element(uid=4)
17 | child:element(uid=5)
18 | */
19 |
20 | var STUB_ONE_INFO = {
21 | PARENT_ID: 'PARENT',
22 | FIRST_CHILD_CLASS_NAME: 'FIRST_CHILD',
23 | CHILD_NAME: 'child:element',
24 | GRANDCHILD_NAME: 'grandchild:element',
25 | GREAT_GRANDCHILD_NAME: 'greatgrandchild:element',
26 | GRANDCHILDREN_COUNT: 3,
27 | CHILD_COUNT: 6,
28 | UID_KEY: 'uid'
29 | };
30 |
31 | function createStubOne () {
32 | var wrapper = document.createElement('wrapper');
33 | var parent = document.createElement('parent:element');
34 | parent.id = STUB_ONE_INFO.PARENT_ID;
35 | wrapper.appendChild(parent);
36 |
37 | var child;
38 | var grandchild;
39 | var greatgrandchild;
40 | for(var i = 0; i < STUB_ONE_INFO.CHILD_COUNT; i++) {
41 | child = document.createElement('child:element');
42 | child.setAttribute(STUB_ONE_INFO.UID_KEY, i);
43 | parent.appendChild(child);
44 | if (i === 0) {
45 | child.className = STUB_ONE_INFO.FIRST_CHILD_CLASS_NAME;
46 | }
47 | if (i < STUB_ONE_INFO.GRANDCHILDREN_COUNT) {
48 | grandchild = document.createElement(STUB_ONE_INFO.GRANDCHILD_NAME);
49 | if (i === 0) {
50 | greatgrandchild = document.createElement(STUB_ONE_INFO.GREAT_GRANDCHILD_NAME);
51 | grandchild.appendChild(greatgrandchild);
52 | }
53 | child.appendChild(grandchild);
54 | }
55 | }
56 |
57 | return wrapper;
58 | }
59 |
60 | module.exports = {
61 | stubOneInfo: STUB_ONE_INFO,
62 | getStubOne: createStubOne
63 | };
64 |
--------------------------------------------------------------------------------
/test/runtime-tests/main/index.spec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | window.Famous = require('famous');
4 | var test = require('tape');
5 | var FamousFramework = require('./../../../lib');
6 | var DataStore = require('./../../../lib/data-store/data-store');
7 |
8 | test('----- FamousFramework', function(t) {
9 | t.plan(1);
10 |
11 | t.test('exports', function(st) {
12 | st.plan(4);
13 | st.ok(FamousFramework, 'FamousFramework exports');
14 | st.ok(DataStore, 'DataStore exports');
15 | st.ok(FamousFramework.register && FamousFramework.execute && FamousFramework.message && FamousFramework.deploy, 'FamousFramework exports register/execture/message/deploy');
16 | st.ok(FamousFramework.register === FamousFramework.scene && FamousFramework.register === FamousFramework.module && FamousFramework.register === FamousFramework.component, 'FamousFramework aliases `scene`/`module`/`component` to `register`.');
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/test/state-manager-tests/fixtures.js:
--------------------------------------------------------------------------------
1 | var state = {
2 | number: 1,
3 | string: 'two',
4 | array: [3, 3, 3],
5 | boolean: true,
6 | nestedState: {
7 | moreNesting: {
8 | nestingArray: [1, 2, 3]
9 | }
10 | }
11 | };
12 |
13 | var observerState = {
14 | args: [],
15 | hasFired: false,
16 | hasFiredMoreThanOnce: false
17 | };
18 |
19 | // Deep-clone the given object.
20 | function clone(b) {
21 | var a;
22 | if (typeof b === 'object') {
23 | a = (b instanceof Array) ? [] : {};
24 | for (var key in b) {
25 | if (typeof b[key] === 'object' && b[key] !== null) {
26 | if (b[key] instanceof Array) {
27 | a[key] = new Array(b[key].length);
28 | for (var i = 0; i < b[key].length; i++) {
29 | a[key][i] = clone(b[key][i]);
30 | }
31 | }
32 | else {
33 | a[key] = clone(b[key]);
34 | }
35 | }
36 | else {
37 | a[key] = b[key];
38 | }
39 | }
40 | }
41 | else {
42 | a = b;
43 | }
44 | return a;
45 | }
46 |
47 | module.exports = {
48 | state: state,
49 | clone: clone,
50 | observerState: observerState
51 | };
52 |
--------------------------------------------------------------------------------
/test/utilities-tests/converter.spec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var test = require('tape');
4 |
5 | var converter = require('./../../lib/utilities/converter');
6 |
7 | var toSalty = converter.sweetToSalty;
8 | var toSweet = converter.saltyToSweet;
9 |
10 | var sweetTimeline = {
11 | '#pen': {
12 | 'position': {
13 | '0%' : { value: [0, 0, 0], curve: 'outExpo' },
14 | '100%' : { value: [1, 1, 1] }
15 | },
16 | 'size': {
17 | '0%' : { value: [0, 0], curve: 'outExpo' },
18 | '50%' : { value: [9, 9] }
19 | }
20 | }
21 | };
22 |
23 | var saltyTimeline = {
24 | '#pen|position': [
25 | [0, [0, 0, 0], 'outExpo'],
26 | [1000, [1, 1, 1], 'linear']
27 | ],
28 | '#pen|size': [
29 | [0, [0, 0], 'outExpo'],
30 | [500, [9, 9], 'linear']
31 | ]
32 | };
33 |
34 | test('convert between timeline representations', function(t) {
35 | t.plan(2);
36 |
37 | var options = { duration: 1000 };
38 |
39 | var actualSaltyTimeline = toSalty(sweetTimeline, options);
40 | t.deepEqual(actualSaltyTimeline, saltyTimeline, 'should convert sweet to salty');
41 |
42 | var actualySweetTimeline = toSweet(saltyTimeline, options);
43 | t.deepEqual(actualySweetTimeline, sweetTimeline, 'should convert salty to sweet');
44 | });
45 |
46 |
--------------------------------------------------------------------------------
/test/utilities-tests/function-parser.spec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var test = require('tape');
4 | var functionParser = require('./../../lib/utilities/function-parser');
5 | var getParameterNames = functionParser.getParameterNames;
6 |
7 | var fn = function(one, two, three, four) {};
8 | function func(one, two, three, four) {}
9 | var fnArgs = ['one', 'two', 'three', 'four'];
10 |
11 | test('getParameterNames', function(t) {
12 | t.plan(3);
13 | t.ok(getParameterNames, 'exports');
14 | t.same(getParameterNames(fn), fnArgs, 'should return function arguments for function expressions');
15 | t.same(getParameterNames(func), fnArgs, 'should return function arguments for function declarations');
16 | t.end();
17 | });
18 |
--------------------------------------------------------------------------------