Initial check-in.

This commit is contained in:
Ken Elf Mathieu Sternberg 2012-08-09 14:57:23 -07:00
commit 05dfa1def0
18 changed files with 11963 additions and 0 deletions

16
.gitignore vendored Normal file
View File

@ -0,0 +1,16 @@
*.pyc
*.pyo
*#
.#*
.DS_Store
*~
npm-debug.log
node_modules/*
app/*
dist/*
dist-compiled/*
app/*
src/*.html
src/*.js
src/*.css
tmp/

View File

@ -0,0 +1,28 @@
{
"name": "couchexperiment",
"title": "CouchExperiment",
"description": "Grunt.JS exploration working with CouchDB.",
"version": "0.1.0",
"homepage": "http://elfsternberg.com",
"author": {
"name": "Elf M. Sternberg",
"email": "elf.sternberg@gmail.com"
},
"repository": {
"type": "svn",
"url": ""
},
"bugs": {
"url": ""
},
"licenses": [
{
"url": "file://./LICENSE",
"type": "All Rights Reserved"
}
],
"dependencies": {
"jquery": ">= 1.6"
},
"keywords": []
}

22
LICENSE-MIT Normal file
View File

@ -0,0 +1,22 @@
Copyright (c) 2012 Ken Elf Mathieu Sternberg
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

81
README.md Normal file
View File

@ -0,0 +1,81 @@
# CouchApp/RequireJS One Page Application Demo
This basically scratches a major itch I've had for a while: is it
possible to automate the integration of
(1) CouchDB one-page apps with
(2) javascript one-page applications optimized with RequireJS?
The answer is this project.
## Getting Started
You will need: Node.js and the Ruby version of Haml. You might need
the global version of require.js (r.js) installed; I do, so I haven't
tested without it.
This project is written in Coffeescript and HAML, and uses Grunt as
its build tool. You should have a copy of CouchDB running in
"AdminParty mode."
As with all NPM-based projects, you should run:
$ npm install
to get started. A pair of convenience scripts are located in the
'bin/' directory. From the root of the application, when in Bash or a
related shell, run:
$ source bin/activate
This will put all of the executables installed in
"./node_modules/.bin" into your path, making them available to you
(and grunt). Now create a new database:
$ curl -X PUT http://localhost:5984/demo-couchapp
Now run the build and install:
$ gruntc
And now it should be possible to browse to
http://localhost:5984/demo-couchapp/_design/app/index.html
... and see "Yes, it worked!" in blue.
If it did not work, the page will say "Did it work?"
## Documentation
There are a number of valuable little snippets of code in here.
First, there are a slew of useful, tiny Grunt.JS tools: HAMLtoHTML,
InstallCouchApp, and just plain "copy". These all demonstrate how to
create small GruntJS recipes and are fairly clear.
Secondly, the "requirejs" GruntJS configuration shows how to force the
optimizer to include require() as part of the final product. This is
critical to ensuring that it's available to the final, compiled app.
And finally, as a framework for developing fast, efficient CouchApps
in Coffeescript, this is pretty invaluable stuff. After I work in my
HAMLtoJS features (no, really, you'll see! I'll show you, I'll show
you all! Muahahahahah!) and a consistent working op for recess, this
will be the framework many of my tools will be in, going into the
future.
## Contributing
In lieu of a formal styleguide, take care to maintain the existing
coding style. Add unit tests for any new or changed
functionality. Lint and test your code using
[grunt](https://github.com/cowboy/grunt).
## License
Copyright (c) 2012 Ken Elf Mathieu Sternberg
Licensed under the MIT license.
The libraries packaged with this demostration are copyright their
respective owners.

8
bin/activate Normal file
View File

@ -0,0 +1,8 @@
#!/bin/bash
# /bin comes before /node_modules/.bin because sometimes I want to
# override the behaviors provided.
PROJECT_ROOT=`pwd`
PATH="$PROJECT_ROOT/bin:$PROJECT_ROOT/node_modules/.bin:$PATH"
export PATH

3
bin/gruntc Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
grunt gruntjs
grunt $*

192
grunt.coffee Normal file
View File

@ -0,0 +1,192 @@
path = require "path"
async = require "async"
fs = require "fs"
coffee = require 'coffee-script'
module.exports = (grunt) ->
grunt.loadNpmTasks "grunt-coffee"
grunt.loadNpmTasks "grunt-requirejs"
grunt.initConfig
pkg: "<json:CouchappRequirejsOnepage.json>"
meta:
banner: "/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - " + "<%= grunt.template.today(\"yyyy-mm-dd\") %>\n" + "<%= pkg.homepage ? \"* \" + pkg.homepage + \"\n\" : \"\" %>" + "* Copyright (c) <%= grunt.template.today(\"yyyy\") %> <%= pkg.author.name %>;" + " Licensed <%= _.pluck(pkg.licenses, \"type\").join(\", \") %> */"
concat:
dist:
src: [ "<banner:meta.banner>", "<file_strip_banner:src/<%= pkg.name %>.js>" ]
dest: "dist/<%= pkg.name %>.js"
min:
dist:
src: [ "<banner:meta.banner>", "<config:concat.dist.dest>" ]
dest: "dist/<%= pkg.name %>.min.js"
qunit:
files: [ "test/**/*.html" ]
lint:
files: [ "grunt.js", "src/**/*.js", "test/**/*.js" ]
watch:
files: "<config:lint.files>"
tasks: "lint qunit"
jshint:
options:
curly: true
eqeqeq: true
immed: true
latedef: true
newcap: true
noarg: true
sub: true
undef: true
boss: true
eqnull: true
browser: true
globals:
jQuery: true
# ___ ___ _ __ __
# / _ \ _ _ _ _ / __| |_ _ _ / _|/ _|
# | (_) | || | '_| \__ \ _| || | _| _|
# \___/ \_,_|_| |___/\__|\_,_|_| |_|
#
haml:
dev:
src: ['src/index.haml']
dest: 'app/attachments/'
coffee:
app:
src: ['src/app.coffee']
dest: 'app/'
client:
src: ['src/client.coffee', 'src/library.coffee']
dest: 'dist/'
requirejs:
dir: 'dist-compiled'
appDir: 'dist'
baseUrl: '.'
paths:
'jquery': '../libs/jquery/jquery'
deps: ['../libs/require/require']
modules: [
{
name: "client"
}
]
couchapp:
demo:
app: 'app/app.js'
db: 'http://localhost:5984/demo-couchapp'
install:
appclient:
src: ['dist-compiled/client.js']
dest: 'app/attachments/js'
recess:
dev:
src: ["src/style.less"]
dest: "dist/style.css"
options:
compile: true
grunt.registerTask "default", "coffee:app coffee:client requirejs install:appclient haml:dev couchapp:demo"
grunt.registerTask "test", "default qunit"
# ___ _ _ _ ___ _
# |_ _|_ _ __| |_ __ _| | | / __|___ _ _ __| |_ __ _ _ __ _ __
# | || ' \(_-< _/ _` | | | | (__/ _ \ || / _| ' \/ _` | '_ \ '_ \
# |___|_||_/__/\__\__,_|_|_| \___\___/\_,_\__|_||_\__,_| .__/ .__/
# |_| |_|
grunt.registerMultiTask "couchapp", "Install Couchapp", ->
couchapp = require 'couchapp'
appobj = require(path.join(process.cwd(), path.normalize(this.data.app)))
done = @async()
couchapp.createApp appobj, this.data.db, (app) ->
app.push(done)
# _ _ _ __ __ _ _ _ _ _____ __ __ _
# | || | /_\ | \/ | | | |_ ___ | || |_ _| \/ | |
# | __ |/ _ \| |\/| | |__ | _/ _ \ | __ | | | | |\/| | |__
# |_||_/_/ \_\_| |_|____| \__\___/ |_||_| |_| |_| |_|____|
#
grunt.registerHelper "haml", (src, dest, done) ->
args =
cmd: "haml"
args: [ "--unix-newlines", "--no-escape-attrs", "--double-quote-attributes", src ]
grunt.utils.spawn args, (err, result) ->
console.log err if err
out = path.basename(src, ".haml")
grunt.file.write path.join(dest, out + ".html"), result.stdout
done()
grunt.registerMultiTask "haml", "Compile HAML", ->
done = @async()
sources = grunt.file.expandFiles(this.file.src)
dest = this.file.dest
async.forEachSeries sources, ((path, cb) ->
grunt.helper "haml", path, dest, cb
), done
# ___ _ ___ __ __
# / __|_ _ _ _ _ _| |_ / __|___ / _|/ _|___ ___
# | (_ | '_| || | ' \ _| (__/ _ \ _| _/ -_) -_)
# \___|_| \_,_|_||_\__|\___\___/_| |_| \___\___|
#
grunt.registerTask "gruntjs", "convert grunt.coffee to grunt.js", ->
jFileName = path.join __dirname, "grunt.js"
cFileName = path.join __dirname, "grunt.coffee"
jStat = fs.statSync jFileName
cStat = fs.statSync cFileName
jmTime = jStat.mtime
cmTime = cStat.mtime
if cmTime < jmTime
grunt.verbose.writeln "grunt.js newer than grunt.coffee, skipping compile"
return
cSource = fs.readFileSync cFileName, "utf-8"
try
jSource = coffee.compile cSource,
bare: true
catch e
grunt.fail.fatal e
fs.writeFileSync jFileName, jSource, "utf-8"
grunt.log.writeln "compiled #{cFileName} to #{jFileName}"
# ___
# / __|___ _ __ _ _
# | (__/ _ \ '_ \ || |
# \___\___/ .__/\_, |
# |_| |__/
grunt.registerHelper "install", (src, dest, done) ->
grunt.file.copy src, path.join(dest, path.basename(src))
done() if done
grunt.registerMultiTask "install", "Install Files", ->
sources = grunt.file.expandFiles(this.file.src)
dest = this.file.dest
sources.forEach (path) ->
grunt.helper "install", path, dest, null

