<commit_before>(function(hello) {

	hello.init({

		flickr: {

			name: 'Flickr',

			// Ensure that you define an oauth_proxy
			oauth: {
				version: '1.0a',
				auth: 'https://www.flickr.com/services/oauth/authorize?perms=read',
				request: 'https://www.flickr.com/services/oauth/request_token',
				token: 'https://www.flickr.com/services/oauth/access_token'
			},

			// API base URL
			base: 'https://api.flickr.com/services/rest',

			// Map GET resquests
			get: {
				me: sign('flickr.people.getInfo'),
				'me/friends': sign('flickr.contacts.getList', {per_page:'@{limit|50}'}),
				'me/following': sign('flickr.contacts.getList', {per_page:'@{limit|50}'}),
				'me/followers': sign('flickr.contacts.getList', {per_page:'@{limit|50}'}),
				'me/albums': sign('flickr.photosets.getList', {per_page:'@{limit|50}'}),
				'me/album' : sign('flickr.photosets.getPhotos&photoset_id=@{id}'),
				'me/photos': sign('flickr.people.getPhotos', {per_page:'@{limit|50}'})
			},

			wrap: {
				me: function(o) {
					formatError(o);
					o = checkResponse(o, 'person');
					if (o.id) {
						if (o.realname) {
							o.name = o.realname._content;
							var m = o.name.split(' ');
							o.first_name = m[0];
							o.last_name = m[1];
						}

						o.thumbnail = getBuddyIcon(o, 'l');
						o.picture = getBuddyIcon(o, 'l');
					}

					return o;
				},

				'me/friends': formatFriends,
				'me/followers': formatFriends,
				'me/following': formatFriends,
				'me/albums': function(o) {
					formatError(o);
					o = checkResponse(o, 'photosets');
					paging(o);
					if (o.photoset) {
						o.data = o.photoset;
						o.data.forEach(function(item) {
							item.name = item.title._content;
							item.photos = 'https://api.flickr.com/services/rest' + getApiUrl('flickr.photosets.getPhotos', {photoset_id: item.id}, true);
						});

						delete o.photoset;
					}

					return o;
				},

				'me/photos': function(o) {
					formatError(o);
					return formatPhotos(o);
				},

				'default': function(o) {
					formatError(o);
					return formatPhotos(o);
				}
			},

			xhr: false,

			jsonp: function(p, qs) {
				if (p.method == 'get') {
					delete qs.callback;
					qs.jsoncallback = p.callbackID;
				}
			}
		}
	});

	function getApiUrl(method, extraParams, skipNetwork) {
		var url = ((skipNetwork) ? '' : 'flickr:') +
			'?method=' + method +
			'&api_key=' + hello.services.flickr.id +
			'&format=json';
		for (var param in extraParams) {
			if (extraParams.hasOwnProperty(param)) {
				url += '&' + param + '=' + extraParams[param];
			}
		}

		return url;
	}

	// This is not exactly neat but avoid to call
	// The method 'flickr.test.login' for each api call

	function withUser(cb) {
		var auth = hello.getAuthResponse('flickr');
		cb(auth && auth.user_nsid ? auth.user_nsid : null);
	}

	function sign(url, params) {
		if (!params) {
			params = {};
		}

		return function(p, callback) {
			withUser(function(userId) {
				params.user_id = userId;
				callback(getApiUrl(url, params, true));
			});
		};
	}

	function getBuddyIcon(profile, size) {
		var url = 'https://www.flickr.com/images/buddyicon.gif';
		if (profile.nsid && profile.iconserver && profile.iconfarm) {
			url = 'https://farm' + profile.iconfarm + '.staticflickr.com/' +
				profile.iconserver + '/' +
				'buddyicons/' + profile.nsid +
				((size) ? '_' + size : '') + '.jpg';
		}

		return url;
	}

	function getPhoto(id, farm, server, secret, size) {
		size = (size) ? '_' + size : '';
		return 'https://farm' + farm + '.staticflickr.com/' + server + '/' + id + '_' + secret + size + '.jpg';
	}

	function formatUser(o) {
	}

	function formatError(o) {
		if (o && o.stat && o.stat.toLowerCase() != 'ok') {
			o.error = {
				code: 'invalid_request',
				message: o.message
			};
		}
	}

	function formatPhotos(o) {
		if (o.photoset || o.photos) {
			var set = ('photoset' in o) ? 'photoset' : 'photos';
			o = checkResponse(o, set);
			paging(o);
			o.data = o.photo;
			delete o.photo;
			for (var i = 0; i < o.data.length; i++) {
				var photo = o.data[i];
				photo.name = photo.title;
				photo.picture = getPhoto(photo.id, photo.farm, photo.server, photo.secret, '');
				photo.source = getPhoto(photo.id, photo.farm, photo.server, photo.secret, 'b');
				photo.thumbnail = getPhoto(photo.id, photo.farm, photo.server, photo.secret, 'm');
			}
		}

		return o;
	}

	function checkResponse(o, key) {

		if (key in o) {
			o = o[key];
		}
		else if (!('error' in o)) {
			o.error = {
				code: 'invalid_request',
				message: o.message || 'Failed to get data from Flickr'
			};
		}

		return o;
	}

	function formatFriends(o) {
		formatError(o);
		if (o.contacts) {
			o = checkResponse(o, 'contacts');
			paging(o);
			o.data = o.contact;
			delete o.contact;
			for (var i = 0; i < o.data.length; i++) {
				var item = o.data[i];
				item.id = item.nsid;
				item.name = item.realname || item.username;
				item.thumbnail = getBuddyIcon(item, 'm');
			}
		}

		return o;
	}

	function paging(res) {
		if (res.page && res.pages && res.page !== res.pages) {
			res.paging = {
				next: '?page=' + (++res.page)
			};
		}
	}

})(hello);
<commit_msg>realized that params are supposed to be done this way<commit_after>(function(hello) {

	hello.init({

		flickr: {

			name: 'Flickr',

			// Ensure that you define an oauth_proxy
			oauth: {
				version: '1.0a',
				auth: 'https://www.flickr.com/services/oauth/authorize?perms=read',
				request: 'https://www.flickr.com/services/oauth/request_token',
				token: 'https://www.flickr.com/services/oauth/access_token'
			},

			// API base URL
			base: 'https://api.flickr.com/services/rest',

			// Map GET resquests
			get: {
				me: sign('flickr.people.getInfo'),
				'me/friends': sign('flickr.contacts.getList', {per_page:'@{limit|50}'}),
				'me/following': sign('flickr.contacts.getList', {per_page:'@{limit|50}'}),
				'me/followers': sign('flickr.contacts.getList', {per_page:'@{limit|50}'}),
				'me/albums': sign('flickr.photosets.getList', {per_page:'@{limit|50}'}),
				'me/album' : sign('flickr.photosets.getPhotos', {photoset_id: '@{id}'}),
				'me/photos': sign('flickr.people.getPhotos', {per_page:'@{limit|50}'})
			},

			wrap: {
				me: function(o) {
					formatError(o);
					o = checkResponse(o, 'person');
					if (o.id) {
						if (o.realname) {
							o.name = o.realname._content;
							var m = o.name.split(' ');
							o.first_name = m[0];
							o.last_name = m[1];
						}

						o.thumbnail = getBuddyIcon(o, 'l');
						o.picture = getBuddyIcon(o, 'l');
					}

					return o;
				},

				'me/friends': formatFriends,
				'me/followers': formatFriends,
				'me/following': formatFriends,
				'me/albums': function(o) {
					formatError(o);
					o = checkResponse(o, 'photosets');
					paging(o);
					if (o.photoset) {
						o.data = o.photoset;
						o.data.forEach(function(item) {
							item.name = item.title._content;
							item.photos = 'https://api.flickr.com/services/rest' + getApiUrl('flickr.photosets.getPhotos', {photoset_id: item.id}, true);
						});

						delete o.photoset;
					}

					return o;
				},

				'me/photos': function(o) {
					formatError(o);
					return formatPhotos(o);
				},

				'default': function(o) {
					formatError(o);
					return formatPhotos(o);
				}
			},

			xhr: false,

			jsonp: function(p, qs) {
				if (p.method == 'get') {
					delete qs.callback;
					qs.jsoncallback = p.callbackID;
				}
			}
		}
	});

	function getApiUrl(method, extraParams, skipNetwork) {
		var url = ((skipNetwork) ? '' : 'flickr:') +
			'?method=' + method +
			'&api_key=' + hello.services.flickr.id +
			'&format=json';
		for (var param in extraParams) {
			if (extraParams.hasOwnProperty(param)) {
				url += '&' + param + '=' + extraParams[param];
			}
		}

		return url;
	}

	// This is not exactly neat but avoid to call
	// The method 'flickr.test.login' for each api call

	function withUser(cb) {
		var auth = hello.getAuthResponse('flickr');
		cb(auth && auth.user_nsid ? auth.user_nsid : null);
	}

	function sign(url, params) {
		if (!params) {
			params = {};
		}

		return function(p, callback) {
			withUser(function(userId) {
				params.user_id = userId;
				callback(getApiUrl(url, params, true));
			});
		};
	}

	function getBuddyIcon(profile, size) {
		var url = 'https://www.flickr.com/images/buddyicon.gif';
		if (profile.nsid && profile.iconserver && profile.iconfarm) {
			url = 'https://farm' + profile.iconfarm + '.staticflickr.com/' +
				profile.iconserver + '/' +
				'buddyicons/' + profile.nsid +
				((size) ? '_' + size : '') + '.jpg';
		}

		return url;
	}

	function getPhoto(id, farm, server, secret, size) {
		size = (size) ? '_' + size : '';
		return 'https://farm' + farm + '.staticflickr.com/' + server + '/' + id + '_' + secret + size + '.jpg';
	}

	function formatUser(o) {
	}

	function formatError(o) {
		if (o && o.stat && o.stat.toLowerCase() != 'ok') {
			o.error = {
				code: 'invalid_request',
				message: o.message
			};
		}
	}

	function formatPhotos(o) {
		if (o.photoset || o.photos) {
			var set = ('photoset' in o) ? 'photoset' : 'photos';
			o = checkResponse(o, set);
			paging(o);
			o.data = o.photo;
			delete o.photo;
			for (var i = 0; i < o.data.length; i++) {
				var photo = o.data[i];
				photo.name = photo.title;
				photo.picture = getPhoto(photo.id, photo.farm, photo.server, photo.secret, '');
				photo.source = getPhoto(photo.id, photo.farm, photo.server, photo.secret, 'b');
				photo.thumbnail = getPhoto(photo.id, photo.farm, photo.server, photo.secret, 'm');
			}
		}

		return o;
	}

	function checkResponse(o, key) {

		if (key in o) {
			o = o[key];
		}
		else if (!('error' in o)) {
			o.error = {
				code: 'invalid_request',
				message: o.message || 'Failed to get data from Flickr'
			};
		}

		return o;
	}

	function formatFriends(o) {
		formatError(o);
		if (o.contacts) {
			o = checkResponse(o, 'contacts');
			paging(o);
			o.data = o.contact;
			delete o.contact;
			for (var i = 0; i < o.data.length; i++) {
				var item = o.data[i];
				item.id = item.nsid;
				item.name = item.realname || item.username;
				item.thumbnail = getBuddyIcon(item, 'm');
			}
		}

		return o;
	}

	function paging(res) {
		if (res.page && res.pages && res.page !== res.pages) {
			res.paging = {
				next: '?page=' + (++res.page)
			};
		}
	}

})(hello);
<|endoftext|>


