From 47557edee1d245ad60b9f15889018a8f2cac3afd Mon Sep 17 00:00:00 2001 From: Boris Yankov Date: Wed, 16 Jan 2013 15:49:36 +0200 Subject: [PATCH] Add KoLite definitions and tests --- README.md | 1 + kolite/kolite-1.1.d.ts | 77 ++++++++++++++++ kolite/kolite-tests.ts | 197 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 275 insertions(+) create mode 100644 kolite/kolite-1.1.d.ts create mode 100644 kolite/kolite-tests.ts diff --git a/README.md b/README.md index 8e17ccba8..eb66412c1 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ Complete * [Knockout.js](http://knockoutjs.com/) (by [Boris Yankov](https://github.com/borisyankov)) * [Knockout.Mapping](https://github.com/SteveSanderson/knockout.mapping) (by [Boris Yankov](https://github.com/borisyankov)) * [Knockout.Validation](https://github.com/ericmbarnard/Knockout-Validation) (by [Dan Ludwig](https://github.com/danludwig)) +* [KoLite](https://github.com/CodeSeven/kolite) (by [Boris Yankov](https://github.com/borisyankov)) * [linq.js](http://linqjs.codeplex.com/) (by [Marcin Najder](https://github.com/marcinnajder)) * [Modernizr](http://modernizr.com/) (by [Boris Yankov](https://github.com/borisyankov)) * [Moment.js](https://github.com/timrwood/moment) (by [Michael Lakerveld](https://github.com/Lakerfield)) diff --git a/kolite/kolite-1.1.d.ts b/kolite/kolite-1.1.d.ts new file mode 100644 index 000000000..c879b7871 --- /dev/null +++ b/kolite/kolite-1.1.d.ts @@ -0,0 +1,77 @@ +// Type definitions for KoLite 1.1 +// Project: https://github.com/CodeSeven/kolite +// Definitions by: Boris Yankov +// Definitions https://github.com/borisyankov/DefinitelyTyped + + +/// +/// + + +// Activity ///////////////////////////////////////////// + +interface KoLiteActivityOptions { + color?: any; + segments?: number; + space?: number; + length?: number; + width?: number; + speed?: number; + align?: string; + valign?: string; + padding?: number; +} + +interface KoLiteActivity { + (options: KoLiteActivityOptions): JQuery; + defaults: KoLiteActivityOptions; + getOpacity(options: { steps?: number; segments?: number; opacity?: number; }, i: number): number; +} + +interface KnockoutBindingHandlers { + activity: KnockoutBindingHandler; +} + +interface JQuery { + activity: KoLiteActivity; + activityEx(isLoading: bool): JQuery; +} + + +// DirtyFlag ///////////////////////////////////////////// + +interface DirtyFlag { + isDirty: KnockoutComputed; + new (objectToTrack: any, isInitiallyDirty?: bool, hashFunction?: () => any); + reset(): void; +} + +interface KnockoutStatic { + DirtyFlag: DirtyFlag; +} + + +// Command ///////////////////////////////////////////// + +interface KoliteCommand { + canExecute: KnockoutComputed; + execute(...args: any[]): any; +} + +interface KoLiteCommandOptions { + execute?: any; + canExecute?: (isExecuting: bool) => any; +} + +interface KnockoutStatic { + command(options: KoLiteCommandOptions): KoliteCommand; + asyncCommand(optons: KoLiteCommandOptions): KoliteCommand; +} + +interface KnockoutUtils { + wrapAccessor(accessor): Function; +} + +interface KnockoutBindingHandlers { + command: KnockoutBindingHandler; +} \ No newline at end of file diff --git a/kolite/kolite-tests.ts b/kolite/kolite-tests.ts new file mode 100644 index 000000000..4e1418211 --- /dev/null +++ b/kolite/kolite-tests.ts @@ -0,0 +1,197 @@ +/// +/// +/// + +function test_asyncCommand() { + var saveCmd = ko.asyncCommand({ + execute: function (complete) { + $.when().always(complete); + }, + canExecute: function (isExecuting) { + return !isExecuting; + } + }); + this.saveCommand = ko.asyncCommand({ + execute: function (callback) { + $.ajax({ + complete: callback, + data: { name: this.name() }, + type: 'POST', + url: '/save/', + + success: function (result) { + alert('Name saved:' + result) + } + }) + }, + canExecute: function (isExecuting) { + return !isExecuting && this.name() + } + }); +} + +function test_dirtyFlag() { + var viewModel; + viewModel.dirtyFlag = new ko.DirtyFlag(viewModel.model); + viewModel.dirtyFlag().isDirty(); + viewModel.dirtyFlag().reset(); + + var self; + this.dirtyFlag = new ko.DirtyFlag( + self.firstName, + self.lastName); + var isDirty = ko.computed(function () { + }); + + var Person = function () { + var self = this; + + self.id = ko.observable(); + self.firstName = ko.observable().extend({ required: true }); + self.lastName = ko.observable().extend({ required: true }); + self.dirtyFlag = new ko.DirtyFlag([self.firstName, self.lastName]); + + return self; + }; +} + +function test_full() { + (function (ko) { + ko.command = function (options) { + var + self = ko.observable(), + canExecuteDelegate = options.canExecute, + executeDelegate = options.execute; + self.canExecute = ko.computed(function () { + return canExecuteDelegate ? canExecuteDelegate() : true; + }); + self.execute = function (arg1, arg2) { + if (!self.canExecute()) return; + executeDelegate.apply(this, [arg1, arg2]); + }; + return self; + }; + + ko.asyncCommand = function (options) { + var + self = ko.observable(), + canExecuteDelegate = options.canExecute, + executeDelegate = options.execute, + completeCallback = function () { + self.isExecuting(false); + }; + self.isExecuting = ko.observable(); + self.canExecute = ko.computed(function () { + return canExecuteDelegate ? canExecuteDelegate(self.isExecuting()) : !self.isExecuting(); + }); + self.execute = function (arg1, arg2) { + if (!self.canExecute()) return; + var args = []; + if (executeDelegate.length >= 2) { + args.push(arg1); + } + if (executeDelegate.length >= 3) { + args.push(arg2); + } + args.push(completeCallback); + self.isExecuting(true); + executeDelegate.apply(this, args); + }; + return self; + }; + })(ko); + (function (ko) { + ko.utils.wrapAccessor = function (accessor) { + return function () { + return accessor; + }; + }; + ko.bindingHandlers.command = { + init: function (element, valueAccessor, allBindingsAccessor, viewModel) { + var + value = valueAccessor(), + commands = value.execute ? { click: value } : value, + isBindingHandler = function (handler) { + return ko.bindingHandlers[handler] !== undefined; + }, + initBindingHandlers = function () { + for (var command in commands) { + if (!isBindingHandler(command)) { + continue; + }; + ko.bindingHandlers[command].init( + element, + ko.utils.wrapAccessor(commands[command].execute), + allBindingsAccessor, + viewModel + ); + } + }, + initEventHandlers = function () { + var events = {}; + for (var command in commands) { + if (!isBindingHandler(command)) { + events[command] = commands[command].execute; + } + } + ko.bindingHandlers.event.init( + element, + ko.utils.wrapAccessor(events), + allBindingsAccessor, + viewModel); + }; + initBindingHandlers(); + initEventHandlers(); + }, + update: function (element, valueAccessor, allBindingsAccessor, viewModel) { + var commands = valueAccessor(); + var canExecute = commands.canExecute; + if (!canExecute) { + for (var command in commands) { + if (commands[command].canExecute) { + canExecute = commands[command].canExecute; + break; + } + } + } + if (!canExecute) { + return; + } + ko.bindingHandlers.enable.update(element, canExecute, allBindingsAccessor, viewModel); + } + }; + })(ko); + + var my: any = {}; + my.TwitterService = function () { + var me = this, + twitterUrl = 'https://api.twitter.com/1/statuses/user_timeline/{name}.json?callback=?&count={count}' + me.getTweets = function (options) { + } + } + my.TweetsViewModel = function () { + var me = this, + service = new my.TwitterService() + me.name = ko.observable('hfjallemark'); + me.tweets = ko.observableArray(); + me.showKeyCodeCommand = ko.command({ + execute: function (data, e) { + } + }); + me.loadTweetsCommand = ko.asyncCommand({ + execute: function (complete) { + service.getTweets({ + always: complete, + count: 15, + name: me.name(), + done: function (result) { + me.tweets(result); + }, + fail: function (options, status) { + } + }) + } + }) + } + ko.applyBindings(new my.TweetsViewModel()); +} \ No newline at end of file