184
grunt.js Normal file
View File

@ -0,0 +1,184 @@
var async, coffee, fs, path;
path = require("path");
async = require("async");
fs = require("fs");
coffee = require('coffee-script');
module.exports = function(grunt) {
grunt.loadNpmTasks("grunt-coffee");
grunt.loadNpmTasks("grunt-requirejs");
grunt.initConfig({
pkg: "<json:CouchappRequirejsOnepage.json>",
meta: {
banner: "/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - " + "<%= grunt.template.today(\"yyyy-mm-dd\") %>\n" + "<%= pkg.homepage ? \"* \" + pkg.homepage + \"\n\" : \"\" %>" + "* Copyright (c) <%= grunt.template.today(\"yyyy\") %> <%= pkg.author.name %>;" + " Licensed <%= _.pluck(pkg.licenses, \"type\").join(\", \") %> */"
},
concat: {
dist: {
src: ["<banner:meta.banner>", "<file_strip_banner:src/<%= pkg.name %>.js>"],
dest: "dist/<%= pkg.name %>.js"
}
},
min: {
dist: {
src: ["<banner:meta.banner>", "<config:concat.dist.dest>"],
dest: "dist/<%= pkg.name %>.min.js"
}
},
qunit: {
files: ["test/**/*.html"]
},
lint: {
files: ["grunt.js", "src/**/*.js", "test/**/*.js"]
},
watch: {
files: "<config:lint.files>",
tasks: "lint qunit"
},
jshint: {
options: {
curly: true,
eqeqeq: true,
immed: true,
latedef: true,
newcap: true,
noarg: true,
sub: true,
undef: true,
boss: true,
eqnull: true,
browser: true
},
globals: {
jQuery: true
}
},
haml: {
dev: {
src: ['src/index.haml'],
dest: 'app/attachments/'
}
},
coffee: {
app: {
src: ['src/app.coffee'],
dest: 'app/'
},
client: {
src: ['src/client.coffee', 'src/library.coffee'],
dest: 'dist/'
}
},
requirejs: {
dir: 'dist-compiled',
appDir: 'dist',
baseUrl: '.',
paths: {
'jquery': '../libs/jquery/jquery'
},
deps: ['../libs/require/require'],
modules: [
{
name: "client"
}
]
},
couchapp: {
demo: {
app: 'app/app.js',
db: 'http://localhost:5984/demo-couchapp'
}
},
install: {
appclient: {
src: ['dist-compiled/client.js'],
dest: 'app/attachments/js'
}
},
recess: {
dev: {
src: ["src/style.less"],
dest: "dist/style.css",
options: {
compile: true
}
}
}
});
grunt.registerTask("default", "coffee:app coffee:client requirejs install:appclient haml:dev couchapp:demo");
grunt.registerTask("test", "default qunit");
grunt.registerMultiTask("couchapp", "Install Couchapp", function() {
var appobj, couchapp, done;
couchapp = require('couchapp');
appobj = require(path.join(process.cwd(), path.normalize(this.data.app)));
done = this.async();
return couchapp.createApp(appobj, this.data.db, function(app) {
return app.push(done);
});
});
grunt.registerHelper("haml", function(src, dest, done) {
var args;
args = {
cmd: "haml",
args: ["--unix-newlines", "--no-escape-attrs", "--double-quote-attributes", src]
};
return grunt.utils.spawn(args, function(err, result) {
var out;
if (err) {
console.log(err);
}
out = path.basename(src, ".haml");
grunt.file.write(path.join(dest, out + ".html"), result.stdout);
return done();
});
});
grunt.registerMultiTask("haml", "Compile HAML", function() {
var dest, done, sources;
done = this.async();
sources = grunt.file.expandFiles(this.file.src);
dest = this.file.dest;
return async.forEachSeries(sources, (function(path, cb) {
return grunt.helper("haml", path, dest, cb);
}), done);
});
grunt.registerTask("gruntjs", "convert grunt.coffee to grunt.js", function() {
var cFileName, cSource, cStat, cmTime, jFileName, jSource, jStat, jmTime;
jFileName = path.join(__dirname, "grunt.js");
cFileName = path.join(__dirname, "grunt.coffee");
jStat = fs.statSync(jFileName);
cStat = fs.statSync(cFileName);
jmTime = jStat.mtime;
cmTime = cStat.mtime;
if (cmTime < jmTime) {
grunt.verbose.writeln("grunt.js newer than grunt.coffee, skipping compile");
return;
}
cSource = fs.readFileSync(cFileName, "utf-8");
try {
jSource = coffee.compile(cSource, {
bare: true
});
} catch (e) {
grunt.fail.fatal(e);
}
fs.writeFileSync(jFileName, jSource, "utf-8");
return grunt.log.writeln("compiled " + cFileName + " to " + jFileName);
});
grunt.registerHelper("install", function(src, dest, done) {
grunt.file.copy(src, path.join(dest, path.basename(src)));
if (done) {
return done();
}
});
return grunt.registerMultiTask("install", "Install Files", function() {
var dest, sources;
sources = grunt.file.expandFiles(this.file.src);
dest = this.file.dest;
return sources.forEach(function(path) {
return grunt.helper("install", path, dest, null);
});
});
};