<commit_before>(function() {

// relies on global var WORKER_ID

var updateRate = 10, timeoutRate = 180,
    testTimeout, pauseTimer, testResults = {},
    workQueueId, workerId=WORKER_ID;

jQuery( doWork );

if ( window.addEventListener ) {
    window.addEventListener( "message", handleMessage, false );
} else if ( window.attachEvent ) {
    window.attachEvent( "onmessage", handleMessage );
}

var cmds = {
    run_test: function(params) {
        testResults = {};
        workQueueId = params.work_queue_id;
        log("Running: " +
            params.name + " at " + params.url +
            " [" + workQueueId.toString() + "]");

        var iframe = document.createElement("iframe");
        iframe.width = 1000;
        iframe.height = 600;
        iframe.className = "test";
        iframe.src = params.url + '?_=' + (new Date).getTime();
        jQuery("#iframes").append( iframe );

        var loadTimeout = 10000;
        var failedToLoad = setTimeout(function() {
            runtimeError('Failed to load the test suite in ' + loadTimeout/1000 + ' seconds');
        }, loadTimeout);

        jQuery(iframe).load(function(e) {
            clearTimeout(failedToLoad);
        });

        // The iframe must communicate back to us
        // with window.top.postMessage.
        // See handleMessage() for how those are received.

        // Timeout after a period of time
        testTimeout = setTimeout(function() {
            runtimeError('Timed out waiting for test results');
        }, timeoutRate * 1000 );
    },
    restart: function() {
        var noCache = true;
        window.location.reload(noCache);
    },
    change_rate: function( num ) {
        updateRate = parseInt( num );
    }
};

function doWork() {
    workQueueId = null;
    msg("Getting work from server...");
    retrySend("/work/query",
              {worker_id: workerId, user_agent: navigator.userAgent},
               doWork, doServerCmd);
}

function doServerCmd( data ) {
    if ( data.cmd ) {
        if ( typeof cmds[ data.cmd ] === "function" ) {
            cmds[ data.cmd ].apply( cmds, data.args );
        } else {
            log("Received an unknown command: " + data.cmd);
        }
    } else {
        clearTimeout( pauseTimer );

        var run_msg = data.desc || "No command from server.";

        msg(run_msg);

        var timeLeft = updateRate;

        pauseTimer = setTimeout(function leftTimer(){
            msg(run_msg + " Checking again in " + timeLeft + " seconds.");
            if ( timeLeft-- >= 1 ) {
                pauseTimer = setTimeout( leftTimer, 1000 );
            } else {
                doWork();
            }
        }, 1000);
    }
}

function done() {
    cancelTest();
    setTimeout(doWork, 3);
}

function cancelTest() {
    if ( testTimeout ) {
        clearTimeout( testTimeout );
        testTimeout = 0;
    }

    jQuery("iframe").remove();
}

function runtimeError(msg) {
    cancelTest();
    var msg = {
        test_run_error: true,
        test_run_error_msg: msg
    }
    log(msg);
    retrySend('/work/submit_results', {
            work_queue_id: workQueueId,
            results: JSON.stringify(msg)
        },
        runtimeError, doWork );
}

function parseQueryStr(qs) {
    var obj = {},
        vars = qs.split("&");
    jQuery.each(vars, function(i, val) {
        var parts = val.split('=');
        obj[parts[0]] = decodeURI(parts[1]);
    });
    return obj;
}

function handleMessage(msg){
    var obj = parseQueryStr(msg.data);
    switch (obj.action) {
        case 'hello':
            testResults.user_agent = obj.user_agent;
            break;
        case 'set_test':
            testResults._current_test = obj.name;
            break;
        case 'set_module':
            testResults._current_module = obj.name;
            break;
        case 'log':
            if (typeof(testResults.tests) === 'undefined') {
                testResults.tests = [];
            }
            testResults.tests.push({
                module: testResults._current_module,
                test: testResults._current_test,
                result: obj.result == 'true' ? true: false,
                message: obj.message,
                stacktrace: obj.stacktrace
            });
            break;
        case 'done':
            log("failures: " + obj.failures + "; total: " + obj.total);
            testResults.failures = parseInt(obj.failures, 10);
            testResults.total = parseInt(obj.total, 10);
            retrySend( '/work/submit_results',
                        {work_queue_id: workQueueId,
                         results: JSON.stringify(testResults)},
                        function() {
                            handleMessage(msg);
                        }, done );
            break;
        default:
            throw new Error("Unknown action: " + obj.action);
            break;
    }
}

var errorOut = 0;

function retrySend( url, data, retry, success ) {
    jQuery.ajax({
        type: "POST",
        url: url,
        timeout: 10000,
        cache: false,
        data: data,
        error: function() {
            if ( errorOut++ > 4 ) {
                cmds.restart();
            } else {
                msg("Error connecting to server, retrying...");
                setTimeout( retry, 15000 );
            }
        },
        success: function(){
            errorOut = 0;
            msg("Sent data to server successfully");
            success.apply( this, arguments );
        },
        dataType: 'json'
    });
}

function log( txt ) {
    jQuery("#history").prepend( "
" +
        (new Date).toString().replace(/^\w+ /, "").replace(/:[^:]+$/, "") +
        ": " + txt + "
" );
    msg( txt );
}

function msg( txt ) {
    jQuery("#msg").html( "[worker=" + workerId.toString() + "] " + txt );
}

})();
<commit_msg>fixes typo in runtime error message logged by worker<commit_after>(function() {

// relies on global var WORKER_ID

var updateRate = 10, timeoutRate = 180,
    testTimeout, pauseTimer, testResults = {},
    workQueueId, workerId=WORKER_ID;

jQuery( doWork );

if ( window.addEventListener ) {
    window.addEventListener( "message", handleMessage, false );
} else if ( window.attachEvent ) {
    window.attachEvent( "onmessage", handleMessage );
}

var cmds = {
    run_test: function(params) {
        testResults = {};
        workQueueId = params.work_queue_id;
        log("Running: " +
            params.name + " at " + params.url +
            " [" + workQueueId.toString() + "]");

        var iframe = document.createElement("iframe");
        iframe.width = 1000;
        iframe.height = 600;
        iframe.className = "test";
        iframe.src = params.url + '?_=' + (new Date).getTime();
        jQuery("#iframes").append( iframe );

        var loadTimeout = 10000;
        var failedToLoad = setTimeout(function() {
            runtimeError('Failed to load the test suite in ' + loadTimeout/1000 + ' seconds');
        }, loadTimeout);

        jQuery(iframe).load(function(e) {
            clearTimeout(failedToLoad);
        });

        // The iframe must communicate back to us
        // with window.top.postMessage.
        // See handleMessage() for how those are received.

        // Timeout after a period of time
        testTimeout = setTimeout(function() {
            runtimeError('Timed out waiting for test results');
        }, timeoutRate * 1000 );
    },
    restart: function() {
        var noCache = true;
        window.location.reload(noCache);
    },
    change_rate: function( num ) {
        updateRate = parseInt( num );
    }
};

function doWork() {
    workQueueId = null;
    msg("Getting work from server...");
    retrySend("/work/query",
              {worker_id: workerId, user_agent: navigator.userAgent},
               doWork, doServerCmd);
}

function doServerCmd( data ) {
    if ( data.cmd ) {
        if ( typeof cmds[ data.cmd ] === "function" ) {
            cmds[ data.cmd ].apply( cmds, data.args );
        } else {
            log("Received an unknown command: " + data.cmd);
        }
    } else {
        clearTimeout( pauseTimer );

        var run_msg = data.desc || "No command from server.";

        msg(run_msg);

        var timeLeft = updateRate;

        pauseTimer = setTimeout(function leftTimer(){
            msg(run_msg + " Checking again in " + timeLeft + " seconds.");
            if ( timeLeft-- >= 1 ) {
                pauseTimer = setTimeout( leftTimer, 1000 );
            } else {
                doWork();
            }
        }, 1000);
    }
}

function done() {
    cancelTest();
    setTimeout(doWork, 3);
}

function cancelTest() {
    if ( testTimeout ) {
        clearTimeout( testTimeout );
        testTimeout = 0;
    }

    jQuery("iframe").remove();
}

function runtimeError(errorMsg) {
    cancelTest();
    var msg = {
        test_run_error: true,
        test_run_error_msg: errorMsg
    }
    log(msg.test_run_error_msg);
    retrySend('/work/submit_results', {
            work_queue_id: workQueueId,
            results: JSON.stringify(msg)
        },
        runtimeError, doWork );
}

function parseQueryStr(qs) {
    var obj = {},
        vars = qs.split("&");
    jQuery.each(vars, function(i, val) {
        var parts = val.split('=');
        obj[parts[0]] = decodeURI(parts[1]);
    });
    return obj;
}

function handleMessage(msg){
    var obj = parseQueryStr(msg.data);
    switch (obj.action) {
        case 'hello':
            testResults.user_agent = obj.user_agent;
            break;
        case 'set_test':
            testResults._current_test = obj.name;
            break;
        case 'set_module':
            testResults._current_module = obj.name;
            break;
        case 'log':
            if (typeof(testResults.tests) === 'undefined') {
                testResults.tests = [];
            }
            testResults.tests.push({
                module: testResults._current_module,
                test: testResults._current_test,
                result: obj.result == 'true' ? true: false,
                message: obj.message,
                stacktrace: obj.stacktrace
            });
            break;
        case 'done':
            log("failures: " + obj.failures + "; total: " + obj.total);
            testResults.failures = parseInt(obj.failures, 10);
            testResults.total = parseInt(obj.total, 10);
            retrySend( '/work/submit_results',
                        {work_queue_id: workQueueId,
                         results: JSON.stringify(testResults)},
                        function() {
                            handleMessage(msg);
                        }, done );
            break;
        default:
            throw new Error("Unknown action: " + obj.action);
            break;
    }
}

var errorOut = 0;

function retrySend( url, data, retry, success ) {
    jQuery.ajax({
        type: "POST",
        url: url,
        timeout: 10000,
        cache: false,
        data: data,
        error: function() {
            if ( errorOut++ > 4 ) {
                cmds.restart();
            } else {
                msg("Error connecting to server, retrying...");
                setTimeout( retry, 15000 );
            }
        },
        success: function(){
            errorOut = 0;
            msg("Sent data to server successfully");
            success.apply( this, arguments );
        },
        dataType: 'json'
    });
}

function log( txt ) {
    jQuery("#history").prepend( "
" +
        (new Date).toString().replace(/^\w+ /, "").replace(/:[^:]+$/, "") +
        ": " + txt + "
" );
    msg( txt );
}

function msg( txt ) {
    jQuery("#msg").html( "[worker=" + workerId.toString() + "] " + txt );
}

})();
<|endoftext|>


<commit_before>module("WebGL Picking tests", {
    setup : function() {
        stop();
        var that = this;
        this.cb = function(e) {
            ok(true, "Scene loaded");
            that.doc = document.getElementById("xml3dframe").contentDocument;
            start();
        };
        loadDocument("scenes/webgl-ambient.xhtml"+window.location.search, this.cb);
    },
    teardown : function() {
        var v = document.getElementById("xml3dframe");
        v.removeEventListener("load", this.cb, true);
    }
});

test("Check current pick object (internal)", 5, function() {
    var xml3dElement = this.doc.getElementById("xml3DElem");
    var h = getHandler(xml3dElement);
    var picked = h.updatePickObjectByPoint(88,60);
    ok(h.currentPickObj, "Object picked");
    strictEqual(h.currentPickObj, picked, "Return value matches");
    strictEqual(h.currentPickObj, this.doc.getElementById("pickingMesh1"), "Picked object 'pickingMesh1'");
});

test("xml3d Apadater getElementByPoint test", 4, function() {
    var xml3dElement = this.doc.getElementById("xml3DElem");
    var element = xml3dElement.getElementByPoint(88,60);
    ok(element, "Object picked");
    strictEqual(element, this.doc.getElementById("pickingMesh1"));
});
<commit_msg>Added test for picking no object<commit_after>module("WebGL Picking tests", {
    setup : function() {
        stop();
        var that = this;
        this.cb = function(e) {
            ok(true, "Scene loaded");
            that.doc = document.getElementById("xml3dframe").contentDocument;
            start();
        };
        loadDocument("scenes/webgl-ambient.xhtml"+window.location.search, this.cb);
    },
    teardown : function() {
        var v = document.getElementById("xml3dframe");
        v.removeEventListener("load", this.cb, true);
    }
});

test("Check current pick object (internal)", function() {
    var xml3dElement = this.doc.getElementById("xml3DElem");
    var h = getHandler(xml3dElement);
    var picked = h.updatePickObjectByPoint(88,60);
    ok(h.currentPickObj, "Object picked");
    strictEqual(h.currentPickObj, picked, "Return value matches");
    strictEqual(h.currentPickObj, this.doc.getElementById("pickingMesh1"), "Picked object 'pickingMesh1'");

    picked = h.updatePickObjectByPoint(5,5);
    strictEqual(h.currentPickObj, null, "Nothing picked");
    strictEqual(h.currentPickObj, picked, "Return value matches");
});

test("xml3d Apadater getElementByPoint test", 4, function() {
    var xml3dElement = this.doc.getElementById("xml3DElem");
    var element = xml3dElement.getElementByPoint(88,60);
    ok(element, "Object picked");
    strictEqual(element, this.doc.getElementById("pickingMesh1"));
});
<|endoftext|>


<commit_before>module.exports = {
	is: function (possibleObj) {
		return (!!possibleObj) && (possibleObj.constructor === Object);
	},
	length: function(obj) {
		return Object.keys(obj).length;
	},
	has: function(obj, property) {
		return obj.hasOwnProperty(property);
	}
};<commit_msg>add .get<commit_after>module.exports = {
	is: function (possibleObj) {
		return (!!possibleObj) && (possibleObj.constructor === Object);
	},
	length: function(obj) {
		return Object.keys(obj).length;
	},
	has: function(obj, property) {
		return obj.hasOwnProperty(property);
	},
	get: function(obj, key) {
		if(typeof obj === 'undefined') return false;
		var index = prop.indexOf('.');

		if(index > -1) {
			return this.get(obj[prop.substring(0, index)], prop.substr(index + 1));
		}

		return obj[prop];
	},
};<|endoftext|>


<commit_before>'use strict';

var Fx = require('../../components/fx');
var Registry = require('../../registry');
var Color = require('../../components/color');

var fillText = require('../../lib').fillText;
var getLineWidth = require('./helpers').getLineWidth;
var hoverLabelText = require('../../plots/cartesian/axes').hoverLabelText;
var BADNUM = require('../../constants/numerical').BADNUM;

function hoverPoints(pointData, xval, yval, hovermode, opts) {
    var barPointData = hoverOnBars(pointData, xval, yval, hovermode, opts);

    if(barPointData) {
        var cd = barPointData.cd;
        var trace = cd[0].trace;
        var di = cd[barPointData.index];

        barPointData.color = getTraceColor(trace, di);
        Registry.getComponentMethod('errorbars', 'hoverInfo')(di, trace, barPointData);

        return [barPointData];
    }
}

function hoverOnBars(pointData, xval, yval, hovermode, opts) {
    var cd = pointData.cd;
    var trace = cd[0].trace;
    var t = cd[0].t;
    var isClosest = (hovermode === 'closest');
    var isWaterfall = (trace.type === 'waterfall');
    var maxHoverDistance = pointData.maxHoverDistance;
    var maxSpikeDistance = pointData.maxSpikeDistance;

    var posVal, sizeVal, posLetter, sizeLetter, dx, dy, pRangeCalc;

    if(trace.orientation === 'h') {
        posVal = yval;
        sizeVal = xval;
        posLetter = 'y';
        sizeLetter = 'x';
        dx = sizeFn;
        dy = positionFn;
    } else {
        posVal = xval;
        sizeVal = yval;
        posLetter = 'x';
        sizeLetter = 'y';
        dy = sizeFn;
        dx = positionFn;
    }

    var period = trace[posLetter + 'period'];
    var isClosestOrPeriod = isClosest || period;

    function thisBarMinPos(di) { return thisBarExtPos(di, -1); }
    function thisBarMaxPos(di) { return thisBarExtPos(di, 1); }

    function thisBarExtPos(di, sgn) {
        var w = (period) ? di.wPeriod : di.w;

        return di[posLetter] + sgn * w / 2;
    }

    var minPos = isClosestOrPeriod ?
        thisBarMinPos :
        function(di) {
            /*
             * In compare mode, accept a bar if you're on it *or* its group.
             * Nearly always it's the group that matters, but in case the bar
             * was explicitly set wider than its group we'd better accept the
             * whole bar.
             *
             * use `bardelta` instead of `bargroupwidth` so we accept hover
             * in the gap. That way hover doesn't flash on and off as you
             * mouse over the plot in compare modes.
             * In 'closest' mode though the flashing seems inevitable,
             * without far more complex logic
             */
            return Math.min(thisBarMinPos(di), di.p - t.bardelta / 2);
        };

    var maxPos = isClosestOrPeriod ?
        thisBarMaxPos :
        function(di) {
            return Math.max(thisBarMaxPos(di), di.p + t.bardelta / 2);
        };

    function inbox(_minPos, _maxPos, maxDistance) {
        if(opts.finiteRange) maxDistance = 0;

        // add a little to the pseudo-distance for wider bars, so that like scatter,
        // if you are over two overlapping bars, the narrower one wins.
        return Fx.inbox(_minPos - posVal, _maxPos - posVal,
            maxDistance + Math.min(1, Math.abs(_maxPos - _minPos) / pRangeCalc) - 1);
    }

    function positionFn(di) {
        return inbox(minPos(di), maxPos(di), maxHoverDistance);
    }

    function thisBarPositionFn(di) {
        return inbox(thisBarMinPos(di), thisBarMaxPos(di), maxSpikeDistance);
    }

    function getSize(di) {
        var s = di[sizeLetter];

        if(isWaterfall) {
            var rawS = Math.abs(di.rawS) || 0;
            if(sizeVal > 0) {
                s += rawS;
            } else if(sizeVal < 0) {
                s -= rawS;
            }
        }

        return s;
    }

    function sizeFn(di) {
        var v = sizeVal;
        var b = di.b;
        var s = getSize(di);

        // add a gradient so hovering near the end of a
        // bar makes it a little closer match
        return Fx.inbox(b - v, s - v, maxHoverDistance + (s - v) / (s - b) - 1);
    }

    function thisBarSizeFn(di) {
        var v = sizeVal;
        var b = di.b;
        var s = getSize(di);

        // add a gradient so hovering near the end of a
        // bar makes it a little closer match
        return Fx.inbox(b - v, s - v, maxSpikeDistance + (s - v) / (s - b) - 1);
    }

    var pa = pointData[posLetter + 'a'];
    var sa = pointData[sizeLetter + 'a'];

    pRangeCalc = Math.abs(pa.r2c(pa.range[1]) - pa.r2c(pa.range[0]));

    function dxy(di) { return (dx(di) + dy(di)) / 2; }
    var distfn = Fx.getDistanceFunction(hovermode, dx, dy, dxy);
    Fx.getClosest(cd, distfn, pointData);

    // skip the rest (for this trace) if we didn't find a close point
    if(pointData.index === false) return;

    // skip points inside axis rangebreaks
    if(cd[pointData.index].p === BADNUM) return;

    // if we get here and we're not in 'closest' mode, push min/max pos back
    // onto the group - even though that means occasionally the mouse will be
    // over the hover label.
    if(!isClosestOrPeriod) {
        minPos = function(di) {
            return Math.min(thisBarMinPos(di), di.p - t.bargroupwidth / 2);
        };
        maxPos = function(di) {
            return Math.max(thisBarMaxPos(di), di.p + t.bargroupwidth / 2);
        };
    }

    // the closest data point
    var index = pointData.index;
    var di = cd[index];

    var size = (trace.base) ? di.b + di.s : di.s;
    pointData[sizeLetter + '0'] = pointData[sizeLetter + '1'] = sa.c2p(di[sizeLetter], true);
    pointData[sizeLetter + 'LabelVal'] = size;

    var extent = t.extents[t.extents.round(di.p)];
    pointData[posLetter + '0'] = pa.c2p(isClosest ? minPos(di) : extent[0], true);
    pointData[posLetter + '1'] = pa.c2p(isClosest ? maxPos(di) : extent[1], true);

    var hasPeriod = di.orig_p !== undefined;
    pointData[posLetter + 'LabelVal'] = hasPeriod ? di.orig_p : di.p;

    pointData.labelLabel = hoverLabelText(pa, pointData[posLetter + 'LabelVal'], trace[posLetter + 'hoverformat']);
    pointData.valueLabel = hoverLabelText(sa, pointData[sizeLetter + 'LabelVal'], trace[sizeLetter + 'hoverformat']);
    pointData.baseLabel = hoverLabelText(sa, di.b, trace[sizeLetter + 'hoverformat']);

    // spikelines always want "closest" distance regardless of hovermode
    pointData.spikeDistance = (thisBarSizeFn(di) + thisBarPositionFn(di)) / 2;
    // they also want to point to the data value, regardless of where the label goes
    // in case of bars shifted within groups
    pointData[posLetter + 'Spike'] = pa.c2p(di.p, true);

    fillText(di, trace, pointData);
    pointData.hovertemplate = trace.hovertemplate;

    return pointData;
}

function getTraceColor(trace, di) {
    var mc = di.mcc || trace.marker.color;
    var mlc = di.mlcc || trace.marker.line.color;
    var mlw = getLineWidth(trace, di);

    if(Color.opacity(mc)) return mc;
    else if(Color.opacity(mlc) && mlw) return mlc;
}

module.exports = {
    hoverPoints: hoverPoints,
    hoverOnBars: hoverOnBars,
    getTraceColor: getTraceColor
};
<commit_msg>fixing hover for period group bars issue 5841<commit_after>'use strict';

var Fx = require('../../components/fx');
var Registry = require('../../registry');
var Color = require('../../components/color');

var fillText = require('../../lib').fillText;
var getLineWidth = require('./helpers').getLineWidth;
var hoverLabelText = require('../../plots/cartesian/axes').hoverLabelText;
var BADNUM = require('../../constants/numerical').BADNUM;

function hoverPoints(pointData, xval, yval, hovermode, opts) {
    var barPointData = hoverOnBars(pointData, xval, yval, hovermode, opts);

    if(barPointData) {
        var cd = barPointData.cd;
        var trace = cd[0].trace;
        var di = cd[barPointData.index];

        barPointData.color = getTraceColor(trace, di);
        Registry.getComponentMethod('errorbars', 'hoverInfo')(di, trace, barPointData);

        return [barPointData];
    }
}

function hoverOnBars(pointData, xval, yval, hovermode, opts) {
    var cd = pointData.cd;
    var trace = cd[0].trace;
    var t = cd[0].t;
    var isClosest = (hovermode === 'closest');
    var isWaterfall = (trace.type === 'waterfall');
    var maxHoverDistance = pointData.maxHoverDistance;
    var maxSpikeDistance = pointData.maxSpikeDistance;

    var posVal, sizeVal, posLetter, sizeLetter, dx, dy, pRangeCalc;

    if(trace.orientation === 'h') {
        posVal = yval;
        sizeVal = xval;
        posLetter = 'y';
        sizeLetter = 'x';
        dx = sizeFn;
        dy = positionFn;
    } else {
        posVal = xval;
        sizeVal = yval;
        posLetter = 'x';
        sizeLetter = 'y';
        dy = sizeFn;
        dx = positionFn;
    }

    var period = trace[posLetter + 'period'];
    var isClosestOrPeriod = isClosest || period;

    function thisBarMinPos(di) { return thisBarExtPos(di, -1); }
    function thisBarMaxPos(di) { return thisBarExtPos(di, 1); }

    function thisBarExtPos(di, sgn) {
        var w = di.w;

        return di[posLetter] + sgn * w / 2;
    }

    var minPos = isClosest ?
        thisBarMinPos : period ?
        function(di) {
            var diff = di.pEnd - di.pStart;
            return di.p + diff / 2 - di.wPeriod;
        } :
        function(di) {
            /*
             * In compare mode, accept a bar if you're on it *or* its group.
             * Nearly always it's the group that matters, but in case the bar
             * was explicitly set wider than its group we'd better accept the
             * whole bar.
             *
             * use `bardelta` instead of `bargroupwidth` so we accept hover
             * in the gap. That way hover doesn't flash on and off as you
             * mouse over the plot in compare modes.
             * In 'closest' mode though the flashing seems inevitable,
             * without far more complex logic
             */
            return Math.min(thisBarMinPos(di), di.p - t.bardelta / 2);
        };

    var maxPos = isClosest ?
        thisBarMaxPos : period ?
        function(di) {
            var diff = di.pEnd - di.pStart;
            return di.p + diff / 2;
        } :
        function(di) {
            return Math.max(thisBarMaxPos(di), di.p + t.bardelta / 2);
        };

    function inbox(_minPos, _maxPos, maxDistance) {
        if(opts.finiteRange) maxDistance = 0;

        // add a little to the pseudo-distance for wider bars, so that like scatter,
        // if you are over two overlapping bars, the narrower one wins.
        return Fx.inbox(_minPos - posVal, _maxPos - posVal,
            maxDistance + Math.min(1, Math.abs(_maxPos - _minPos) / pRangeCalc) - 1);
    }

    function positionFn(di) {
        return inbox(minPos(di), maxPos(di), maxHoverDistance);
    }

    function thisBarPositionFn(di) {
        return inbox(thisBarMinPos(di), thisBarMaxPos(di), maxSpikeDistance);
    }

    function getSize(di) {
        var s = di[sizeLetter];

        if(isWaterfall) {
            var rawS = Math.abs(di.rawS) || 0;
            if(sizeVal > 0) {
                s += rawS;
            } else if(sizeVal < 0) {
                s -= rawS;
            }
        }

        return s;
    }

    function sizeFn(di) {
        var v = sizeVal;
        var b = di.b;
        var s = getSize(di);

        // add a gradient so hovering near the end of a
        // bar makes it a little closer match
        return Fx.inbox(b - v, s - v, maxHoverDistance + (s - v) / (s - b) - 1);
    }

    function thisBarSizeFn(di) {
        var v = sizeVal;
        var b = di.b;
        var s = getSize(di);

        // add a gradient so hovering near the end of a
        // bar makes it a little closer match
        return Fx.inbox(b - v, s - v, maxSpikeDistance + (s - v) / (s - b) - 1);
    }

    var pa = pointData[posLetter + 'a'];
    var sa = pointData[sizeLetter + 'a'];

    pRangeCalc = Math.abs(pa.r2c(pa.range[1]) - pa.r2c(pa.range[0]));

    function dxy(di) { return (dx(di) + dy(di)) / 2; }
    var distfn = Fx.getDistanceFunction(hovermode, dx, dy, dxy);
    Fx.getClosest(cd, distfn, pointData);

    // skip the rest (for this trace) if we didn't find a close point
    if(pointData.index === false) return;

    // skip points inside axis rangebreaks
    if(cd[pointData.index].p === BADNUM) return;

    // if we get here and we're not in 'closest' mode, push min/max pos back
    // onto the group - even though that means occasionally the mouse will be
    // over the hover label.
    if(!isClosestOrPeriod) {
        minPos = function(di) {
            return Math.min(thisBarMinPos(di), di.p - t.bargroupwidth / 2);
        };
        maxPos = function(di) {
            return Math.max(thisBarMaxPos(di), di.p + t.bargroupwidth / 2);
        };
    }

    // the closest data point
    var index = pointData.index;
    var di = cd[index];

    var size = (trace.base) ? di.b + di.s : di.s;
    pointData[sizeLetter + '0'] = pointData[sizeLetter + '1'] = sa.c2p(di[sizeLetter], true);
    pointData[sizeLetter + 'LabelVal'] = size;

    var extent = t.extents[t.extents.round(di.p)];
    pointData[posLetter + '0'] = pa.c2p(isClosest ? minPos(di) : extent[0], true);
    pointData[posLetter + '1'] = pa.c2p(isClosest ? maxPos(di) : extent[1], true);

    var hasPeriod = di.orig_p !== undefined;
    pointData[posLetter + 'LabelVal'] = hasPeriod ? di.orig_p : di.p;

    pointData.labelLabel = hoverLabelText(pa, pointData[posLetter + 'LabelVal'], trace[posLetter + 'hoverformat']);
    pointData.valueLabel = hoverLabelText(sa, pointData[sizeLetter + 'LabelVal'], trace[sizeLetter + 'hoverformat']);
    pointData.baseLabel = hoverLabelText(sa, di.b, trace[sizeLetter + 'hoverformat']);

    // spikelines always want "closest" distance regardless of hovermode
    pointData.spikeDistance = (thisBarSizeFn(di) + thisBarPositionFn(di)) / 2;
    // they also want to point to the data value, regardless of where the label goes
    // in case of bars shifted within groups
    pointData[posLetter + 'Spike'] = pa.c2p(di.p, true);

    fillText(di, trace, pointData);
    pointData.hovertemplate = trace.hovertemplate;

    return pointData;
}

function getTraceColor(trace, di) {
    var mc = di.mcc || trace.marker.color;
    var mlc = di.mlcc || trace.marker.line.color;
    var mlw = getLineWidth(trace, di);

    if(Color.opacity(mc)) return mc;
    else if(Color.opacity(mlc) && mlw) return mlc;
}

module.exports = {
    hoverPoints: hoverPoints,
    hoverOnBars: hoverOnBars,
    getTraceColor: getTraceColor
};
<|endoftext|>


<commit_before>
console.log("hi");

var shape1 = new VectorObject(50, 30);
var shape2 = new VectorObject(60, 70);

function setup() {
	createCanvas(400, 400);
	frameRate(5);
}

function draw() {

	ellipse(shape1.x, shape1.y, 50, 50);
	ellipse(shape2.x, shape2.y, 50, 50);
	var added = shape1.add(shape2);
	console.log(added.x);
	ellipse(added.x, added.y, 30, 30);
}

function VectorObject (x,y) {
	this.x = x;
	this.y = y;
}

VectorObject.prototype.add = function (VecObj) {

	var addedX = this.x + VecObj.x;
	var addedY = this.y + VecObj.y;

	return new VectorObject(addedX, addedY);
}

console.log(shape1.x);<commit_msg>bouncing ball with custom objects<commit_after>

console.log("hi");

var shape1 = new VectorObject(50, 30);
var shape2 = new VectorObject(10, 5);

function setup() {
	createCanvas(500, 500);
	frameRate(0);
}

function draw() {
	background(100, 200, 200);
	fill(50, 60, 70);
	ellipse(shape1.x, shape1.y, 50, 50);

	//var added = shape1.add(shape2);
	shape1 = shape1.add(shape2);
	//console.log(added.x);

	ellipse(shape1.x, shape1.y, 30, 30);

	if (shape1.x > width || shape1.x < 0) {
		shape2.x = (shape2.x * -1);
	}
	if (shape1.y > height || shape1.y < 0) {
		shape2.y = (shape2.y * -1);
	}
}

function VectorObject (x,y) {
	this.x = x;
	this.y = y;
}

VectorObject.prototype.add = function (VecObj) {

	var addedX = this.x + VecObj.x;
	var addedY = this.y + VecObj.y;

	return new VectorObject(addedX, addedY);
}

console.log(shape1.x);<|endoftext|>


<commit_before>//     (c) 2012 Michael Aufreiter
//     Data.js is freely distributable under the MIT license.
//     Portions of Data.js are inspired or borrowed from Underscore.js,
//     Backbone.js and Google's Visualization API.
//     For all details and documentation:
//     http://substance.io/michael/data-js

(function(root){

var _,
    util,
    errors,
    Chronicle;

if (typeof exports !== 'undefined') {
  _    = require('underscore');
  // Should be require('substance-util') in the future
  util   = require('./lib/util/util');
  errors   = require('./lib/util/errors');
  Chronicle = require('./lib/chronicle/chronicle');
} else {
  _ = root._;
  util = root.Substance.util;
  errors   = root.Substance.errors;
  Chronicle   = root.Substance.Chronicle;
}

var ArrayOperation = Chronicle.OT.ArrayOperation;
var TextOperation = Chronicle.OT.TextOperation;

// Initial Setup
// -------------

// The top-level namespace. All public Data.js classes and modules will
// be attached to this. Exported for both CommonJS and the browser.
var Data = {};

// Current version of the library. Keep in sync with `package.json`.
Data.VERSION = '0.7.0';

// Top Level API
// -------

Data.VALUE_TYPES = [
  'string',
  'object',
  'number',
  'boolean',
  'date'
];

Data.isValueType = function (type) {
  return _.include(Data.VALUE_TYPES, _.last(type));
};

// Data.Graph
// --------------

// A `Data.Graph` can be used for representing arbitrary complex object
// graphs. Relations between objects are expressed through links that
// point to referred objects. Data.Graphs can be traversed in various ways.
// See the testsuite for usage.

Data.Graph = function(schema) {
  this.schema = schema;

  this.nodes = {};
  this.indexes = {
    "comments": {},
    "annotations": {}
  };
};

Data.Graph.__prototype__ = function() {

  this.getTypes = function(typeId) {
    var type = this.schema.types[typeId];
    if (type.parent) {
      return [type.parent, typeId];
    } else {
      return [typeId];
    }
  };

  // Rebuild all indexes
  this.buildIndexes =  function() {
    this.indexes = {};
    _.each(this.nodes, function(node) {
      _.each(this.schema.indexes, function(index, key) {
        this.addToIndex(key, node);
      }, this);
    }, this);
  };

  // Add node to index
  this.addToIndex = function(node) {

    var self = this;
    function add(index) {
      var indexSpec = self.schema.indexes[index];
      var indexes = self.indexes;

      var idx = indexes[index];
      if (!_.include(self.getTypes(node.type), indexSpec.type)) return;

      // Create index if it doesn't exist
      var prop = indexSpec.properties[0];
      if (prop) {
        if (!idx) idx = indexes[index] = {};
        if (!node[prop]) return; // skip falsy values
        // Scoped by one property
        if (!idx[node[prop]]) {
          idx[node[prop]] = [node.id];
        } else {
          idx[node[prop]].push(node.id);
        }
      } else {
        // Flat indexes
        if (!idx) idx = indexes[index] = [];
        idx.push(node.id);
      }
    }

    _.each(this.schema.indexes, function(index, key) {
      add(key);
    });
  };

  // Silently remove node from index
  // --------

  this.removeFromIndex = function(node) {
    var self = this;
    function remove(index) {
      var indexSpec = self.schema.indexes[index];
      var indexes = self.indexes;
      var scopes = indexes[index];

      // Remove when source
      if (scopes[node.id]) {
        delete scopes[node.id];
      }

      if (!_.include(self.getTypes(node.type), indexSpec.type)) return;

      // Remove when target
      var prop = indexSpec.properties[0];

      var nodes = scopes[node[prop]];
      if (nodes) {
        scopes[node[prop]] = _.without(nodes, node.id);
      }
    }

    _.each(this.schema.indexes, function(index, key) {
      remove(key);
    });
  };

  // TODO: Prettify -> Code duplication alert
  this.updateIndex = function(node, prevNode) {

    var self = this;
    function update(index) {
      var indexSpec = self.schema.indexes[index];
      var indexes = self.indexes;

      var scopes = indexes[index];

      if (!_.include(self.getTypes(node.type), indexSpec.type)) return;

      // Remove when target
      var prop = indexSpec.properties[0];

      var nodes = scopes[prevNode[prop]];
      if (nodes) {
        scopes[prevNode[prop]] = _.without(nodes, prevNode.id);
      }

      // Create index if it doesn't exist
      if (!scopes) scopes = indexes[index] = {};
      prop = indexSpec.properties[0];

      if (!scopes[node[prop]]) {
        scopes[node[prop]] = [node.id];
      } else {
        scopes[node[prop]].push(node.id);
      }
    }

    _.each(this.schema.indexes, function(index, key) {
      update(key);
    });
  };

  // View Traversal
  // --------

  this.traverse = function(view) {
    return _.map(this.views[view], function(node) {
      return this.nodes[node];
    }, this);
  };

  // Find data nodes based on index
  // --------

  this.find = function(index, scope) {
    var indexes = this.indexes;
    var nodes = this.nodes;

    function wrap(nodeIds) {
      return _.map(nodeIds, function(n) {
        return nodes[n];
      });
    }

    if (!indexes[index]) return []; // throw index-not-found error instead?
    if (_.isArray(indexes[index])) return wrap(indexes[index]);
    if (!indexes[index][scope]) return [];

    return wrap(indexes[index][scope]);
  };

  this.get = function(id) {
    return this.nodes[id];
  };

  this.create = function(node) {
    this.nodes[node.id] = util.deepclone(node);
    this.addToIndex(node);
    return this;
  };

  // Delete node by id, referenced nodes remain untouched
  this.delete = function(id) {
    // TODO: update indexes
    this.removeFromIndex(this.nodes[id]);
    delete this.nodes[id];
  };

  this.exec = function(command) {
    console.log("Executing command: ", command);
    new Data.Graph.Command(command).apply(this);
  };

  this.resolve = function(path) {
    if (path.length === 0) return this;

    // resolve the item for manipulation
    // TODO: it would be great if we could resolve references stored in properties (using schema)
    var node = this.get(path[0]);
    for (var idx = 1; idx < path.length; idx++) {
      node = node[path[idx]];
      if (node === undefined) {
        throw new Error("Key error: could not find element for path " + JSON.stringify(path));
      }
    }
    return node;
  };

  this.properties = function(type) {
    var result = type.parent ? this.schema.types[type.parent].properties : {};
    _.extend(result, type.properties);
    return result;
  };

  this.propertyType = function(node, key) {
    var properties = this.properties(this.schema.types[node.type]);
    return properties[key];
  };

  this.reset = function() {
    this.nodes = {};

    // TODO: derive from schema
    this.indexes = {
      "comments": {},
      "annotations": {}
    };
  };

};

Data.Graph.prototype = _.extend(new Data.Graph.__prototype__(), util.Events);

var GraphMethods = function() {

  this.NOP = function() {
  };

  // Node manipulation
  // --------

  this.create = function(graph, path, args) {
    graph.create(args);
  };

  this.delete = function(graph, path, args) {
    graph.delete(args.id);
  };

  // Array manipulation
  // --------

  this.pop = function(graph, path) {
    var array = graph.resolve(path);
    array.pop();
  };

  this.push = function(graph, path, args) {
    var array = graph.resolve(path);
    array.push(args.value);
  };

  this.insert = function(graph, path, args) {
    var array = graph.resolve(path);
    array.splice(args.index, 0, args.value);
  };

  // Diff based update
  // --------

  this.update = function(graph, path, args) {

    var property = new Data.Graph.Property(graph, path);
    var oldNode = util.deepclone(property.node);
    var op;

    if (property.type === 'string') {
      try {
        op = TextOperation.fromJSON(args);
      } catch (err) {
        throw new Error("Illegal argument: provided diff is not a valid TextOperation: " + args);
      }
      property.set(op.apply(property.get()));
    } else if (property.type === 'array') {
      try {
        op = ArrayOperation.fromJSON(args);
      } catch (err) {
        throw new Error("Illegal argument: provided diff is not a valid ArrayOperation: " + args);
      }
      // Note: the array operation works inplace
      op.apply(property.get());
    } else {
      throw new Error("Illegal type: incremental update not available for type " + property.type);
    }

    graph.updateIndex(property.node, oldNode);
  };

};

var GraphCommand = function(options) {

  if (!options) throw new Error("Illegal argument: expected command spec, was " + options);

  // convert the convenient array notation into the internal object notation
  if (_.isArray(options)) {
    var op = options[0];
    var path = options.slice(1);
    var args = _.last(path);

    options = {
      op: op,
      path: path
    };

    if (_.isObject(args)) {
      options.args = path.pop();
    }
  }

  this.op = options.op;
  this.path = options.path;
  this.args = options.args;

};

GraphCommand.__prototype__ = function() {

  var methods = new GraphMethods();

  this.apply = function(graph) {
    if (!methods[this.op]) {
      throw new Error("Unknown operation: " + this.op);
    }

    methods[this.op](graph, this.path, this.args);
  };

  this.copy = function() {
    return new GraphCommand(this);
  };

  this.toJSON = function() {
    return {
      op: this.op,
      path: this.path,
      args: this.args
    };
  };

};
GraphCommand.prototype = new GraphCommand.__prototype__();

var Property = function(graph, path) {
  this.key = _.last(path);
  this.node = graph.resolve(path.slice(0, -1));
  if (this.node === undefined) {
    throw new Error("Could not look up property for path " + path.join("."));
  }
  this.type = graph.propertyType(this.node, this.key);
};

Property.prototype = {
  get: function() {
    return this.node[this.key];
  },

  set: function(value) {
    this.node[this.key] = value;
  }
};

Data.Graph.Command = GraphCommand;
Data.Graph.Property = Property;

if (typeof exports !== 'undefined') {
  exports = Data;
} else {
  root.Substance.Data = Data;
}

})(this);
<commit_msg>More sophisticated property types.<commit_after>//     (c) 2012 Michael Aufreiter
//     Data.js is freely distributable under the MIT license.
//     Portions of Data.js are inspired or borrowed from Underscore.js,
//     Backbone.js and Google's Visualization API.
//     For all details and documentation:
//     http://substance.io/michael/data-js

(function(root){

var _,
    util,
    errors,
    Chronicle;

if (typeof exports !== 'undefined') {
  _    = require('underscore');
  // Should be require('substance-util') in the future
  util   = require('./lib/util/util');
  errors   = require('./lib/util/errors');
  Chronicle = require('./lib/chronicle/chronicle');
} else {
  _ = root._;
  util = root.Substance.util;
  errors   = root.Substance.errors;
  Chronicle   = root.Substance.Chronicle;
}

var ArrayOperation = Chronicle.OT.ArrayOperation;
var TextOperation = Chronicle.OT.TextOperation;

// Initial Setup
// -------------

// The top-level namespace. All public Data.js classes and modules will
// be attached to this. Exported for both CommonJS and the browser.
var Data = {};

// Current version of the library. Keep in sync with `package.json`.
Data.VERSION = '0.7.0';

// Top Level API
// -------

Data.VALUE_TYPES = [
  'string',
  'object',
  'number',
  'boolean',
  'date'
];

Data.isValueType = function (type) {
  return _.include(Data.VALUE_TYPES, _.last(type));
};

// Data.Graph
// --------------

// A `Data.Graph` can be used for representing arbitrary complex object
// graphs. Relations between objects are expressed through links that
// point to referred objects. Data.Graphs can be traversed in various ways.
// See the testsuite for usage.

Data.Graph = function(schema) {
  this.schema = schema;

  this.nodes = {};
  this.indexes = {
    "comments": {},
    "annotations": {}
  };
};

Data.Graph.__prototype__ = function() {

  this.getTypes = function(typeId) {
    var type = this.schema.types[typeId];
    if (type.parent) {
      return [type.parent, typeId];
    } else {
      return [typeId];
    }
  };

  // Rebuild all indexes
  this.buildIndexes =  function() {
    this.indexes = {};
    _.each(this.nodes, function(node) {
      _.each(this.schema.indexes, function(index, key) {
        this.addToIndex(key, node);
      }, this);
    }, this);
  };

  // Add node to index
  this.addToIndex = function(node) {

    var self = this;
    function add(index) {
      var indexSpec = self.schema.indexes[index];
      var indexes = self.indexes;

      var idx = indexes[index];
      if (!_.include(self.getTypes(node.type), indexSpec.type)) return;

      // Create index if it doesn't exist
      var prop = indexSpec.properties[0];
      if (prop) {
        if (!idx) idx = indexes[index] = {};
        if (!node[prop]) return; // skip falsy values
        // Scoped by one property
        if (!idx[node[prop]]) {
          idx[node[prop]] = [node.id];
        } else {
          idx[node[prop]].push(node.id);
        }
      } else {
        // Flat indexes
        if (!idx) idx = indexes[index] = [];
        idx.push(node.id);
      }
    }

    _.each(this.schema.indexes, function(index, key) {
      add(key);
    });
  };

  // Silently remove node from index
  // --------

  this.removeFromIndex = function(node) {
    var self = this;
    function remove(index) {
      var indexSpec = self.schema.indexes[index];
      var indexes = self.indexes;
      var scopes = indexes[index];

      // Remove when source
      if (scopes[node.id]) {
        delete scopes[node.id];
      }

      if (!_.include(self.getTypes(node.type), indexSpec.type)) return;

      // Remove when target
      var prop = indexSpec.properties[0];

      var nodes = scopes[node[prop]];
      if (nodes) {
        scopes[node[prop]] = _.without(nodes, node.id);
      }
    }

    _.each(this.schema.indexes, function(index, key) {
      remove(key);
    });
  };

  // TODO: Prettify -> Code duplication alert
  this.updateIndex = function(node, prevNode) {

    var self = this;
    function update(index) {
      var indexSpec = self.schema.indexes[index];
      var indexes = self.indexes;

      var scopes = indexes[index];

      if (!_.include(self.getTypes(node.type), indexSpec.type)) return;

      // Remove when target
      var prop = indexSpec.properties[0];

      var nodes = scopes[prevNode[prop]];
      if (nodes) {
        scopes[prevNode[prop]] = _.without(nodes, prevNode.id);
      }

      // Create index if it doesn't exist
      if (!scopes) scopes = indexes[index] = {};
      prop = indexSpec.properties[0];

      if (!scopes[node[prop]]) {
        scopes[node[prop]] = [node.id];
      } else {
        scopes[node[prop]].push(node.id);
      }
    }

    _.each(this.schema.indexes, function(index, key) {
      update(key);
    });
  };

  // View Traversal
  // --------

  this.traverse = function(view) {
    return _.map(this.views[view], function(node) {
      return this.nodes[node];
    }, this);
  };

  // Find data nodes based on index
  // --------

  this.find = function(index, scope) {
    var indexes = this.indexes;
    var nodes = this.nodes;

    function wrap(nodeIds) {
      return _.map(nodeIds, function(n) {
        return nodes[n];
      });
    }

    if (!indexes[index]) return []; // throw index-not-found error instead?
    if (_.isArray(indexes[index])) return wrap(indexes[index]);
    if (!indexes[index][scope]) return [];

    return wrap(indexes[index][scope]);
  };

  this.get = function(id) {
    return this.nodes[id];
  };

  this.create = function(node) {
    this.nodes[node.id] = util.deepclone(node);
    this.addToIndex(node);
    return this;
  };

  // Delete node by id, referenced nodes remain untouched
  this.delete = function(id) {
    // TODO: update indexes
    this.removeFromIndex(this.nodes[id]);
    delete this.nodes[id];
  };

  this.exec = function(command) {
    console.log("Executing command: ", command);
    new Data.Graph.Command(command).apply(this);
  };

  this.resolve = function(path) {
    if (path.length === 0) return this;

    // resolve the item for manipulation
    // TODO: it would be great if we could resolve references stored in properties (using schema)
    var node = this.get(path[0]);
    for (var idx = 1; idx < path.length; idx++) {
      node = node[path[idx]];
      if (node === undefined) {
        throw new Error("Key error: could not find element for path " + JSON.stringify(path));
      }
    }
    return node;
  };

  this.properties = function(type) {
    var result = type.parent ? this.schema.types[type.parent].properties : {};
    _.extend(result, type.properties);
    return result;
  };

  // Returns the property type
  // TODO: should take typename, key instead of node object, key
  this.propertyType = function(node, key) {
    var properties = this.properties(this.schema.types[node.type]);
    var type = properties[key];
    return _.isArray(type) ? type : [type];
  };

  // Returns just the basetype
  // TODO: should take typename, key instead of node object, key
  this.propertyBaseType = function(node, key) {
    return this.propertyType(node, key)[0];
  };

  this.reset = function() {
    this.nodes = {};

    // TODO: derive from schema
    this.indexes = {
      "comments": {},
      "annotations": {}
    };
  };

};

Data.Graph.prototype = _.extend(new Data.Graph.__prototype__(), util.Events);

var GraphMethods = function() {

  this.NOP = function() {
  };

  // Node manipulation
  // --------

  this.create = function(graph, path, args) {
    graph.create(args);
  };

  this.delete = function(graph, path, args) {
    graph.delete(args.id);
  };

  // Array manipulation
  // --------

  this.pop = function(graph, path) {
    var array = graph.resolve(path);
    array.pop();
  };

  this.push = function(graph, path, args) {
    var array = graph.resolve(path);
    array.push(args.value);
  };

  this.insert = function(graph, path, args) {
    var array = graph.resolve(path);
    array.splice(args.index, 0, args.value);
  };

  // Diff based update
  // --------

  this.update = function(graph, path, args) {

    var property = new Data.Graph.Property(graph, path);
    var oldNode = util.deepclone(property.node);
    var op;

    if (property.baseType === 'string') {
      try {
        op = TextOperation.fromJSON(args);
      } catch (err) {
        throw new Error("Illegal argument: provided diff is not a valid TextOperation: " + args);
      }
      property.set(op.apply(property.get()));
    } else if (property.baseType === 'array') {
      try {
        op = ArrayOperation.fromJSON(args);
      } catch (err) {
        throw new Error("Illegal argument: provided diff is not a valid ArrayOperation: " + args);
      }
      // Note: the array operation works inplace
      op.apply(property.get());
    } else {
      console.log('PROP', property);
      throw new Error("Illegal type: incremental update not available for type " + property.baseType);
    }

    graph.updateIndex(property.node, oldNode);
  };

};

var GraphCommand = function(options) {

  if (!options) throw new Error("Illegal argument: expected command spec, was " + options);

  // convert the convenient array notation into the internal object notation
  if (_.isArray(options)) {
    var op = options[0];
    var path = options.slice(1);
    var args = _.last(path);

    options = {
      op: op,
      path: path
    };

    if (_.isObject(args)) {
      options.args = path.pop();
    }
  }

  this.op = options.op;
  this.path = options.path;
  this.args = options.args;
};

GraphCommand.__prototype__ = function() {

  var methods = new GraphMethods();

  this.apply = function(graph) {
    if (!methods[this.op]) {
      throw new Error("Unknown operation: " + this.op);
    }

    methods[this.op](graph, this.path, this.args);
  };

  this.copy = function() {
    return new GraphCommand(this);
  };

  this.toJSON = function() {
    return {
      op: this.op,
      path: this.path,
      args: this.args
    };
  };

};
GraphCommand.prototype = new GraphCommand.__prototype__();

var Property = function(graph, path) {
  this.key = _.last(path);
  this.node = graph.resolve(path.slice(0, -1));
  if (this.node === undefined) {
    throw new Error("Could not look up property for path " + path.join("."));
  }

  this.type = graph.propertyType(this.node, this.key);
  this.baseType = this.type[0];
};

Property.prototype = {
  get: function() {
    return this.node[this.key];
  },

  set: function(value) {
    this.node[this.key] = value;
  }
};

Data.Graph.Command = GraphCommand;
Data.Graph.Property = Property;

if (typeof exports !== 'undefined') {
  exports = Data;
} else {
  root.Substance.Data = Data;
}

})(this);
<|endoftext|>


<commit_before>function addEventHandler(e,event,handler){
  if(e.addEventListener){
    e.addEventListener(event,handler,false);
  }else if(e.attachEvent){
    e.attachEvent("on"+event,handler);
  }else{
    e["on"+event] = handler;
  }
}
var inputbox = document.getElementById("thenumber");
var leftin = document.getElementById("btn-in-left");
var rightin = document.getElementById("btn-in-right");
var leftout = document.getElementById("btn-out-left");
var rightout = document.getElementById("btn-out-right");
var numberbox=document.getElementsByClassName("box-number")[0];
var sortbtn = document.getElementById("btn-bubble-sort");
//addEventHandler(inputbox,"blur",checkInput);
addEventHandler(leftin,"click",leftInQueue);
addEventHandler(rightin,"click",rightInQueue);
addEventHandler(leftout,"click",leftOutQueue);
addEventHandler(rightout,"click",rightOutQueue);
addEventHandler(sortbtn,"click",bubbleSort);

function bubbleSort(){
  var divs = numberbox.getElementsByTagName("div");
  var arr = new Array();
  for(var i=0;i<divs.length;i++){
    var temp = divs[i].innerHTML;
    arr.push(parseInt(temp));
  }
  myBubbleSort(arr);
//  arr.sort();
  console.log(arr.sort());
  /*
  numberbox.innerHTML=arr.map(function(key){
    return "
"+key+"
";
  }).join("");
  */
}

function myBubbleSort(a){
  var timer = null;

//  timer = setInterval("run()",50);

  for(var i=0;i<a.length-1;i++){
    for(var j=0;ja[j+1]){
      //  function run(){
        console.log("a: "+a);
        render(a,j);
        var tmp = a[j];
        a[j]=a[j+1];
        a[j+1]=tmp;
        console.log("a: "+a);
        render(a,j);
      // setTimeout(render(a,j),2000);
      //  }
    //    clearInterval(timer);
      }
    }
  }

}

function render(array,a){
  var content="";
  for(var i=0;i<array.length;i++){
    if(i==a || i==a+1){
      content+="
"+array[i]+"
";
    }else{
      content+="
"+array[i]+"
";
    }
  }
  numberbox.innerHTML = content;
}

function leftInQueue(){
  if(checkInput()){
  var num = getValue();
//  console.log("checkInput"+checkInput());
//  if(typeof num!="undefined")
    var div = document.createElement("div");
    var text = document.createTextNode(num);
    div.className="num-element";
    div.style.height=num+"px";
    //div.style.lineHeight=num+"px";
    div.appendChild(text);
    numberbox.insertBefore(div,numberbox.firstChild);
  }
}

function rightInQueue(){
  if(checkInput()){
  var num = getValue();
  var div = document.createElement("div");
  var text = document.createTextNode(num);
  div.className="num-element";
  div.style.height=num+"px";
//  div.style.lineHeight=num+"px";
  div.appendChild(text);
  numberbox.appendChild(div);
  }
}
function leftOutQueue(){
  if(numberbox.hasChildNodes){
  alert("remove "+numberbox.firstChild.innerHTML);
  numberbox.removeChild(numberbox.firstChild);
  }
}
function rightOutQueue(){
  if(numberbox.hasChildNodes){
  alert("remove "+numberbox.lastChild.innerHTML);
  numberbox.removeChild(numberbox.lastChild);
  }
}
//numberbox.addEventListener("click",function(e){});
addEventHandler(numberbox,"click",function(e){
  if(e.target && e.target.className=="num-element"){
    deleteElement(e.target);
  }
 });
function deleteElement(element){
element.parentNode.removeChild(element);
}

function checkInput(){
  var inputvalue = inputbox.value.trim();
  var pattern = /^[0-9]+$/;
  if(!inputvalue.match(pattern)){
    alert("please input number!");
    return false;
  }
  if(inputvalue<10 || inputvalue>100){
    alert("only between 10-100!");
    return false;
  }
  var divs = numberbox.getElementsByTagName("div");
  if(divs.length>=60){
    alert("cannot more than maxsize(60)!");
    return false;
  }
  return true;
}

function getValue(){
  var inputvalue = inputbox.value.trim();
  return inputvalue;
}
<commit_msg>不会弄定时器动画，设置了断点才能看到过程<commit_after>function addEventHandler(e,event,handler){
  if(e.addEventListener){
    e.addEventListener(event,handler,false);
  }else if(e.attachEvent){
    e.attachEvent("on"+event,handler);
  }else{
    e["on"+event] = handler;
  }
}
var inputbox = document.getElementById("thenumber");
var leftin = document.getElementById("btn-in-left");
var rightin = document.getElementById("btn-in-right");
var leftout = document.getElementById("btn-out-left");
var rightout = document.getElementById("btn-out-right");
var numberbox=document.getElementsByClassName("box-number")[0];
var sortbtn = document.getElementById("btn-bubble-sort");
//addEventHandler(inputbox,"blur",checkInput);
addEventHandler(leftin,"click",leftInQueue);
addEventHandler(rightin,"click",rightInQueue);
addEventHandler(leftout,"click",leftOutQueue);
addEventHandler(rightout,"click",rightOutQueue);
addEventHandler(sortbtn,"click",bubbleSort);

function bubbleSort(){
  var divs = numberbox.getElementsByTagName("div");
  var arr = new Array();
  for(var i=0;i<divs.length;i++){
    var temp = divs[i].innerHTML;
    arr.push(parseInt(temp));
  }
  myBubbleSort(arr);
//  arr.sort();
  console.log(arr.sort());
  /*
  numberbox.innerHTML=arr.map(function(key){
    return "
"+key+"
";
  }).join("");
  */
}

function myBubbleSort(a){
  var timer = null;

//  timer = setInterval("run()",50);
//定时器动画看不了啊啊，只能看到最终结果，设置了断点才能看到一步一步的。。。
  for(var i=0;i<a.length-1;i++){
    for(var j=0;ja[j+1]){
      //  function run(){
        console.log("a: "+a);
        render(a,j);
        var tmp = a[j];
        a[j]=a[j+1];
        a[j+1]=tmp;
        console.log("a: "+a);
        render(a,j);
      // setTimeout(render(a,j),2000);
      //  }
    //    clearInterval(timer);
      }
    }
  }

}

