From 3b653e414c33b0fef1d7ccf6605b57353d5db564 Mon Sep 17 00:00:00 2001 From: Boris Yankov Date: Mon, 29 Oct 2012 12:49:49 +0200 Subject: [PATCH] Initial Sammy.js definitions and tests --- Definitions/sammyjs-0.7.d.ts | 228 ++++++++++++++++ README.md | 5 +- Tests/sammyjs-tests.ts | 500 +++++++++++++++++++++++++++++++++++ 3 files changed, 732 insertions(+), 1 deletion(-) create mode 100644 Definitions/sammyjs-0.7.d.ts create mode 100644 Tests/sammyjs-tests.ts diff --git a/Definitions/sammyjs-0.7.d.ts b/Definitions/sammyjs-0.7.d.ts new file mode 100644 index 000000000..b26d23ca2 --- /dev/null +++ b/Definitions/sammyjs-0.7.d.ts @@ -0,0 +1,228 @@ +// Type definitions for Sammy.js +// Project: http://sammyjs.org/ +// Definitions: https://github.com/borisyankov/DefinitelyTyped + + +/// + +interface Sammy { + (): Application; + (selector: string): Application; + (handler: Function): Application; + (selector: string, handler: Function): Application; + + Cache(app, options); + DataCacheProxy(initial, $element); + DataLocationProxy(app, data_name, href_attribute); + DefaultLocationProxy(app, run_interval_every); + EJS(app, method_alias); + + Exceptional(app, errorReporter); + Flash(app); + Form(app); // formFor ( name, object, content_callback ) + + Haml(app, method_alias); + Handlebars(app, method_alias); + Hogan(app, method_alias); + Hoptoad(app, errorReporter); + JSON(app); + Meld(app, method_alias); + MemoryCacheProxy(initial); + Mustache(app, method_alias); + NestedParams(app); + OAuth2(app); + PathLocationProxy(app); + Pure(app, method_alias); + PushLocationProxy(app); + Session(app, options); + Storage(app); + + Title(); + Tmpl(app, method_alias); + addLogger(logger); + log(); + + Object: Object; +} + +interface Object { + + constructor (obj: any); + + escapeHTML(s: string): string; + h(s: string): string; + + has(key: string): bool; + join(...args: any[]): string; + keys(attributes_only?: bool): string[]; + log(...args: any[]): void; + toHTML(): string; + toHash(): any; + toString(include_functions?: bool): string; +} + +interface Application extends Object { + + ROUTE_VERBS: string[]; + APP_EVENTS: string[]; + + (appFn: Function); + + $element(selector: string): JQuery; + after: (callback: Function): Application; + any(verb: string, path: string, callback: Function): void; + route(verb: string, path: string, callback: Function): void; + around(callback); + before(options: any, callback: Function): Application; + bind(name: string, data: any, callback: Function): Application; + bindToAllEvents(callback); + clearTemplateCache(); + contextMatchesOptions(context, match_options, positive); + del(path: string, callback: Function): Application; + del(path: RegExp, callback: Function): Application; + destroy(); + error(message, original_error); + eventNamespace(): string; + get(path: string, callback: Function): Application; + get(path: RegExp, callback: Function): Application; + getLocation(): string; + helper(name, method); + helpers(extensions); + isRunning(); + log(...params: any[]): void; + lookupRoute(verb, path); + mapRoutes(route_array: any[]): Application; + notFound(verb, path); + post(path: string, callback: Function): Application; + post(path: RegExp, callback: Function): Application; + put(path: string, callback: Function): Application; + put(path: RegExp, callback: Function): Application; + refresh(): Application; + routablePath(path); + route(verb: string, path: string, callback: Function): Application; + route(verb: string, path: RegExp, callback: Function): Application; + run(start_url); + runRoute(verb, path, params, target); + setLocation(new_location: string): string; + setLocationProxy(new_proxy: DataLocationProxy): void; + swap(content, callback); + templateCache(key, value); + toString(): string; + trigger(name: string, data: any): Application; + unload(); + use(...params: any[]): void; +} + +interface DataLocationProxy { + (app, run_interval_every): DataLocationProxy; + fullPath(location_obj): string; + bind(): void; + unbind(): void; + setLocation(new_location: string): string; + _startPolling(every: number): void; +} + +interface EventContext { + constructor (app, verb, path, params, target); + $element(); + engineFor(engine); + eventNamespace(); + interpolate(content, data, engine, partials); + json(string); + load(location, options, callback); + loadPartials(partials); + notFound(); + partial(location, data, callback, partials); + redirect(); + render(location, data, callback, partials); + renderEach(location, name, data, callback); + send(); + swap(contents, callback); + toString(); + trigger(name, data); +} + +interface FormBuilder { + constructor (name, object); + checkbox(keypath, value, attributes); + close(); + hidden(keypath, attributes); + label(keypath, content, attributes); + open(attributes); + password(keypath, attributes); + radio(keypath, value, attributes); + select(keypath, options, attributes); + submit(attributes); + text(keypath, attributes); + textarea(keypath, attributes); +} + +interface GoogleAnalytics { + constructor (app, tracker); + noTrack(); + track(path); +} + +interface RenderContext { + constructor (event_context); + appendTo(selector); + collect(array, callback, now); + interpolate(data, engine, retain); + load(location, options, callback); + loadPartials(partials); + next(content); + partial(location, data, callback, partials); + prependTo(selector); + render(location, data, callback, partials); + renderEach(location, name, data, callback); + replace(selector); + send(); + swap(callback); + then(callback); + trigger(name, data); + wait(); +} + + +interface StoreOptions { + name?: string; + element?: string; + type?: string; + memory?: any; + data?: any; + cookie?: any; + local?: any; + session?: any; +} + +interface Store { + constructor (options); + + clear(key); + clearAll(); + each(callback); + exists(key); + fetch(key, callback); + filter(callback); + first(callback); + get(key); + isAvailable(); + keys(); + load(key, path, callback); + set(key, value); + + Cookie(name, element, options); + Data(name, element); + LocalStorage(name, element); + Memory(name, element); + SessionStorage(name, element); + isAvailable(type); + Template(app, method_alias); +} + + +interface JQueryStatic { + sammy: Sammy; +} + +declare var Sammy: Sammy; \ No newline at end of file diff --git a/README.md b/README.md index a92d08c42..4f68d27a2 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ Complete * [node_redis](https://github.com/mranney/node_redis) * [QUnit](http://qunitjs.com/) (by [Diullei Gomes](https://github.com/Diullei)) * [Raphael](http://raphaeljs.com/) (by [CheCoxshall](https://github.com/CheCoxshall)) +* [Sammy.js](http://sammyjs.org/) * [Spin](http://fgnass.github.com/spin.js/) * [Underscore.js](http://underscorejs.org/) @@ -47,4 +48,6 @@ Next * Meteor * PhoneGap * Isotope -* Zepto \ No newline at end of file +* Zepto +* Socket.IO +* MongoDB \ No newline at end of file diff --git a/Tests/sammyjs-tests.ts b/Tests/sammyjs-tests.ts new file mode 100644 index 000000000..fa0fa3a67 --- /dev/null +++ b/Tests/sammyjs-tests.ts @@ -0,0 +1,500 @@ +/// + +var _this: RenderContext; + +function test_general() { + var app = Sammy('#main', function () { + var _this: Application; + _this.use('Mustache'); + _this.get('#/', function () { + _this.load('posts.json') + .renderEach('post.mustache') + .swap(); + }); + }); + + app.run('#/'); + + _this.get('#/', function(context) { + _this.load('data/items.json') + .then(function(items) { + $.each(items, function(i, item) { + context.log(item.title, '-', item.artist); + }); + }); + }); +} + +function test_app() { + var s = new Sammy.Object({ first_name: 'Sammy', last_name: 'Davis Jr.' }); + s.toHTML(); + + var app = $.sammy(function () { + var current_user = false; + function checkLoggedIn(callback) { + if (!current_user) { + $.getJSON('/session', function (json) { + if (json.login) { + current_user = json; + callback(); + } else { + current_user = false; + _this.redirect('#/login'); + } + }); + } else { + callback(); + } + }; + _this.around(checkLoggedIn); + }); + + var app = $.sammy(function () { + _this.before('#/route', function () { }); + _this.before({ except: { path: '#/route' } }, function () { + _this.log('not before #/route'); + }); + _this.get('#/', function () { }); + _this.get('#/route', function () { }); + }); + + var app = $.sammy(), + context = { verb: 'get', path: '#/mypath' }; + + app.contextMatchesOptions(context, '#/mypath'); + app.contextMatchesOptions(context, '#/otherpath'); + app.contextMatchesOptions(context, { only: { path: '#/mypath' } }); + app.contextMatchesOptions(context, { only: { path: '#/otherpath' } }); + app.contextMatchesOptions(context, /path/); + app.contextMatchesOptions(context, /^path/); + app.contextMatchesOptions(context, { only: { verb: 'get' } }); + app.contextMatchesOptions(context, { only: { verb: 'post' } }); + app.contextMatchesOptions(context, { except: { verb: 'post' } }); + app.contextMatchesOptions(context, { except: { verb: 'get' } }); + app.contextMatchesOptions(context, { except: { path: '#/otherpath' } }); + app.contextMatchesOptions(context, { except: { path: '#/mypath' } }); + app.contextMatchesOptions(context, { path: ['#/mypath', '#/otherpath'] }); + app.contextMatchesOptions(context, { path: ['#/otherpath', '#/thirdpath'] }); + app.contextMatchesOptions(context, { only: { path: ['#/mypath', '#/otherpath'] } }); + app.contextMatchesOptions(context, { only: { path: ['#/otherpath', '#/thirdpath'] } }); + app.contextMatchesOptions(context, { except: { path: ['#/mypath', '#/otherpath'] } }); + app.contextMatchesOptions(context, { except: { path: ['#/otherpath', '#/thirdpath'] } }); + + var app = $.sammy(function (app) { + $.each([1, 2, 3], function (i, num) { + app.helper('helper' + num, function () { + _this.log("I'm helper number " + num); + }); + }); + _this.get('#/', function () { + _this.helper2(); + }); + }); + + var app = $.sammy(function () { + helpers({ + upcase: function (text) { + return text.toString().toUpperCase(); + } + }); + get('#/', function () { + with (_this) { + $('#main').html(upcase($('#main').text()); + } + }); + }); + + var app = $.sammy(function () { + _this.mapRoutes([ + ['get', '#/', function () { _this.log('index'); }], + ['post', '#/create', 'addUser'], + [/dowhatever/, function () { _this.log(_this.verb, _this.path) }]; + ]); + }); + + var app = $.sammy(function () { }); + $(function () + app.run(); + }); + + var app = $.sammy(function () { + _this.setLocationProxy(new Sammy.DataLocationProxy(_this)); + }); + + var app = $.sammy(function () { + _this.swap = function (content, callback) { + var context = _this; + context.$element().fadeOut('slow', function () { + context.$element().html(content); + context.$element().fadeIn('slow', function () { + if (callback) { + callback.apply(); + } + }); + }); + }; + }); + + var MyPlugin = function (app, prepend) { + _this.helpers({ + myhelper: function (text) { + alert(prepend + " " + text); + } + }); + }; + var app = $.sammy(function () { + _this.use(MyPlugin, '_this is my plugin'); + _this.get('#/', function () { + _this.myhelper('and dont you forget it!'); + }); + }); + + $.sammy(function () { + _this.use('Mustache'); + _this.use('Storage'); + }); +} + +function test_misc() { + var app = $.sammy(function () { + _this.setLocationProxy(new Sammy.DataLocationProxy(_this, 'location', 'rel')); + _this.get('about', function () { + _this.partial('about.html'); + }); + }); + + $.sammy(function () { + _this.get('#/:name', function () { + if (_this.params['name'] == 'sammy') { + _this.partial('name.html.erb', { name: 'Sammy' }); + } else { + _this.redirect('#/somewhere-else') + } + }); + }); + + redirect('#/other/route'); + redirect('#', 'other', 'route'); + render('mytemplate.mustache', { name: 'quirkey' }) + .appendTo('ul'); + renderEach('mytemplate.mustache', [{ name: 'quirkey' }, { name: 'endor' }]); + + var item = { + name: 'My Item', + price: '$25.50', + meta: { + id: '123' + } + }; + var form = new Sammy.FormBuilder('item', item); + form.text('name'); + + var options = [ + ['Small', 's'], + ['Medium', 'm'], + ['Large', 'l'] + ]; + form.select('size', options); + + $.sammy(function () { + _this.use('GoogleAnalytics') + _this.get('#/dont/track/me', function () { + _this.noTrack(); + }); + }); + + var app = $.sammy(function () { + _this.use(Sammy.Haml); + _this.get('#/hello/:name', function () { + _this.title = 'Hello!' + _this.name = _this.params.name; + _this.partial('mytemplate.haml'); + }); + }); + app.run() + + var app = $.sammy(function () { + _this.use('Handlebars', 'hb'); + _this.get('#/hello/:name', function () { + _this.title = 'Hello!' + _this.name = _this.params.name; + _this.partial('mytemplate.hb'); + }); + }); + + var app = $.sammy(function () { + _this.use('Handlebars', 'hb'); + _this.get('#/hello/:name/to/:friend', function (context) { + _this.load('mypartial.hb') + .then(function (partial) { + context.partials = { hello_friend: partial }; + context.name = context.params.name; + context.friend = context.params.friend; + context.partial('mytemplate.hb'); + }); + }); + }); + + var app = $.sammy(function () { + _this.use('Hogan', 'hg'); + _this.get('#/hello/:name', function () { + _this.title = 'Hello!' + _this.name = _this.params.name; + _this.partial('mytemplate.hg'); + }); + }); + + var app = $.sammy(function () { + _this.use('Hogan', 'hg'); + _this.get('#/hello/:name/to/:friend', function (context) { + _this.load('mypartial.hg') + .then(function (partial) { + context.partials = { hello_friend: partial }; + context.name = context.params.name; + context.friend = context.params.friend; + context.partial('mytemplate.hg'); + }); + }); + }); + + var app = $.sammy(function () { + _this.use(Sammy.JSON); + _this.get('#/', function () { + _this.json({ user_id: 123 }); + _this.json("{\"user_id\":\"123\"}"); + _this.json("{\"user_id\":\"123\"}").user_id; + }); + }) + + var app = $.sammy(function () { + _this.use('Mustache', 'ms'); + _this.get('#/hello/:name', function () { + _this.title = 'Hello!' + _this.name = _this.params.name; + _this.partial('mytemplate.ms'); + }); + }); + + var app = $.sammy(function () { + _this.use('Mustache', 'ms'); + _this.get('#/hello/:name/to/:friend', function (context) { + _this.load('mypartial.ms') + .then(function (partial) { + context.partials = { hello_friend: partial }; + context.name = context.params.name; + context.friend = context.params.friend; + context.partial('mytemplate.ms'); + }); + }); + }); + + var app = $.sammy(function (app) { + _this.use(Sammy.NestedParams); + _this.post('#/parse_me', function (context) { + $.log(_this.params); + }); + }); + + _this.use('Storage'); + _this.use('OAuth2'); + _this.oauthorize = "/oauth/authorize"; + _this.requireOAuth(); + _this.requireOAuth("/private"); + _this.before(function (context) { return context.requireOAuth(); }) + _this.get("/private", function (context) { + _this.requireOAuth(function () { }); + }); + _this.bind("oauth.connected", function () { $("#signin").hide() }); + _this.bind("oauth.disconnected", function () { $("#signin").show() }); + _this.bind("oauth.denied", function (evt, error) { + _this.partial("admin/views/no_access.tmpl", { error: error.message }); + }); + _this.get("#/signout", function (context) { + context.loseAccessToken(); + context.redirect("#/"); + }); + + _this.get('#/', function () { + _this.render('mytemplate.template', { name: 'test' }); + }); + + _this.send($.getJSON, '/app.json') + .then(function (json) { + $('#message').text(json['message']); + } + ); + + _this.get('#/', function () { + _this.load('myfile.txt') + .then(function (content) { + $('#main').html(content); + }); + }); + + _this.get('#/', function () { + _this.load('mytext.json') + .then(function (content) { + var context = _this, + data = JSON.parse(content); + context.wait(); + $.post(data.url, {}, function (response) { + context.next(JSON.parse(response)); + }); + }) + .then(function (data) { + $('#message').text(data.status); + }); + }); + + var store = new Sammy.Store({ name: 'mystore', element: '#element', type: 'local' }); + store.set('foo', 'bar'); + store.get('foo'); + store.set('json', { obj: '_this is an obj' }); + store.get('json'); + store.keys(); + store.clear('foo'); + store.keys(); + store.clearAll(); + store.keys(); + + store.each(function (key, value) { + Sammy.log('key', key, 'value', value); + }); + var store = new Sammy.Store; + store.exists('foo'); + store.fetch('foo', function () { + return 'bar!'; + }); + store.get('foo'); + store.fetch('foo', function () { + return 'baz!'; + }); + + var store = new Sammy.Store; + store.set('one', 'two'); + store.set('two', 'three'); + store.set('1', 'two'); + var returned = store.filter(function (key, value) { + return value === 'two'; + }); + + var store = new Sammy.Store; + store.load('mytemplate', '/mytemplate.tpl', function () { + s.get('mytemplate') + }); + + var store = new Sammy.Store({ name: 'kvo' }); + $('body').bind('set-kvo-foo', function (e, data) { + Sammy.log(data.key + ' changed to ' + data.value); + }); + store.set('foo', 'bar'); + + $.sammy(function () { + _this.use('Template'); + _this.get('#/', function () { + _this.user = { name: 'Aaron Quint' }; + _this.partial('user.template'); + }) + }); + + _this.use(Sammy.Template, 'tpl'); + _this.get('#/', function () { + _this.partial('myfile.tpl'); + }); + _this.get('#/', function () { + _this.template('myform.tpl', { form: "
" }, { escape_html: false }); + }); +} + +function test_routes() { + route('get', '#/', function () { + }); + put('#/post/form', function () { + return false; + }); + get('/test/123', function () { + }); + + get('#/by_name/:name', function () { + alert(_this.params['name']); + }); + get(/\#\/by_name\/(.*)/, function () { + alert(_this.params['splat']); + }); + get('#/by_name/:name', function () { + _this.redirect('#', _this.params['name']); + }); + + get('#/by_name/:name', function (context) { + context.redirect('#', _this.params['name']); + }); +} + +function test_events() { + bind('db-loaded', function (e, data) { + _this.redirect('#/'); + }); + + var app = $.sammy(function () { + bind('test', function () { + _this.trigger('other-event'); + }); + }); + app.trigger('other-event'); + + var app = $.sammy(function () { + bind('test', function (e, data) { + alert(data['my_data']); + }); + get('#/', function () { + _this.trigger('test', { my_data: 'EVENTED!' }); + }); + }); +} + +function test_plugins() { + var MyPlugin = function (app) { + _this.helpers({ + alert: function (message) { + _this.log("ALERT! " + message); + } + }); + }; + var app = $.sammy(function () { + _this.use(MyPlugin); + _this.get('#/', function () { + _this.alert("I'm home"); + }); + }); + var MyAdvancedPlugin = function (app, prefix, suffix) { + _this.helpers({ + alert: function (message) { + _this.log(prefix, message, suffix); + } + }); + }; + + var app = $.sammy(function () { + _this.use(MyAdvancedPlugin, 'BEFORE!', 'AFTER!'); + _this.get('#/', function () { + _this.alert("I'm home"); + }); + }); + + var dbLoadAndDisplay = function (app) { + _this.get('#/', function () { + _this.record = _this.app.db[_this.app.element_selector]; + _this.app.swap(_this.record.toHTML()); + }); + _this.bind('run', function () { + }); + }; + + var app1 = Sammy('#div_1', function () { + _this.use(dbLoadAndDisplay); + }); + + var app2 = Sammy('#div_2', function () { + _this.use(dbLoadAndDisplay); + }); +} \ No newline at end of file