14
libs/jquery-loader.js vendored Normal file
View File

@ -0,0 +1,14 @@
(function() {
// Get any jquery=___ param from the query string.
var jqversion = location.search.match(/[?&]jquery=(.*?)(?=&|$)/);
var path;
if (jqversion) {
// A version was specified, load that version from code.jquery.com.
path = 'http://code.jquery.com/jquery-' + jqversion[1] + '.js';
} else {
// No version was specified, load the local version.
path = '../libs/jquery/jquery.js';
}
// This is the only time I'll ever use document.write, I promise!
document.write('<script src="' + path + '"></script>');
}());

9404
libs/jquery/jquery.js vendored Normal file

File diff suppressed because it is too large Load Diff

232
libs/qunit/qunit.css Normal file
View File

@ -0,0 +1,232 @@
/**
* QUnit v1.4.0 - A JavaScript Unit Testing Framework
*
* http://docs.jquery.com/QUnit
*
* Copyright (c) 2012 John Resig, Jörn Zaefferer
* Dual licensed under the MIT (MIT-LICENSE.txt)
* or GPL (GPL-LICENSE.txt) licenses.
*/
/** Font Family and Sizes */
#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
}
#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
#qunit-tests { font-size: smaller; }
/** Resets */
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
margin: 0;
padding: 0;
}
/** Header */
#qunit-header {
padding: 0.5em 0 0.5em 1em;
color: #8699a4;
background-color: #0d3349;
font-size: 1.5em;
line-height: 1em;
font-weight: normal;
border-radius: 15px 15px 0 0;
-moz-border-radius: 15px 15px 0 0;
-webkit-border-top-right-radius: 15px;
-webkit-border-top-left-radius: 15px;
}
#qunit-header a {
text-decoration: none;
color: #c2ccd1;
}
#qunit-header a:hover,
#qunit-header a:focus {
color: #fff;
}
#qunit-header label {
display: inline-block;
}
#qunit-banner {
height: 5px;
}
#qunit-testrunner-toolbar {
padding: 0.5em 0 0.5em 2em;
color: #5E740B;
background-color: #eee;
}
#qunit-userAgent {
padding: 0.5em 0 0.5em 2.5em;
background-color: #2b81af;
color: #fff;
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
}
/** Tests: Pass/Fail */
#qunit-tests {
list-style-position: inside;
}
#qunit-tests li {
padding: 0.4em 0.5em 0.4em 2.5em;
border-bottom: 1px solid #fff;
list-style-position: inside;
}
#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
display: none;
}
#qunit-tests li strong {
cursor: pointer;
}
#qunit-tests li a {
padding: 0.5em;
color: #c2ccd1;
text-decoration: none;
}
#qunit-tests li a:hover,
#qunit-tests li a:focus {
color: #000;
}
#qunit-tests ol {
margin-top: 0.5em;
padding: 0.5em;
background-color: #fff;
border-radius: 15px;
-moz-border-radius: 15px;
-webkit-border-radius: 15px;
box-shadow: inset 0px 2px 13px #999;
-moz-box-shadow: inset 0px 2px 13px #999;
-webkit-box-shadow: inset 0px 2px 13px #999;
}
#qunit-tests table {
border-collapse: collapse;
margin-top: .2em;
}
#qunit-tests th {
text-align: right;
vertical-align: top;
padding: 0 .5em 0 0;
}
#qunit-tests td {
vertical-align: top;
}
#qunit-tests pre {
margin: 0;
white-space: pre-wrap;
word-wrap: break-word;
}
#qunit-tests del {
background-color: #e0f2be;
color: #374e0c;
text-decoration: none;
}
#qunit-tests ins {
background-color: #ffcaca;
color: #500;
text-decoration: none;
}
/*** Test Counts */
#qunit-tests b.counts { color: black; }
#qunit-tests b.passed { color: #5E740B; }
#qunit-tests b.failed { color: #710909; }
#qunit-tests li li {
margin: 0.5em;
padding: 0.4em 0.5em 0.4em 0.5em;
background-color: #fff;
border-bottom: none;
list-style-position: inside;
}
/*** Passing Styles */
#qunit-tests li li.pass {
color: #5E740B;
background-color: #fff;
border-left: 26px solid #C6E746;
}
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
#qunit-tests .pass .test-name { color: #366097; }
#qunit-tests .pass .test-actual,
#qunit-tests .pass .test-expected { color: #999999; }
#qunit-banner.qunit-pass { background-color: #C6E746; }
/*** Failing Styles */
#qunit-tests li li.fail {
color: #710909;
background-color: #fff;
border-left: 26px solid #EE5757;
white-space: pre;
}
#qunit-tests > li:last-child {
border-radius: 0 0 15px 15px;
-moz-border-radius: 0 0 15px 15px;
-webkit-border-bottom-right-radius: 15px;
-webkit-border-bottom-left-radius: 15px;
}
#qunit-tests .fail { color: #000000; background-color: #EE5757; }
#qunit-tests .fail .test-name,
#qunit-tests .fail .module-name { color: #000000; }
#qunit-tests .fail .test-actual { color: #EE5757; }
#qunit-tests .fail .test-expected { color: green; }
#qunit-banner.qunit-fail { background-color: #EE5757; }
/** Result */
#qunit-testresult {
padding: 0.5em 0.5em 0.5em 2.5em;
color: #2b81af;
background-color: #D2E0E6;
border-bottom: 1px solid white;
}
/** Fixture */
#qunit-fixture {
position: absolute;
top: -10000px;
left: -10000px;
width: 1000px;
height: 1000px;
}