function render(array,a){
  var content="";
  for(var i=0;i<array.length;i++){
    if(i==a || i==a+1){
      content+="
"+array[i]+"
";
    }else{
      content+="
"+array[i]+"
";
    }
  }
  numberbox.innerHTML = content;
}

function leftInQueue(){
  if(checkInput()){
  var num = getValue();
//  console.log("checkInput"+checkInput());
//  if(typeof num!="undefined")
    var div = document.createElement("div");
    var text = document.createTextNode(num);
    div.className="num-element";
    div.style.height=num+"px";
    //div.style.lineHeight=num+"px";
    div.appendChild(text);
    numberbox.insertBefore(div,numberbox.firstChild);
  }
}

function rightInQueue(){
  if(checkInput()){
  var num = getValue();
  var div = document.createElement("div");
  var text = document.createTextNode(num);
  div.className="num-element";
  div.style.height=num+"px";
//  div.style.lineHeight=num+"px";
  div.appendChild(text);
  numberbox.appendChild(div);
  }
}
function leftOutQueue(){
  if(numberbox.hasChildNodes){
  alert("remove "+numberbox.firstChild.innerHTML);
  numberbox.removeChild(numberbox.firstChild);
  }
}
function rightOutQueue(){
  if(numberbox.hasChildNodes){
  alert("remove "+numberbox.lastChild.innerHTML);
  numberbox.removeChild(numberbox.lastChild);
  }
}
//numberbox.addEventListener("click",function(e){});
addEventHandler(numberbox,"click",function(e){
  if(e.target && e.target.className=="num-element"){
    deleteElement(e.target);
  }
 });