1659
libs/qunit/qunit.js Normal file

File diff suppressed because it is too large Load Diff

34
libs/require/require.js Normal file
View File

@ -0,0 +1,34 @@
/*
RequireJS 2.0.1 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
Available via the MIT or new BSD license.
see: http://github.com/jrburke/requirejs for details
*/
var requirejs,require,define;
(function(Z){function w(b){return I.call(b)==="[object Function]"}function E(b){return I.call(b)==="[object Array]"}function n(b,d){if(b){var f;for(f=0;f<b.length;f+=1)if(d(b[f],f,b))break}}function L(b,d){if(b){var f;for(f=b.length-1;f>-1;f-=1)if(d(b[f],f,b))break}}function A(b,d){for(var f in b)if(b.hasOwnProperty(f)&&d(b[f],f))break}function R(b,d,f){d&&A(d,function(d,e){if(f||!b.hasOwnProperty(e))b[e]=d})}function s(b,d){return function(){return d.apply(b,arguments)}}function $(b){if(!b)return b;
var d=Z;n(b.split("."),function(b){d=d[b]});return d}function aa(b,d,f){return function(){var g=ga.call(arguments,0),e;if(f&&w(e=g[g.length-1]))e.__requireJsBuild=!0;g.push(d);return b.apply(null,g)}}function ba(b,d,f){n([["toUrl"],["undef"],["defined","requireDefined"],["specified","requireSpecified"]],function(g){b[g[0]]=aa(d[g[1]||g[0]],f)})}function F(b,d,f,g){d=Error(d+"\nhttp://requirejs.org/docs/errors.html#"+b);d.requireType=b;d.requireModules=g;if(f)d.originalError=f;return d}function ha(){if(G&&
G.readyState==="interactive")return G;L(document.getElementsByTagName("script"),function(b){if(b.readyState==="interactive")return G=b});return G}var ia=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,ja=/require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,ca=/\.js$/,ka=/^\.\//,I=Object.prototype.toString,x=Array.prototype,ga=x.slice,la=x.splice,u=!!(typeof window!=="undefined"&&navigator&&document),da=!u&&typeof importScripts!=="undefined",ma=u&&navigator.platform==="PLAYSTATION 3"?/^complete$/:/^(complete|loaded)$/,
S=typeof opera!=="undefined"&&opera.toString()==="[object Opera]",v={},q={},M=[],J=!1,l,t,B,y,C,G,H,N,ea;if(typeof define==="undefined"){if(typeof requirejs!=="undefined"){if(w(requirejs))return;q=requirejs;requirejs=void 0}typeof require!=="undefined"&&!w(require)&&(q=require,require=void 0);l=requirejs=function(b,d,f,g){var e="_",n;!E(b)&&typeof b!=="string"&&(n=b,E(d)?(b=d,d=f,f=g):b=[]);if(n&&n.context)e=n.context;(g=v[e])||(g=v[e]=l.s.newContext(e));n&&g.configure(n);return g.require(b,d,f)};
l.config=function(b){return l(b)};require||(require=l);l.version="2.0.1";l.jsExtRegExp=/^\/|:|\?|\.js$/;l.isBrowser=u;x=l.s={contexts:v,newContext:function(b){function d(a,c,j){var r=c&&c.split("/"),b=k.map,m=b&&b["*"],h,d,f,e;if(a&&a.charAt(0)===".")if(c){r=k.pkgs[c]?[c]:r.slice(0,r.length-1);c=a=r.concat(a.split("/"));for(h=0;c[h];h+=1)if(d=c[h],d===".")c.splice(h,1),h-=1;else if(d==="..")if(h===1&&(c[2]===".."||c[0]===".."))break;else h>0&&(c.splice(h-1,2),h-=2);h=k.pkgs[c=a[0]];a=a.join("/");
h&&a===c+"/"+h.main&&(a=c)}else a.indexOf("./")===0&&(a=a.substring(2));if(j&&(r||m)&&b){c=a.split("/");for(h=c.length;h>0;h-=1){f=c.slice(0,h).join("/");if(r)for(d=r.length;d>0;d-=1)if(j=b[r.slice(0,d).join("/")])if(j=j[f]){e=j;break}!e&&m&&m[f]&&(e=m[f]);if(e){c.splice(0,h,e);a=c.join("/");break}}}return a}function f(a){u&&n(document.getElementsByTagName("script"),function(c){if(c.getAttribute("data-requiremodule")===a&&c.getAttribute("data-requirecontext")===i.contextName)return c.parentNode.removeChild(c),
!0})}function g(a){var c=k.paths[a];if(c&&E(c)&&c.length>1)return f(a),c.shift(),i.undef(a),i.require([a]),!0}function e(a,c,j,r){var b=a?a.indexOf("!"):-1,m=null,h=c?c.name:null,e=a,f=!0,g="",k,l;a||(f=!1,a="_@r"+(L+=1));b!==-1&&(m=a.substring(0,b),a=a.substring(b+1,a.length));m&&(m=d(m,h,r),l=p[m]);a&&(m?g=l&&l.normalize?l.normalize(a,function(a){return d(a,h,r)}):d(a,h,r):(g=d(a,h,r),k=O[g],k||(k=i.nameToUrl(a,null,c),O[g]=k)));a=m&&!l&&!j?"_unnormalized"+(N+=1):"";return{prefix:m,name:g,parentMap:c,
unnormalized:!!a,url:k,originalName:e,isDefine:f,id:(m?m+"!"+g:g)+a}}function q(a){var c=a.id,j=o[c];j||(j=o[c]=new i.Module(a));return j}function t(a,c,j){var b=a.id,fa=o[b];if(p.hasOwnProperty(b)&&(!fa||fa.defineEmitComplete))c==="defined"&&j(p[b]);else q(a).on(c,j)}function z(a,c){var j=a.requireModules,b=!1;if(c)c(a);else if(n(j,function(c){if(c=o[c])c.error=a,c.events.error&&(b=!0,c.emit("error",a))}),!b)l.onError(a)}function x(){M.length&&(la.apply(D,[D.length-1,0].concat(M)),M=[])}function v(a,
c,j){a=a&&a.map;c=aa(j||i.require,a,c);ba(c,i,a);c.isBrowser=u;return c}function y(a){delete o[a];n(K,function(c,j){if(c.map.id===a)return K.splice(j,1),c.defined||(i.waitCount-=1),!0})}function B(a,c){var j=a.map.id,b=a.depMaps,d;if(a.inited){if(c[j])return a;c[j]=!0;n(b,function(a){if(a=o[a.id])return!a.inited||!a.enabled?(d=null,delete c[j],!0):d=B(a,c)});return d}}function C(a,c,j){var b=a.map.id,d=a.depMaps;if(a.inited&&a.map.isDefine){if(c[b])return p[b];c[b]=a;n(d,function(d){var d=d.id,h=
o[d];!P[d]&&h&&(!h.inited||!h.enabled?j[b]=!0:(h=C(h,c,j),j[d]||a.defineDepById(d,h)))});a.check(!0);return p[b]}}function H(a){a.check()}function T(){var a=k.waitSeconds*1E3,c=a&&i.startTime+a<(new Date).getTime(),j=[],b=!1,d=!0,m,h,e;if(!U){U=!0;A(o,function(a){m=a.map;h=m.id;if(a.enabled&&!a.error)if(!a.inited&&c)g(h)?b=e=!0:(j.push(h),f(h));else if(!a.inited&&a.fetched&&m.isDefine&&(b=!0,!m.prefix))return d=!1});if(c&&j.length)return a=F("timeout","Load timeout for modules: "+j,null,j),a.contextName=
i.contextName,z(a);d&&(n(K,function(a){if(!a.defined){var a=B(a,{}),c={};a&&(C(a,c,{}),A(c,H))}}),A(o,H));if((!c||e)&&b)if((u||da)&&!V)V=setTimeout(function(){V=0;T()},50);U=!1}}function W(a){q(e(a[0],null,!0)).init(a[1],a[2])}function I(a){var a=a.currentTarget||a.srcElement,c=i.onScriptLoad;a.detachEvent&&!S?a.detachEvent("onreadystatechange",c):a.removeEventListener("load",c,!1);c=i.onScriptError;a.detachEvent&&!S||a.removeEventListener("error",c,!1);return{node:a,id:a&&a.getAttribute("data-requiremodule")}}
var k={waitSeconds:7,baseUrl:"./",paths:{},pkgs:{},shim:{}},o={},X={},D=[],p={},O={},Q={},L=1,N=1,K=[],U,Y,i,P,V;P={require:function(a){return v(a)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports=p[a.map.id]={}},module:function(a){return a.module={id:a.map.id,uri:a.map.url,config:function(){return k.config&&k.config[a.map.id]||{}},exports:p[a.map.id]}}};Y=function(a){this.events=X[a.id]||{};this.map=a;this.shim=k.shim[a.id];this.depExports=[];this.depMaps=[];this.depMatched=
[];this.pluginMaps={};this.depCount=0};Y.prototype={init:function(a,c,b,d){d=d||{};if(!this.inited){this.factory=c;if(b)this.on("error",b);else this.events.error&&(b=s(this,function(a){this.emit("error",a)}));n(a,s(this,function(a,c){typeof a==="string"&&(a=e(a,this.map.isDefine?this.map:this.map.parentMap,!1,!0),this.depMaps.push(a));var d=P[a.id];d?this.depExports[c]=d(this):(this.depCount+=1,t(a,"defined",s(this,function(a){this.defineDep(c,a);this.check()})),b&&t(a,"error",b))}));this.inited=
!0;this.ignore=d.ignore;d.enabled||this.enabled?this.enable():this.check()}},defineDepById:function(a,c){var b;n(this.depMaps,function(c,d){if(c.id===a)return b=d,!0});return this.defineDep(b,c)},defineDep:function(a,c){this.depMatched[a]||(this.depMatched[a]=!0,this.depCount-=1,this.depExports[a]=c)},fetch:function(){if(!this.fetched)this.fetched=!0,i.startTime=(new Date).getTime(),this.map.prefix?this.callPlugin():this.shim?v(this,!0)(this.shim.deps||[],s(this,function(){this.load()})):this.load()},
load:function(){var a=this.map.url;Q[a]||(Q[a]=!0,i.load(this.map.id,a))},check:function(a){if(this.enabled){var c=this.map.id,b=this.depExports,d=this.exports,e=this.factory,m;if(this.inited)if(this.error)this.emit("error",this.error);else{if(!this.defining){this.defining=!0;if(this.depCount<1&&!this.defined){if(w(e)){if(this.events.error)try{d=i.execCb(c,e,b,d)}catch(h){m=h}else d=i.execCb(c,e,b,d);if(this.map.isDefine)if((b=this.module)&&b.exports!==void 0&&b.exports!==this.exports)d=b.exports;
else if(d===void 0&&this.usingExports)d=this.exports;if(m)return m.requireMap=this.map,m.requireModules=[this.map.id],m.requireType="define",z(this.error=m)}else d=e;this.exports=d;if(this.map.isDefine&&!this.ignore&&(p[c]=d,l.onResourceLoad))l.onResourceLoad(i,this.map,this.depMaps);delete o[c];this.defined=!0;i.waitCount-=1;i.waitCount===0&&(K=[])}this.defining=!1;if(!a&&this.defined&&!this.defineEmitted)this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0}}else this.fetch()}},
callPlugin:function(){var a=this.map,c=a.id,b=e(a.prefix,null,!1,!0);t(b,"defined",s(this,function(b){var j=this.map.name,m=this.map.parentMap?this.map.parentMap.name:null;if(this.map.unnormalized){if(b.normalize&&(j=b.normalize(j,function(a){return d(a,m,!0)})||""),b=e(a.prefix+"!"+j),t(b,"defined",s(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),b=o[b.id]){if(this.events.error)b.on("error",s(this,function(a){this.emit("error",a)}));b.enable()}}else j=s(this,function(a){this.init([],
function(){return a},null,{enabled:!0})}),j.error=s(this,function(a){this.inited=!0;this.error=a;a.requireModules=[c];A(o,function(a){a.map.id.indexOf(c+"_unnormalized")===0&&y(a.map.id)});z(a)}),j.fromText=function(a,c){var b=J;b&&(J=!1);l.exec(c);b&&(J=!0);i.completeLoad(a)},b.load(a.name,v(a.parentMap,!0,function(a,c){return i.require(a,c)}),j,k)}));i.enable(b,this);this.pluginMaps[b.id]=b},enable:function(){this.enabled=!0;if(!this.waitPushed)K.push(this),i.waitCount+=1,this.waitPushed=!0;n(this.depMaps,
s(this,function(a){var c=a.id,b=o[c];!P[c]&&b&&!b.enabled&&i.enable(a,this)}));A(this.pluginMaps,s(this,function(a){var c=o[a.id];c&&!c.enabled&&i.enable(a,this)}));this.check()},on:function(a,c){var b=this.events[a];b||(b=this.events[a]=[]);b.push(c)},emit:function(a,c){n(this.events[a],function(a){a(c)});a==="error"&&delete this.events[a]}};return i={config:k,contextName:b,registry:o,defined:p,urlMap:O,urlFetched:Q,waitCount:0,defQueue:D,Module:Y,makeModuleMap:e,configure:function(a){a.baseUrl&&
a.baseUrl.charAt(a.baseUrl.length-1)!=="/"&&(a.baseUrl+="/");var c=k.paths,b=k.pkgs,d=k.shim,e=k.map||{};R(k,a,!0);R(c,a.paths,!0);k.paths=c;if(a.map)R(e,a.map,!0),k.map=e;if(a.shim)A(a.shim,function(a,c){E(a)&&(a={deps:a});if(a.exports&&!a.exports.__buildReady)a.exports=i.makeShimExports(a.exports);d[c]=a}),k.shim=d;if(a.packages)n(a.packages,function(a){a=typeof a==="string"?{name:a}:a;b[a.name]={name:a.name,location:a.location||a.name,main:(a.main||"main").replace(ka,"").replace(ca,"")}}),k.pkgs=
b;if(a.deps||a.callback)i.require(a.deps||[],a.callback)},makeShimExports:function(a){var c;return typeof a==="string"?(c=function(){return $(a)},c.exports=a,c):function(){return a.apply(Z,arguments)}},requireDefined:function(a,c){var b=e(a,c,!1,!0).id;return p.hasOwnProperty(b)},requireSpecified:function(a,c){a=e(a,c,!1,!0).id;return p.hasOwnProperty(a)||o.hasOwnProperty(a)},require:function(a,c,d,f){var g;if(typeof a==="string"){if(w(c))return z(F("requireargs","Invalid require call"),d);if(l.get)return l.get(i,
a,c);a=e(a,c,!1,!0);a=a.id;return!p.hasOwnProperty(a)?z(F("notloaded",'Module name "'+a+'" has not been loaded yet for context: '+b)):p[a]}d&&!w(d)&&(f=d,d=void 0);c&&!w(c)&&(f=c,c=void 0);for(x();D.length;)if(g=D.shift(),g[0]===null)return z(F("mismatch","Mismatched anonymous define() module: "+g[g.length-1]));else W(g);q(e(null,f)).init(a,c,d,{enabled:!0});T();return i.require},undef:function(a){var c=e(a,null,!0),b=o[a];delete p[a];delete O[a];delete Q[c.url];delete X[a];if(b){if(b.events.defined)X[a]=
b.events;y(a)}},enable:function(a){o[a.id]&&q(a).enable()},completeLoad:function(a){var c=k.shim[a]||{},b=c.exports&&c.exports.exports,d,e;for(x();D.length;){e=D.shift();if(e[0]===null){e[0]=a;if(d)break;d=!0}else e[0]===a&&(d=!0);W(e)}e=o[a];if(!d&&!p[a]&&e&&!e.inited)if(k.enforceDefine&&(!b||!$(b)))if(g(a))return;else return z(F("nodefine","No define call for "+a,null,[a]));else W([a,c.deps||[],c.exports]);T()},toUrl:function(a,c){var b=a.lastIndexOf("."),d=null;b!==-1&&(d=a.substring(b,a.length),
a=a.substring(0,b));return i.nameToUrl(a,d,c)},nameToUrl:function(a,c,b){var e,f,g,h,i,a=d(a,b&&b.id,!0);if(l.jsExtRegExp.test(a))c=a+(c||"");else{e=k.paths;f=k.pkgs;b=a.split("/");for(h=b.length;h>0;h-=1)if(i=b.slice(0,h).join("/"),g=f[i],i=e[i]){E(i)&&(i=i[0]);b.splice(0,h,i);break}else if(g){a=a===g.name?g.location+"/"+g.main:g.location;b.splice(0,h,a);break}c=b.join("/")+(c||".js");c=(c.charAt(0)==="/"||c.match(/^[\w\+\.\-]+:/)?"":k.baseUrl)+c}return k.urlArgs?c+((c.indexOf("?")===-1?"?":"&")+
k.urlArgs):c},load:function(a,b){l.load(i,a,b)},execCb:function(a,b,d,e){return b.apply(e,d)},onScriptLoad:function(a){if(a.type==="load"||ma.test((a.currentTarget||a.srcElement).readyState))G=null,a=I(a),i.completeLoad(a.id)},onScriptError:function(a){var b=I(a);if(!g(b.id))return z(F("scripterror","Script error",a,[b.id]))}}}};l({});ba(l,v._);if(u&&(t=x.head=document.getElementsByTagName("head")[0],B=document.getElementsByTagName("base")[0]))t=x.head=B.parentNode;l.onError=function(b){throw b;};
l.load=function(b,d,f){var g=b&&b.config||{},e;if(u)return e=g.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script"),e.type=g.scriptType||"text/javascript",e.charset="utf-8",e.setAttribute("data-requirecontext",b.contextName),e.setAttribute("data-requiremodule",d),e.attachEvent&&!(e.attachEvent.toString&&e.attachEvent.toString().indexOf("[native code")<0)&&!S?(J=!0,e.attachEvent("onreadystatechange",b.onScriptLoad)):(e.addEventListener("load",
b.onScriptLoad,!1),e.addEventListener("error",b.onScriptError,!1)),e.src=f,H=e,B?t.insertBefore(e,B):t.appendChild(e),H=null,e;else da&&(importScripts(f),b.completeLoad(d))};u&&L(document.getElementsByTagName("script"),function(b){if(!t)t=b.parentNode;if(y=b.getAttribute("data-main")){if(!q.baseUrl)C=y.split("/"),N=C.pop(),ea=C.length?C.join("/")+"/":"./",q.baseUrl=ea,y=N.replace(ca,"");q.deps=q.deps?q.deps.concat(y):[y];return!0}});define=function(b,d,f){var g,e;typeof b!=="string"&&(f=d,d=b,b=null);
E(d)||(f=d,d=[]);!d.length&&w(f)&&f.length&&(f.toString().replace(ia,"").replace(ja,function(b,e){d.push(e)}),d=(f.length===1?["require"]:["require","exports","module"]).concat(d));if(J&&(g=H||ha()))b||(b=g.getAttribute("data-requiremodule")),e=v[g.getAttribute("data-requirecontext")];(e?e.defQueue:M).push([b,d,f])};define.amd={jQuery:!0};l.exec=function(b){return eval(b)};l(q)}})(this);