function deleteElement(element){
element.parentNode.removeChild(element);
}

function checkInput(){
  var inputvalue = inputbox.value.trim();
  var pattern = /^[0-9]+$/;
  if(!inputvalue.match(pattern)){
    alert("please input number!");
    return false;
  }
  if(inputvalue<10 || inputvalue>100){
    alert("only between 10-100!");
    return false;
  }
  var divs = numberbox.getElementsByTagName("div");
  if(divs.length>=60){
    alert("cannot more than maxsize(60)!");
    return false;
  }
  return true;
}

function getValue(){
  var inputvalue = inputbox.value.trim();
  return inputvalue;
}
<|endoftext|>


<commit_before>/*
 * grunt-appc-js
 * https://github.com/ingo/grunt-appc-js
 *
 * Copyright (c) 2015 Ingo Muschenetz
 * Licensed under the MIT license.
 */

'use strict';

var extendGruntPlugin = require('extend-grunt-plugin');
var packpath = require('packpath');
var path = require('path');
var _ = require('lodash');

module.exports = function (grunt) {

	grunt.registerMultiTask('appcJs', 'Linting and style checks for Appcelerator JavaScript', function () {

		var that = this;
		var source = this.data;
		if (this.data.src) {
			source = this.data.src;
		}

		initializeJscsPlugin();
		initializeJshintPlugin();
		initializeContinuePlugin();
		initializeRetirePlugin();

		grunt.task.run('jshint:src', 'jscs:src', 'continue:on', 'retire', 'continue:off');

		/**
		 * Initializes the jscs plugin
		 *
		 * @return {void}
		 */
		function initializeJscsPlugin() {
			// there is likely a better way to specify the path to the files
			var optionsJscs = {
				src: source,
				options: _.omit(that.options({
					config: 'node_modules/grunt-appc-js/.jscsrc',
					reporter: require('jscs-stylish').path,
				}), 'globals')
			};

			var jscs = require('grunt-jscs/tasks/jscs');
			extendGruntPlugin(grunt, jscs, {
				'jscs.src' : optionsJscs
			});
		}

		/**
		 * Initializes the jshint plugin
		 *
		 * @return {void}
		 */
		function initializeJshintPlugin() {
			var jsHintConfig = {
				browser: true,
				curly: true,
				eqeqeq: true,
				eqnull: true,
				expr: true,
				immed: true,
				indent: 4,
				latedef: false,
				newcap: true,
				noarg: true,
				nonew: true,
				undef: true,
				unused: false,
				trailing: true,
				loopfunc: true,
				proto: true,
				node: true,
				'-W104': true,
				'-W068': true,
				globals: {
					after      : false,
					afterEach  : false,
					before     : false,
					beforeEach : false,
					describe   : false,
					it         : false,
					Titanium   : false,
					Ti         : false
				}
			};

			var optionsJsHint = {
				src: source,
				options: _.omit(_.merge(that.options(),
					{reporter: require('jshint-stylish')},
					jsHintConfig), 'fix')
			};

			var jshint = require('grunt-contrib-jshint/tasks/jshint');
			extendGruntPlugin(grunt, jshint, {
				'jshint.src' : optionsJsHint
			});
		}

		/**
		 * Initializes the retire.js plugin
		 *
		 * The way the retire plugin works is not compatible with extendGruntPlugin
		 * so we simply add the config manually.
		 *
		 * @return {void}
		 */
		function initializeRetirePlugin() {
			var optionsRetire = {
				js: source,
				node: ['.'],
				options: {
					packageOnly: false
				}
			};

			var retire = require('grunt-retire/tasks/retire');
			retire(grunt);
			grunt.config.set('retire', optionsRetire);
		}

		/**
		 * Initializes the continue plugin
		 *
		 * This plugin allows us to temporarily set the --force flag so retire.js
		 * wont't fail our build. Should be removed after a certain transition
		 * period.
		 *
		 * @return {void}
		 */
		function initializeContinuePlugin() {
			var gruntContinue = require('grunt-continue/tasks/continue');
			gruntContinue(grunt);
		}
	});

};
<commit_msg>[RDPP-780] Allow lint only of files<commit_after>/*
 * grunt-appc-js
 * https://github.com/ingo/grunt-appc-js
 *
 * Copyright (c) 2015 Ingo Muschenetz
 * Licensed under the MIT license.
 */

'use strict';

var extendGruntPlugin = require('extend-grunt-plugin');
var packpath = require('packpath');
var path = require('path');
var _ = require('lodash');

module.exports = function (grunt) {

	grunt.registerMultiTask('appcJs', 'Linting and style checks for Appcelerator JavaScript', function (lintOnly) {
		var that = this;
		var source = this.data;
		if (this.data.src) {
			source = this.data.src;
		}

		initializeJscsPlugin();
		initializeJshintPlugin();
		if(lintOnly) {
			grunt.task.run('jshint:src', 'jscs:src');
		} else {
			initializeContinuePlugin();
			initializeRetirePlugin();
			grunt.task.run('jshint:src', 'jscs:src', 'continue:on', 'retire', 'continue:off');

		}

		/**
		 * Initializes the jscs plugin
		 *
		 * @return {void}
		 */
		function initializeJscsPlugin() {
			// there is likely a better way to specify the path to the files
			var optionsJscs = {
				src: source,
				options: _.omit(that.options({
					config: 'node_modules/grunt-appc-js/.jscsrc',
					reporter: require('jscs-stylish').path,
				}), 'globals')
			};

			var jscs = require('grunt-jscs/tasks/jscs');
			extendGruntPlugin(grunt, jscs, {
				'jscs.src' : optionsJscs
			});
		}

		/**
		 * Initializes the jshint plugin
		 *
		 * @return {void}
		 */
		function initializeJshintPlugin() {
			var jsHintConfig = {
				browser: true,
				curly: true,
				eqeqeq: true,
				eqnull: true,
				expr: true,
				immed: true,
				indent: 4,
				latedef: false,
				newcap: true,
				noarg: true,
				nonew: true,
				undef: true,
				unused: false,
				trailing: true,
				loopfunc: true,
				proto: true,
				node: true,
				'-W104': true,
				'-W068': true,
				globals: {
					after      : false,
					afterEach  : false,
					before     : false,
					beforeEach : false,
					describe   : false,
					it         : false,
					Titanium   : false,
					Ti         : false
				}
			};

			var optionsJsHint = {
				src: source,
				options: _.omit(_.merge(that.options(),
					{reporter: require('jshint-stylish')},
					jsHintConfig), 'fix')
			};

			var jshint = require('grunt-contrib-jshint/tasks/jshint');
			extendGruntPlugin(grunt, jshint, {
				'jshint.src' : optionsJsHint
			});
		}

		/**
		 * Initializes the retire.js plugin
		 *
		 * The way the retire plugin works is not compatible with extendGruntPlugin
		 * so we simply add the config manually.
		 *
		 * @return {void}
		 */
		function initializeRetirePlugin() {
			var optionsRetire = {
				js: source,
				node: ['.'],
				options: {
					packageOnly: false
				}
			};

			var retire = require('grunt-retire/tasks/retire');
			retire(grunt);
			grunt.config.set('retire', optionsRetire);
		}

		/**
		 * Initializes the continue plugin
		 *
		 * This plugin allows us to temporarily set the --force flag so retire.js
		 * wont't fail our build. Should be removed after a certain transition
		 * period.
		 *
		 * @return {void}
		 */
		function initializeContinuePlugin() {
			var gruntContinue = require('grunt-continue/tasks/continue');
			gruntContinue(grunt);
		}
	});

};
<|endoftext|>