41
package.json Normal file
View File

@ -0,0 +1,41 @@
{
"name": "couchapp-requirejs-onepageapp-demo",
"description": "A Demo Project showing how to integrate CouchApp and Require.JS",
"version": "0.1.0",
"author": {
"name": "Ken Elf Mathieu Sternberg",
"email": "elf.sternberg@gmail.com"
},
"repository": {
"type": "git",
"url": "git://github.com/elf/couchapp-requirejs-onepageapp-demo.git"
},
"bugs": {
"url": "https://github.com/elf/couchapp-requirejs-onepageapp-demo/issues"
},
"licenses": [
{
"type": "MIT",
"url": "https://github.com/elf/couchapp-requirejs-onepageapp-demo/blob/master/LICENSE-MIT"
}
],
"engines": {
"node": ">= 0.6.0"
},
"scripts": {
"test": "grunt qunit"
},
"keywords": ["clientside", "grunt", "coffeescript", "node"],
"devDependencies": {
"grunt": "~0.3.11",
"grunt-requirejs": "0.2.9",
"grunt-coffee": "0.0.5",
"grunt-recess": "0.1.0",
"coffee-script": "1.3.3",
"async": "0.1.22",
"underscore": "1.3.3",
"couchapp": "0.9.1",
"connect": "2.3.9"
}
}