<commit_before>const months = [
  'Leden',
  'Únor',
  'Březen',
  'Duben',
  'Květen',
  'Červen',
  'Červenec',
  'Srpen',
  'Září',
  'Říjen',
  'Listopad',
  'Prosinec',
];

const months2 = [
  'Ledna',
  'Února',
  'Března',
  'Dubna',
  'Května',
  'Června',
  'Červenece',
  'Srpna',
  'Září',
  'Října',
  'Listopadu',
  'Prosince',
];

export const dateWithDay = date => {
  if (!date) return '';
  const parts = date.split('T')[0].split('-');
  return `${parseInt(parts[2], 10)}. ${months2[parseInt(parts[1], 10)]}, ${parts[0]}`;
};

export const dateJustMonth = date => {
  if (!date) return '';
  const parts = date.split('T')[0].split('-');
  return `${months[parseInt(parts[1], 10)]} ${parts[0]}`;
};
<commit_msg>fix date<commit_after>const months = [
  'Leden',
  'Únor',
  'Březen',
  'Duben',
  'Květen',
  'Červen',
  'Červenec',
  'Srpen',
  'Září',
  'Říjen',
  'Listopad',
  'Prosinec',
];

const months2 = [
  'Ledna',
  'Února',
  'Března',
  'Dubna',
  'Května',
  'Června',
  'Červenece',
  'Srpna',
  'Září',
  'Října',
  'Listopadu',
  'Prosince',
];

export const dateWithDay = date => {
  if (!date) return '';
  const parts = date.split('T')[0].split('-');
  return `${parseInt(parts[2], 10)}. ${months2[parseInt(parts[1], 10) - 1]}, ${parts[0]}`;
};

export const dateJustMonth = date => {
  if (!date) return '';
  const parts = date.split('T')[0].split('-');
  return `${months[parseInt(parts[1], 10) - 1]} ${parts[0]}`;
};
<|endoftext|>


<commit_before>/**
 * Created by Richard Bouška on 16. 9. 2016.
 */

//Category theory for JavaScript programmers #1: contracts

/*
 Popisuje koncept contracu pomocí funkce která kontroluje že se jedná o uvedený datový typ
 v první lekci čistě str contract
 ukazuje proč je kontrak užitečný a že nás chrání před neočekávaných chováním programu
 */

//contract for string
const str = s => {
    if (typeof s !== "string") {
        throw new TypeError(`Expectes string!, got ${typeof s}`);
    }
    return s;
};

//here should come tests

/*
 console.log(str("OK: test string"));
 console.log(str(1));
 */

//not type safe repeat
let repeat;
repeat = (s) => s + s;
//console.log(repeat("joe"));

//I expect 55 but get 10
//console.log(repeat(5));
//I expect 55 but get 10
//console.log(repeat("5"));

repeat = (s) => {
    s = str(s);
    return s + s;
};

//console.log(repeat(5));
//console.log(repeat("5"));
//console.log(repeat("joe"));

//realistic example is for es zIndex from the DOM

//--------------------------------------------------------------------------------------
// Category theory for JavaScript programmers #2: guarded functions and categories

/*
 minule jsme ukázali contract a jak to pomůže zabránit programu aby proběhl ane choval se divně
 jakmile máme kontrakty můžeme psát guarger functions

 2 části: contract + guarded functions tvoří kategorii

 functors: functions that map between categories
 natural transformations: maps betweem functors

 contracts: in our case str
 guarded functions: in our case: repeat
 together they form category (objects & morphisms)

 objects: contracts
 morphisms: guarded functions

 for example repeat is a guardeed function from  string to string
 */

//simplest contract "ANY " - každá funkce je vlastně guarded přinejhorším  contractem ANY

const any = x => x;

// a functor for simplification of creation of basic contracts.
const typeOf = type => {
    type = str(type);
    return p => {
        if (typeof p !== type) {
            throw new TypeError(`Expects ${type}, got ${typeof p}`);
        }
        return p;
    };
};

//now we can create 5 other basic contracts:
const bool = typeOf("boolean");
const obj = typeOf("object");
const num = typeOf("number");
const undef = typeOf("undefined");
const func = typeOf("function");

//here should be tests for the individual contracts
/*
 console.log(num(3)); //it should pass OK
 console.log(num("3")); ////it should fail with TypeError OK
 console.log(func(x => x));//it should pass OK
 console.log(func("x => x"));//it should fail OK
 */

/* this was not part of the lesson - adding for completness*/
const int32 = n => {
    if (n | 0 !== n) {
        throw new TypeError(`Expects int32, got ${typeof n}`);
    }
    return n;
};

// test for contract for int32

//EXAMPLE: we can define inc as a guarded function
const inc = x => {
    x = num(x);
    return num(x + 1);
};
//console.log(inc(3));

//--------------------------------------------------------------------------------------
//Category theory for JavaScript programmers #3: the "array" contract
/*
 for our particular category objects are contracts
 objects: contracts taking a value they test it if they match expectation they throw type error if they dont. They dont need to return exactly the same value but they value must be *strongly* related
 morphisms: guarded functions rhat expects imput that passes a contract and returns a output that passes a contract (například funkce repeat or ins - guarded from num to num i.e. num -> num
 */

/*
 instanceof only checks if Array.prototype is on an object's [[Prototype]] chain. It fails when checking arrays across frames since the Array constructor used for the instance will likely be different to the one used for the test.
 if (Object.prototype.toString.call(obj) == '[object Array]')
 */

const arr = a => {
    if (!Array.isArray(a)) {
        throw new TypeError(`Expects array!, got ${typeof a}`);
    } else return a;
};

/*
 console.log(arr([3])); //it should pass OK
 console.log(arr(3)); //it should fail OK
 console.log(arr([1, 2, 3])); //it should pass OK
 console.log(arr("[1, 2, 3]")); //it should fail OK
 */

//--------------------------------------------------------------------------------------
//Category theory for JavaScript programmers #4: functors
/*
 je fajn že umíme definovat arr ale bylo by leště lepší umět definovat contract který bude typově bezpečný pro typy uvnitř pole
 bude tvořit functor který bude pracovat nad contracty i nad guarded functiuons:
 pokud dostane contract napr int32 tak vrátí kontract pro [int32] a pokud dostane guarded finction lets say str->bool vrátí pole funkcí str->bool souvisí to s map metodou na poili
 */

//functor for array of that works on bots  contracts and guarded functions and púroduces new objects and new morphisms!
const arrOf = c => a => arr(a).map(c);

/*
 console.log (arrOf(num)([1,2,3,"4"])); - should fail OK
 console.log (arrOf(num)([1,2,3,4])); - should pass OK

 */