20
src/app.coffee Normal file
View File

@ -0,0 +1,20 @@
couchapp = require('couchapp')
path = require('path')
ddoc =
_id:'_design/app'
rewrites: {}
views: {}
shows: {}
lists: {}
validate_doc_update: (newDoc, oldDoc, userCtx) ->
if newDoc._deleted == true && userCtx.roles.indexOf('_admin') == -1
throw "Only admin can delete documents on this database.";
couchapp.loadAttachments ddoc, path.join(__dirname, 'attachments')
module.exports = ddoc

8
src/client.coffee Normal file
View File

@ -0,0 +1,8 @@
require.config
paths:
'jquery': '../libs/jquery/jquery'
require ['jquery', 'library'], ($, doit) ->
$ ->
doit()

11
src/index.haml Normal file
View File

@ -0,0 +1,11 @@
!!! 5
%html{:xmlns => "http://www.w3.org/1999/xhtml"}
%head
%meta{:content => "text/html; charset=utf-8", "http-equiv" => "Content-Type"}/
%meta{:name => "keywords", :content => ""}/
%meta{:name => "description", :content => ""}/
%script{:language => "javascript", :type => "text/javascript", :src => "js/client.js"}
%title Demo
%body
%h1 Demonstration
%p#working It worked?

6
src/library.coffee Normal file
View File

@ -0,0 +1,6 @@
define ['jquery'], ($) ->
-> $('#working').html "<b style=\"color:royalblue\">Yes, it worked!</b>"