//--------------------------------------------------------------------------------------
//Category theory for JavaScript programmers #5: the Maybe functor

class Maybe {
    getOrElse(x) {
        return this instanceof Some ? this.x : x;
    }

}
class None extends Maybe {
    toString() {
        return "None";
    }
}
const none = new None();

class Some extends Maybe {
    constructor(x) {
        super();
        this.x = x;
    }
    toString() {
        return `Some(${this.x}) `;
    }
}
const some = x => new Some(x);

const maybe = c => m => {
    if (m instanceof None) return m;
    if (m instanceof Some) return some(c(m.x));
    throw new TypeError(`Expected None or Some(${c}), got ${typeof m}`);
};

console.log("" + maybe(repeat)(none));
console.log(maybe(repeat)(some("joe")).getOrElse("jane"));
console.log(maybe(repeat)(none).getOrElse("jane"));

//----------------------<commit_msg>typo fixes<commit_after>/**
 * Created by Richard Bouška on 16. 9. 2016.
 */

//Category theory for JavaScript programmers #1: contracts

/*
 Popisuje koncept contracu pomocí funkce která kontroluje že se jedná o uvedený datový typ
 v první lekci čistě str contract
 ukazuje proč je kontrak užitečný a že nás chrání před neočekávaných chováním programu
 */

//contract for string
const str = s => {
    if (typeof s !== "string") {
        throw new TypeError(`Expectes string!, got ${typeof s}`);
    }
    return s;
};

//here should come tests

/*
 console.log(str("OK: test string"));
 console.log(str(1));
 */

//not type safe repeat
let repeat;
repeat = (s) => s + s;
//console.log(repeat("joe"));

//I expect 55 but get 10
//console.log(repeat(5));
//I expect 55 but get 10
//console.log(repeat("5"));

repeat = (s) => {
    s = str(s);
    return s + s;
};

//console.log(repeat(5));
//console.log(repeat("5"));
//console.log(repeat("joe"));

//realistic example is for es zIndex from the DOM

//--------------------------------------------------------------------------------------
// Category theory for JavaScript programmers #2: guarded functions and categories

/*
 Minule jsme ukázali contract a jak to pomůže zabránit programu aby proběhl ale choval se divně.

 Jakmile máme kontrakty můžeme psát *guarded functions*

 2 části: contract + guarded functions tvoří kategorii

 functors: functions that map between categories
 natural transformations: maps betweem functors

 contracts: in our case str
 guarded functions: in our case: repeat
 together they form category (objects & morphisms)

 objects: contracts
 morphisms: guarded functions

 for example repeat is a guardeed function from  string to string
 */

//simplest contract "ANY " - každá funkce je vlastně guarded přinejhorším  contractem ANY

const any = x => x;

// a functor for simplification of creation of basic contracts.
const typeOf = type => {
    type = str(type);
    return p => {
        if (typeof p !== type) {
            throw new TypeError(`Expects ${type}, got ${typeof p}`);
        }
        return p;
    };
};

//now we can create 5 other basic contracts:
const bool = typeOf("boolean");
const obj = typeOf("object");
const num = typeOf("number");
const undef = typeOf("undefined");
const func = typeOf("function");

//here should be tests for the individual contracts
/*
 console.log(num(3)); //it should pass OK
 console.log(num("3")); ////it should fail with TypeError OK
 console.log(func(x => x));//it should pass OK
 console.log(func("x => x"));//it should fail OK
 */

/* this was not part of the lesson - adding for completness*/
const int32 = n => {
    if (n | 0 !== n) {
        throw new TypeError(`Expects int32, got ${typeof n}`);
    }
    return n;
};

// test for contract for int32

//EXAMPLE: we can define inc as a guarded function
const inc = x => {
    x = num(x);
    return num(x + 1);
};
//console.log(inc(3));

//--------------------------------------------------------------------------------------
//Category theory for JavaScript programmers #3: the "array" contract
/*
 for our particular category objects are contracts
 objects: contracts taking a value they test it if they match expectation they throw type error if they dont. They dont need to return exactly the same value but they value must be *strongly* related
 morphisms: guarded functions rhat expects imput that passes a contract and returns a output that passes a contract (například funkce repeat or ins - guarded from num to num i.e. num -> num
 */

/*
 instanceof only checks if Array.prototype is on an object's [[Prototype]] chain. It fails when checking arrays across frames since the Array constructor used for the instance will likely be different to the one used for the test.
 if (Object.prototype.toString.call(obj) == '[object Array]')
 */

const arr = a => {
    if (!Array.isArray(a)) {
        throw new TypeError(`Expects array!, got ${typeof a}`);
    } else return a;
};

/*
 console.log(arr([3])); //it should pass OK
 console.log(arr(3)); //it should fail OK
 console.log(arr([1, 2, 3])); //it should pass OK
 console.log(arr("[1, 2, 3]")); //it should fail OK
 */

//--------------------------------------------------------------------------------------
//Category theory for JavaScript programmers #4: functors
/*
 je fajn že umíme definovat arr ale bylo by leště lepší umět definovat contract který bude typově bezpečný pro typy uvnitř pole
 bude tvořit functor který bude pracovat nad contracty i nad guarded functiuons:
 pokud dostane contract napr int32 tak vrátí kontract pro [int32] a pokud dostane guarded finction lets say str->bool vrátí pole funkcí str->bool souvisí to s map metodou na poili
 */

//functor for array of that works on bots  contracts and guarded functions and púroduces new objects and new morphisms!
const arrOf = c => a => arr(a).map(c);

/*
 console.log (arrOf(num)([1,2,3,"4"])); - should fail OK
 console.log (arrOf(num)([1,2,3,4])); - should pass OK

 */

//--------------------------------------------------------------------------------------
//Category theory for JavaScript programmers #5: the Maybe functor

class Maybe {
    getOrElse(x) {
        return this instanceof Some ? this.x : x;
    }

}
class None extends Maybe {
    toString() {
        return "None";
    }
}
const none = new None();

class Some extends Maybe {
    constructor(x) {
        super();
        this.x = x;
    }
    toString() {
        return `Some(${this.x}) `;
    }
}
const some = x => new Some(x);

const maybe = c => m => {
    if (m instanceof None) return m;
    if (m instanceof Some) return some(c(m.x));
    throw new TypeError(`Expected None or Some(${c}), got ${typeof m}`);
};

console.log("" + maybe(repeat)(none));
console.log(maybe(repeat)(some("joe")).getOrElse("jane"));
console.log(maybe(repeat)(none).getOrElse("jane"));

//----------------------<|endoftext|>


<commit_before>// The global object is "self" in Web Workers.
global = (function() { return this; })();

/**
 * Save timer references to avoid Sinon interfering (see GH-237).
 */

var Date = global.Date;
var setTimeout = global.setTimeout;
var setInterval = global.setInterval;
var clearTimeout = global.clearTimeout;
var clearInterval = global.clearInterval;

/**
 * Node shims.
 *
 * These are meant only to allow
 * mocha.js to run untouched, not
 * to allow running node code in
 * the browser.
 */

var process = {};
process.exit = function(status){};
process.stdout = {};

/**
 * Remove uncaughtException listener.
 */

process.removeListener = function(e){
  if ('uncaughtException' == e) {
    global.onerror = function() {};
  }
};

/**
 * Implements uncaughtException listener.
 */

process.on = function(e, fn){
  if ('uncaughtException' == e) {
    global.onerror = function(err, url, line){
      fn(new Error(err + ' (' + url + ':' + line + ')'));
    };
  }
};

/**
 * Expose mocha.
 */

var Mocha = global.Mocha = require('mocha'),
    mocha = global.mocha = new Mocha({ reporter: 'html' });

var immediateQueue = []
  , immediateTimeout;

function timeslice() {
  var immediateStart = new Date().getTime();
  while (immediateQueue.length && (new Date().getTime() - immediateStart) < 100) {
    immediateQueue.shift()();
  }
  if (immediateQueue.length) {
    immediateTimeout = setTimeout(timeslice, 0);
  } else {
    immediateTimeout = null;
  }
}

/**
 * High-performance override of Runner.immediately.
 */

Mocha.Runner.immediately = function(callback) {
  immediateQueue.push(callback);
  if (!immediateTimeout) {
    immediateTimeout = setTimeout(timeslice, 0);
  }
};

/**
 * Override ui to ensure that the ui functions are initialized.
 * Normally this would happen in Mocha.prototype.loadFiles.
 */

mocha.ui = function(ui){
  Mocha.prototype.ui.call(this, ui);
  this.suite.emit('pre-require', global, null, this);
  return this;
};

/**
 * Setup mocha with the given setting options.
 */

mocha.setup = function(opts){
  if ('string' == typeof opts) opts = { ui: opts };
  for (var opt in opts) this[opt](opts[opt]);
  return this;
};

/**
 * Run mocha, returning the Runner.
 */

mocha.run = function(fn){
  var options = mocha.options;
  mocha.globals('location');

  var query = Mocha.utils.parseQuery(global.location.search || '');
  if (query.grep) mocha.grep(query.grep);
  if (query.invert) mocha.invert();

  return Mocha.prototype.run.call(mocha, function(){
    // The DOM Document is not available in Web Workers.
    if (global.document) {
      Mocha.utils.highlightTags('code');
    }
    if (fn) fn();
  });
};
<commit_msg>expose shim process<commit_after>// The global object is "self" in Web Workers.
global = (function() { return this; })();

/**
 * Save timer references to avoid Sinon interfering (see GH-237).
 */

var Date = global.Date;
var setTimeout = global.setTimeout;
var setInterval = global.setInterval;
var clearTimeout = global.clearTimeout;
var clearInterval = global.clearInterval;

/**
 * Node shims.
 *
 * These are meant only to allow
 * mocha.js to run untouched, not
 * to allow running node code in
 * the browser.
 */

var process = {};
process.exit = function(status){};
process.stdout = {};

/**
 * Remove uncaughtException listener.
 */

process.removeListener = function(e){
  if ('uncaughtException' == e) {
    global.onerror = function() {};
  }
};

/**
 * Implements uncaughtException listener.
 */

process.on = function(e, fn){
  if ('uncaughtException' == e) {
    global.onerror = function(err, url, line){
      fn(new Error(err + ' (' + url + ':' + line + ')'));
    };
  }
};

/**
 * Expose mocha.
 */

var Mocha = global.Mocha = require('mocha'),
    mocha = global.mocha = new Mocha({ reporter: 'html' });

var immediateQueue = []
  , immediateTimeout;

function timeslice() {
  var immediateStart = new Date().getTime();
  while (immediateQueue.length && (new Date().getTime() - immediateStart) < 100) {
    immediateQueue.shift()();
  }
  if (immediateQueue.length) {
    immediateTimeout = setTimeout(timeslice, 0);
  } else {
    immediateTimeout = null;
  }
}

/**
 * High-performance override of Runner.immediately.
 */

Mocha.Runner.immediately = function(callback) {
  immediateQueue.push(callback);
  if (!immediateTimeout) {
    immediateTimeout = setTimeout(timeslice, 0);
  }
};

/**
 * Override ui to ensure that the ui functions are initialized.
 * Normally this would happen in Mocha.prototype.loadFiles.
 */

mocha.ui = function(ui){
  Mocha.prototype.ui.call(this, ui);
  this.suite.emit('pre-require', global, null, this);
  return this;
};

/**
 * Setup mocha with the given setting options.
 */

mocha.setup = function(opts){
  if ('string' == typeof opts) opts = { ui: opts };
  for (var opt in opts) this[opt](opts[opt]);
  return this;
};

/**
 * Run mocha, returning the Runner.
 */

mocha.run = function(fn){
  var options = mocha.options;
  mocha.globals('location');

  var query = Mocha.utils.parseQuery(global.location.search || '');
  if (query.grep) mocha.grep(query.grep);
  if (query.invert) mocha.invert();

  return Mocha.prototype.run.call(mocha, function(){
    // The DOM Document is not available in Web Workers.
    if (global.document) {
      Mocha.utils.highlightTags('code');
    }
    if (fn) fn();
  });
};

/**
 * Expose the process shim.
 */

Mocha.process = process;
<|endoftext|>