Commit db064303 authored by 神楽坂玲奈's avatar 神楽坂玲奈

deck builder

parent 2337df64
GNU GPL v3
\ No newline at end of file
locale = 'zh'
class Card extends Spine.Model
@configure "Card", "atk", "name"
@extend Spine.Model.Ajax
@extend Spine.Events
@url: "https://api.mongolab.com/api/1/databases/mycard/collections/cards?apiKey=508e5726e4b0c54ca4492ead"
@locale_url: "https://api.mongolab.com/api/1/databases/mycard/collections/lang_#{locale}?apiKey=508e5726e4b0c54ca4492ead"
@query: (q, callback)->
$.getJSON "#{@url}&q=#{JSON.stringify(q)}", (cards) ->
cards_id = (card._id for card in cards)
$.getJSON "#{Card.locale_url}&q=#{JSON.stringify({_id: { $in: cards_id}})}", (langs) ->
@model.refresh (new Card(lang) for lang in langs
id = lang["id"] = lang["_id"]
for card in cards
if card["_id"] == id
$.extend(lang, card)
break
)
class CardUsage extends Spine.Model
@configure "CardUsage", "card_id", "count", "side"
decode = (str)->
key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789*-="
result = 0
for char in str
result <<= 6
result += key.indexOf(char)
result
$('img#qrcode').attr('src', 'https://chart.googleapis.com/chart?chs=200x200&cht=qr&chl=' + encodeURIComponent(location.href))
$('#name').html($.url().param('name'))
cards_encoded = $.url().param('cards')
deck = []
cards_id = []
for i in [0...cards_encoded.length] by 5
decoded = decode(cards_encoded.substr(i, 5))
side = decoded >> 29
count = decoded >> 27 & 0x3
id = decoded & 0x07FFFFFF
cards_id.push id
deck.push<< {card_id: id, count: count, side: side}
$('#cards').append($('<dt />', {text: id}))
$('#cards').append($('<dd />', {text: count}))
Card.query {_id: { $in: cards_id}}
Card.bind "refresh",
// Generated by CoffeeScript 1.4.0
(function() {
var Card, cards_encoded, cards_id, count, deck, decode, decoded, i, id, locale, side, _i, _ref,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
locale = 'zh';
Card = (function(_super) {
__extends(Card, _super);
function Card() {
return Card.__super__.constructor.apply(this, arguments);
}
Card.configure("Card", "atk", "name");
Card.extend(Spine.Model.Ajax);
Card.extend(Spine.Events);
Card.url = "https://api.mongolab.com/api/1/databases/mycard/collections/cards?apiKey=508e5726e4b0c54ca4492ead";
Card.locale_url = "https://api.mongolab.com/api/1/databases/mycard/collections/lang_" + locale + "?apiKey=508e5726e4b0c54ca4492ead";
Card.query = function(q, callback) {
return $.getJSON("" + this.url + "&q=" + (JSON.stringify(q)), function(cards) {
var card, cards_id;
cards_id = (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = cards.length; _i < _len; _i++) {
card = cards[_i];
_results.push(card._id);
}
return _results;
})();
return $.getJSON("" + Card.locale_url + "&q=" + (JSON.stringify({
_id: {
$in: cards_id
}
})), function(langs) {
var id, lang, _i, _j, _len, _len1;
for (_i = 0, _len = langs.length; _i < _len; _i++) {
lang = langs[_i];
id = lang["id"] = lang["_id"];
for (_j = 0, _len1 = cards.length; _j < _len1; _j++) {
card = cards[_j];
if (card["_id"] === id) {
$.extend(lang, card);
break;
}
}
(new Card(lang)).save;
}
return alert(Card.first());
});
});
};
return Card;
})(Spine.Model);
decode = function(str) {
var char, key, result, _i, _len;
key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789*-=";
result = 0;
for (_i = 0, _len = str.length; _i < _len; _i++) {
char = str[_i];
result <<= 6;
result += key.indexOf(char);
}
return result;
};
$('img#qrcode').attr('src', 'https://chart.googleapis.com/chart?chs=200x200&cht=qr&chl=' + encodeURIComponent(location.href));
$('#name').html($.url().param('name'));
cards_encoded = $.url().param('cards');
deck = [];
cards_id = [];
for (i = _i = 0, _ref = cards_encoded.length; _i < _ref; i = _i += 5) {
decoded = decode(cards_encoded.substr(i, 5));
side = decoded >> 29;
count = decoded >> 27 & 0x3;
id = decoded & 0x07FFFFFF;
cards_id.push(id);
deck.push << {
card_id: id,
count: count,
side: side
};
$('#cards').append($('<dt />', {
text: id
}));
$('#cards').append($('<dd />', {
text: count
}));
}
Card.query({
_id: {
$in: cards_id
}
});
}).call(this);
/*! normalize.css v1.0.1 | MIT License | git.io/normalize */
/* ==========================================================================
HTML5 display definitions
========================================================================== */
/*
* Corrects `block` display not defined in IE 6/7/8/9 and Firefox 3.
*/
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
nav,
section,
summary {
display: block;
}
/*
* Corrects `inline-block` display not defined in IE 6/7/8/9 and Firefox 3.
*/
audio,
canvas,
video {
display: inline-block;
*display: inline;
*zoom: 1;
}
/*
* Prevents modern browsers from displaying `audio` without controls.
* Remove excess height in iOS 5 devices.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/*
* Addresses styling for `hidden` attribute not present in IE 7/8/9, Firefox 3,
* and Safari 4.
* Known issue: no IE 6 support.
*/
[hidden] {
display: none;
}
/* ==========================================================================
Base
========================================================================== */
/*
* 1. Corrects text resizing oddly in IE 6/7 when body `font-size` is set using
* `em` units.
* 2. Prevents iOS text size adjust after orientation change, without disabling
* user zoom.
*/
html {
font-size: 100%; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
-ms-text-size-adjust: 100%; /* 2 */
}
/*
* Addresses `font-family` inconsistency between `textarea` and other form
* elements.
*/
html,
button,
input,
select,
textarea {
font-family: sans-serif;
}
/*
* Addresses margins handled incorrectly in IE 6/7.
*/
body {
margin: 0;
}
/* ==========================================================================
Links
========================================================================== */
/*
* Addresses `outline` inconsistency between Chrome and other browsers.
*/
a:focus {
outline: thin dotted;
}
/*
* Improves readability when focused and also mouse hovered in all browsers.
*/
a:active,
a:hover {
outline: 0;
}
/* ==========================================================================
Typography
========================================================================== */
/*
* Addresses font sizes and margins set differently in IE 6/7.
* Addresses font sizes within `section` and `article` in Firefox 4+, Safari 5,
* and Chrome.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
h2 {
font-size: 1.5em;
margin: 0.83em 0;
}
h3 {
font-size: 1.17em;
margin: 1em 0;
}
h4 {
font-size: 1em;
margin: 1.33em 0;
}
h5 {
font-size: 0.83em;
margin: 1.67em 0;
}
h6 {
font-size: 0.75em;
margin: 2.33em 0;
}
/*
* Addresses styling not present in IE 7/8/9, Safari 5, and Chrome.
*/
abbr[title] {
border-bottom: 1px dotted;
}
/*
* Addresses style set to `bolder` in Firefox 3+, Safari 4/5, and Chrome.
*/
b,
strong {
font-weight: bold;
}
blockquote {
margin: 1em 40px;
}
/*
* Addresses styling not present in Safari 5 and Chrome.
*/
dfn {
font-style: italic;
}
/*
* Addresses styling not present in IE 6/7/8/9.
*/
mark {
background: #ff0;
color: #000;
}
/*
* Addresses margins set differently in IE 6/7.
*/
p,
pre {
margin: 1em 0;
}
/*
* Corrects font family set oddly in IE 6, Safari 4/5, and Chrome.
*/
code,
kbd,
pre,
samp {
font-family: monospace, serif;
_font-family: 'courier new', monospace;
font-size: 1em;
}
/*
* Improves readability of pre-formatted text in all browsers.
*/
pre {
white-space: pre;
white-space: pre-wrap;
word-wrap: break-word;
}
/*
* Addresses CSS quotes not supported in IE 6/7.
*/
q {
quotes: none;
}
/*
* Addresses `quotes` property not supported in Safari 4.
*/
q:before,
q:after {
content: '';
content: none;
}
/*
* Addresses inconsistent and variable font size in all browsers.
*/
small {
font-size: 80%;
}
/*
* Prevents `sub` and `sup` affecting `line-height` in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
/* ==========================================================================
Lists
========================================================================== */
/*
* Addresses margins set differently in IE 6/7.
*/
dl,
menu,
ol,
ul {
margin: 1em 0;
}
dd {
margin: 0 0 0 40px;
}
/*
* Addresses paddings set differently in IE 6/7.
*/
menu,
ol,
ul {
padding: 0 0 0 40px;
}
/*
* Corrects list images handled incorrectly in IE 7.
*/
nav ul,
nav ol {
list-style: none;
list-style-image: none;
}
/* ==========================================================================
Embedded content
========================================================================== */
/*
* 1. Removes border when inside `a` element in IE 6/7/8/9 and Firefox 3.
* 2. Improves image quality when scaled in IE 7.
*/
img {
border: 0; /* 1 */
-ms-interpolation-mode: bicubic; /* 2 */
}
/*
* Corrects overflow displayed oddly in IE 9.
*/
svg:not(:root) {
overflow: hidden;
}
/* ==========================================================================
Figures
========================================================================== */
/*
* Addresses margin not present in IE 6/7/8/9, Safari 5, and Opera 11.
*/
figure {
margin: 0;
}
/* ==========================================================================
Forms
========================================================================== */
/*
* Corrects margin displayed oddly in IE 6/7.
*/
form {
margin: 0;
}
/*
* Define consistent border, margin, and padding.
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/*
* 1. Corrects color not being inherited in IE 6/7/8/9.
* 2. Corrects text not wrapping in Firefox 3.
* 3. Corrects alignment displayed oddly in IE 6/7.
*/
legend {
border: 0; /* 1 */
padding: 0;
white-space: normal; /* 2 */
*margin-left: -7px; /* 3 */
}
/*
* 1. Corrects font size not being inherited in all browsers.
* 2. Addresses margins set differently in IE 6/7, Firefox 3+, Safari 5,
* and Chrome.
* 3. Improves appearance and consistency in all browsers.
*/
button,
input,
select,
textarea {
font-size: 100%; /* 1 */
margin: 0; /* 2 */
vertical-align: baseline; /* 3 */
*vertical-align: middle; /* 3 */
}
/*
* Addresses Firefox 3+ setting `line-height` on `input` using `!important` in
* the UA stylesheet.
*/
button,
input {
line-height: normal;
}
/*
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
* and `video` controls.
* 2. Corrects inability to style clickable `input` types in iOS.
* 3. Improves usability and consistency of cursor style between image-type
* `input` and others.
* 4. Removes inner spacing in IE 7 without affecting normal text inputs.
* Known issue: inner spacing remains in IE 6.
*/
button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
*overflow: visible; /* 4 */
}
/*
* Re-set default cursor for disabled elements.
*/
button[disabled],
input[disabled] {
cursor: default;
}
/*
* 1. Addresses box sizing set to content-box in IE 8/9.
* 2. Removes excess padding in IE 8/9.
* 3. Removes excess padding in IE 7.
* Known issue: excess padding remains in IE 6.
*/
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
*height: 13px; /* 3 */
*width: 13px; /* 3 */
}
/*
* 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome.
* 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome
* (include `-moz` to future-proof).
*/
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; /* 2 */
box-sizing: content-box;
}
/*
* Removes inner padding and search cancel button in Safari 5 and Chrome
* on OS X.
*/
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/*
* Removes inner padding and border in Firefox 3+.
*/
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
/*
* 1. Removes default vertical scrollbar in IE 6/7/8/9.
* 2. Improves readability and alignment in all browsers.
*/
textarea {
overflow: auto; /* 1 */
vertical-align: top; /* 2 */
}
/* ==========================================================================
Tables
========================================================================== */
/*
* Remove most spacing between table cells.
*/
table {
border-collapse: collapse;
border-spacing: 0;
}
This diff is collapsed.
This diff is collapsed.
<!DOCTYPE html>
<html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
<meta charset="UTF-8">
<!--[if lt IE 9]><script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js" type="text/javascript"></script>
<script src="https://raw.github.com/allmarkedup/jQuery-URL-Parser/master/purl.js"></script>
<script type="text/javascript">
function decode(str){
var key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789*-="
var result = 0
for(var i in str){
result <<= 6
result += key.indexOf(str.charAt(i))
}
return result
}
$(document).ready(function(){
$('#name').html($.url().param('name'))
var cards_encoded = $.url().param('cards')
for(var i=0; i<cards_encoded.length; i+=5){
var decoded = decode(cards_encoded.substr(i, 5))
var side = decoded >> 29
var count = decoded >> 27 & 0x3
var id = decoded & 0x07FFFFFF
$('#cards').append($('<dt />', {text: id}))
$('#cards').append($('<dd />', {text: count}))
}
})
</script>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>mycard deck</title>
<meta name="description" content="mycard卡组编辑器">
<meta name="viewport" content="width=device-width">
<!-- Place favicon.ico and apple-touch-icon.png in the root directory -->
<link rel="stylesheet" href="/assets/stylesheets/normalize.css">
<script src="/vendor/javascripts/modernizr-2.6.2.min.js"></script>
</head>
<body>
<div id="name"></div>
<dl id="cards"></dl>
<!--[if lt IE 7]>
<p class="chromeframe">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">activate Google Chrome Frame</a> to improve your experience.</p>
<![endif]-->
<!-- Add your site or application content here -->
<img id="qrcode" src="http://google.com/">
<div id="name"></div>
<dl id="cards">
<div id="card_template">
</div>
</dl>
<script src="/vendor/javascripts/jquery-1.8.2.min.js"></script>
<script src="/vendor/javascripts/jQuery-URL-Parser.js"></script>
<script src="/vendor/javascripts/json2.js"></script>
<script src="/vendor/javascripts/spine/spine.js"></script>
<script src="/vendor/javascripts/spine/ajax.js"></script>
<script src="/assets/javascripts/decks.js"></script>
<!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
<!--<script>
var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
s.parentNode.insertBefore(g,s)}(document,'script'));
</script>-->
</body>
</html>
\ No newline at end of file
This diff is collapsed.
......@@ -31,6 +31,10 @@
count++
}else{
if(last_id){
var t = last_id | (side << 29) | (count << 27)
alert(t)
alert(encode(t))
alert('---')
result += encode(last_id | (side << 29) | (count << 27))
}
last_id = id
......
/*
* JQuery URL Parser plugin, v2.2.1
* Developed and maintanined by Mark Perkins, mark@allmarkedup.com
* Source repository: https://github.com/allmarkedup/jQuery-URL-Parser
* Licensed under an MIT-style license. See https://github.com/allmarkedup/jQuery-URL-Parser/blob/master/LICENSE for details.
*/
;(function(factory) {
if (typeof define === 'function' && define.amd) {
// AMD available; use anonymous module
if ( typeof jQuery !== 'undefined' ) {
define(['jquery'], factory);
} else {
define([], factory);
}
} else {
// No AMD available; mutate global vars
if ( typeof jQuery !== 'undefined' ) {
factory(jQuery);
} else {
factory();
}
}
})(function($, undefined) {
var tag2attr = {
a : 'href',
img : 'src',
form : 'action',
base : 'href',
script : 'src',
iframe : 'src',
link : 'href'
},
key = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'fragment'], // keys available to query
aliases = { 'anchor' : 'fragment' }, // aliases for backwards compatability
parser = {
strict : /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, //less intuitive, more accurate to the specs
loose : /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // more intuitive, fails on relative paths and deviates from specs
},
toString = Object.prototype.toString,
isint = /^[0-9]+$/;
function parseUri( url, strictMode ) {
var str = decodeURI( url ),
res = parser[ strictMode || false ? 'strict' : 'loose' ].exec( str ),
uri = { attr : {}, param : {}, seg : {} },
i = 14;
while ( i-- ) {
uri.attr[ key[i] ] = res[i] || '';
}
// build query and fragment parameters
uri.param['query'] = parseString(uri.attr['query']);
uri.param['fragment'] = parseString(uri.attr['fragment']);
// split path and fragement into segments
uri.seg['path'] = uri.attr.path.replace(/^\/+|\/+$/g,'').split('/');
uri.seg['fragment'] = uri.attr.fragment.replace(/^\/+|\/+$/g,'').split('/');
// compile a 'base' domain attribute
uri.attr['base'] = uri.attr.host ? (uri.attr.protocol ? uri.attr.protocol+'://'+uri.attr.host : uri.attr.host) + (uri.attr.port ? ':'+uri.attr.port : '') : '';
return uri;
};
function getAttrName( elm ) {
var tn = elm.tagName;
if ( typeof tn !== 'undefined' ) return tag2attr[tn.toLowerCase()];
return tn;
}
function promote(parent, key) {
if (parent[key].length == 0) return parent[key] = {};
var t = {};
for (var i in parent[key]) t[i] = parent[key][i];
parent[key] = t;
return t;
}
function parse(parts, parent, key, val) {
var part = parts.shift();
if (!part) {
if (isArray(parent[key])) {
parent[key].push(val);
} else if ('object' == typeof parent[key]) {
parent[key] = val;
} else if ('undefined' == typeof parent[key]) {
parent[key] = val;
} else {
parent[key] = [parent[key], val];
}
} else {
var obj = parent[key] = parent[key] || [];
if (']' == part) {
if (isArray(obj)) {
if ('' != val) obj.push(val);
} else if ('object' == typeof obj) {
obj[keys(obj).length] = val;
} else {
obj = parent[key] = [parent[key], val];
}
} else if (~part.indexOf(']')) {
part = part.substr(0, part.length - 1);
if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
parse(parts, obj, part, val);
// key
} else {
if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
parse(parts, obj, part, val);
}
}
}
function merge(parent, key, val) {
if (~key.indexOf(']')) {
var parts = key.split('['),
len = parts.length,
last = len - 1;
parse(parts, parent, 'base', val);
} else {
if (!isint.test(key) && isArray(parent.base)) {
var t = {};
for (var k in parent.base) t[k] = parent.base[k];
parent.base = t;
}
set(parent.base, key, val);
}
return parent;
}
function parseString(str) {
return reduce(String(str).split(/&|;/), function(ret, pair) {
try {
pair = decodeURIComponent(pair.replace(/\+/g, ' '));
} catch(e) {
// ignore
}
var eql = pair.indexOf('='),
brace = lastBraceInKey(pair),
key = pair.substr(0, brace || eql),
val = pair.substr(brace || eql, pair.length),
val = val.substr(val.indexOf('=') + 1, val.length);
if ('' == key) key = pair, val = '';
return merge(ret, key, val);
}, { base: {} }).base;
}
function set(obj, key, val) {
var v = obj[key];
if (undefined === v) {
obj[key] = val;
} else if (isArray(v)) {
v.push(val);
} else {
obj[key] = [v, val];
}
}
function lastBraceInKey(str) {
var len = str.length,
brace, c;
for (var i = 0; i < len; ++i) {
c = str[i];
if (']' == c) brace = false;
if ('[' == c) brace = true;
if ('=' == c && !brace) return i;
}
}
function reduce(obj, accumulator){
var i = 0,
l = obj.length >> 0,
curr = arguments[2];
while (i < l) {
if (i in obj) curr = accumulator.call(undefined, curr, obj[i], i, obj);
++i;
}
return curr;
}
function isArray(vArg) {
return Object.prototype.toString.call(vArg) === "[object Array]";
}
function keys(obj) {
var keys = [];
for ( prop in obj ) {
if ( obj.hasOwnProperty(prop) ) keys.push(prop);
}
return keys;
}
function purl( url, strictMode ) {
if ( arguments.length === 1 && url === true ) {
strictMode = true;
url = undefined;
}
strictMode = strictMode || false;
url = url || window.location.toString();
return {
data : parseUri(url, strictMode),
// get various attributes from the URI
attr : function( attr ) {
attr = aliases[attr] || attr;
return typeof attr !== 'undefined' ? this.data.attr[attr] : this.data.attr;
},
// return query string parameters
param : function( param ) {
return typeof param !== 'undefined' ? this.data.param.query[param] : this.data.param.query;
},
// return fragment parameters
fparam : function( param ) {
return typeof param !== 'undefined' ? this.data.param.fragment[param] : this.data.param.fragment;
},
// return path segments
segment : function( seg ) {
if ( typeof seg === 'undefined' ) {
return this.data.seg.path;
} else {
seg = seg < 0 ? this.data.seg.path.length + seg : seg - 1; // negative segments count from the end
return this.data.seg.path[seg];
}
},
// return fragment segments
fsegment : function( seg ) {
if ( typeof seg === 'undefined' ) {
return this.data.seg.fragment;
} else {
seg = seg < 0 ? this.data.seg.fragment.length + seg : seg - 1; // negative segments count from the end
return this.data.seg.fragment[seg];
}
}
};
};
if ( typeof $ !== 'undefined' ) {
$.fn.url = function( strictMode ) {
var url = '';
if ( this.length ) {
url = $(this).attr( getAttrName(this[0]) ) || '';
}
return purl( url, strictMode );
};
$.url = purl;
} else {
window.purl = purl;
}
});
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// Generated by CoffeeScript 1.3.3
(function() {
var $, Ajax, Base, Collection, Extend, Include, Model, Singleton, Spine,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__slice = [].slice;
Spine = this.Spine || require('spine');
$ = Spine.$;
Model = Spine.Model;
Ajax = {
getURL: function(object) {
return object && (typeof object.url === "function" ? object.url() : void 0) || object.url;
},
enabled: true,
pending: false,
requests: [],
disable: function(callback) {
if (this.enabled) {
this.enabled = false;
try {
return callback();
} catch (e) {
throw e;
} finally {
this.enabled = true;
}
} else {
return callback();
}
},
requestNext: function() {
var next;
next = this.requests.shift();
if (next) {
return this.request(next);
} else {
return this.pending = false;
}
},
request: function(callback) {
var _this = this;
return (callback()).complete(function() {
return _this.requestNext();
});
},
queue: function(callback) {
if (!this.enabled) {
return;
}
if (this.pending) {
this.requests.push(callback);
} else {
this.pending = true;
this.request(callback);
}
return callback;
}
};
Base = (function() {
function Base() {}
Base.prototype.defaults = {
contentType: 'application/json',
dataType: 'json',
processData: false,
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
};
Base.prototype.ajax = function(params, defaults) {
return $.ajax($.extend({}, this.defaults, defaults, params));
};
Base.prototype.queue = function(callback) {
return Ajax.queue(callback);
};
return Base;
})();
Collection = (function(_super) {
__extends(Collection, _super);
function Collection(model) {
this.model = model;
this.errorResponse = __bind(this.errorResponse, this);
this.recordsResponse = __bind(this.recordsResponse, this);
}
Collection.prototype.find = function(id, params) {
var record;
record = new this.model({
id: id
});
return this.ajax(params, {
type: 'GET',
url: Ajax.getURL(record)
}).success(this.recordsResponse).error(this.errorResponse);
};
Collection.prototype.all = function(params) {
return this.ajax(params, {
type: 'GET',
url: Ajax.getURL(this.model)
}).success(this.recordsResponse).error(this.errorResponse);
};
Collection.prototype.fetch = function(params, options) {
var id,
_this = this;
if (params == null) {
params = {};
}
if (options == null) {
options = {};
}
if (id = params.id) {
delete params.id;
return this.find(id, params).success(function(record) {
return _this.model.refresh(record, options);
});
} else {
return this.all(params).success(function(records) {
return _this.model.refresh(records, options);
});
}
};
Collection.prototype.recordsResponse = function(data, status, xhr) {
return this.model.trigger('ajaxSuccess', null, status, xhr);
};
Collection.prototype.errorResponse = function(xhr, statusText, error) {
return this.model.trigger('ajaxError', null, xhr, statusText, error);
};
return Collection;
})(Base);
Singleton = (function(_super) {
__extends(Singleton, _super);
function Singleton(record) {
this.record = record;
this.errorResponse = __bind(this.errorResponse, this);
this.recordResponse = __bind(this.recordResponse, this);
this.model = this.record.constructor;
}
Singleton.prototype.reload = function(params, options) {
var _this = this;
return this.queue(function() {
return _this.ajax(params, {
type: 'GET',
url: Ajax.getURL(_this.record)
}).success(_this.recordResponse(options)).error(_this.errorResponse(options));
});
};
Singleton.prototype.create = function(params, options) {
var _this = this;
return this.queue(function() {
return _this.ajax(params, {
type: 'POST',
data: JSON.stringify(_this.record),
url: Ajax.getURL(_this.model)
}).success(_this.recordResponse(options)).error(_this.errorResponse(options));
});
};
Singleton.prototype.update = function(params, options) {
var _this = this;
return this.queue(function() {
return _this.ajax(params, {
type: 'PUT',
data: JSON.stringify(_this.record),
url: Ajax.getURL(_this.record)
}).success(_this.recordResponse(options)).error(_this.errorResponse(options));
});
};
Singleton.prototype.destroy = function(params, options) {
var _this = this;
return this.queue(function() {
return _this.ajax(params, {
type: 'DELETE',
url: Ajax.getURL(_this.record)
}).success(_this.recordResponse(options)).error(_this.errorResponse(options));
});
};
Singleton.prototype.recordResponse = function(options) {
var _this = this;
if (options == null) {
options = {};
}
return function(data, status, xhr) {
var _ref;
if (Spine.isBlank(data)) {
data = false;
} else {
data = _this.model.fromJSON(data);
}
Ajax.disable(function() {
if (data) {
if (data.id && _this.record.id !== data.id) {
_this.record.changeID(data.id);
}
return _this.record.updateAttributes(data.attributes());
}
});
_this.record.trigger('ajaxSuccess', data, status, xhr);
return (_ref = options.success) != null ? _ref.apply(_this.record) : void 0;
};
};
Singleton.prototype.errorResponse = function(options) {
var _this = this;
if (options == null) {
options = {};
}
return function(xhr, statusText, error) {
var _ref;
_this.record.trigger('ajaxError', xhr, statusText, error);
return (_ref = options.error) != null ? _ref.apply(_this.record) : void 0;
};
};
return Singleton;
})(Base);
Model.host = '';
Include = {
ajax: function() {
return new Singleton(this);
},
url: function() {
var args, url;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
url = Ajax.getURL(this.constructor);
if (url.charAt(url.length - 1) !== '/') {
url += '/';
}
url += encodeURIComponent(this.id);
args.unshift(url);
return args.join('/');
}
};
Extend = {
ajax: function() {
return new Collection(this);
},
url: function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
args.unshift(this.className.toLowerCase() + 's');
args.unshift(Model.host);
return args.join('/');
}
};
Model.Ajax = {
extended: function() {
this.fetch(this.ajaxFetch);
this.change(this.ajaxChange);
this.extend(Extend);
return this.include(Include);
},
ajaxFetch: function() {
var _ref;
return (_ref = this.ajax()).fetch.apply(_ref, arguments);
},
ajaxChange: function(record, type, options) {
if (options == null) {
options = {};
}
if (options.ajax === false) {
return;
}
return record.ajax()[type](options.ajax, options);
}
};
Model.Ajax.Methods = {
extended: function() {
this.extend(Extend);
return this.include(Include);
}
};
Ajax.defaults = Base.prototype.defaults;
Spine.Ajax = Ajax;
if (typeof module !== "undefined" && module !== null) {
module.exports = Ajax;
}
}).call(this);
// Generated by CoffeeScript 1.3.3
(function() {
var $, Spine,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
Spine = this.Spine || require('spine');
$ = Spine.$;
Spine.List = (function(_super) {
__extends(List, _super);
List.prototype.events = {
'click .item': 'click'
};
List.prototype.selectFirst = false;
function List() {
this.change = __bind(this.change, this);
List.__super__.constructor.apply(this, arguments);
this.bind('change', this.change);
}
List.prototype.template = function() {
throw 'Override template';
};
List.prototype.change = function(item) {
this.current = item;
if (!this.current) {
this.children().removeClass('active');
return;
}
this.children().removeClass('active');
return $(this.children().get(this.items.indexOf(this.current))).addClass('active');
};
List.prototype.render = function(items) {
if (items) {
this.items = items;
}
this.html(this.template(this.items));
this.change(this.current);
if (this.selectFirst) {
if (!this.children('.active').length) {
return this.children(':first').click();
}
}
};
List.prototype.children = function(sel) {
return this.el.children(sel);
};
List.prototype.click = function(e) {
var item;
item = this.items[$(e.currentTarget).index()];
this.trigger('change', item);
return true;
};
return List;
})(Spine.Controller);
if (typeof module !== "undefined" && module !== null) {
module.exports = Spine.List;
}
}).call(this);
// Generated by CoffeeScript 1.3.3
(function() {
var Spine;
Spine = this.Spine || require('spine');
Spine.Model.Local = {
extended: function() {
this.change(this.saveLocal);
return this.fetch(this.loadLocal);
},
saveLocal: function() {
var result;
result = JSON.stringify(this);
return localStorage[this.className] = result;
},
loadLocal: function() {
var result;
result = localStorage[this.className];
return this.refresh(result || [], {
clear: true
});
}
};
if (typeof module !== "undefined" && module !== null) {
module.exports = Spine.Model.Local;
}
}).call(this);
// Generated by CoffeeScript 1.3.3
(function() {
var $, Spine,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__slice = [].slice;
Spine = this.Spine || require('spine');
$ = Spine.$;
Spine.Manager = (function(_super) {
__extends(Manager, _super);
Manager.include(Spine.Events);
function Manager() {
this.controllers = [];
this.bind('change', this.change);
this.add.apply(this, arguments);
}
Manager.prototype.add = function() {
var cont, controllers, _i, _len, _results;
controllers = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
_results = [];
for (_i = 0, _len = controllers.length; _i < _len; _i++) {
cont = controllers[_i];
_results.push(this.addOne(cont));
}
return _results;
};
Manager.prototype.addOne = function(controller) {
var _this = this;
controller.bind('active', function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return _this.trigger.apply(_this, ['change', controller].concat(__slice.call(args)));
});
controller.bind('release', function() {
return _this.controllers.splice(_this.controllers.indexOf(controller), 1);
});
return this.controllers.push(controller);
};
Manager.prototype.deactivate = function() {
return this.trigger.apply(this, ['change', false].concat(__slice.call(arguments)));
};
Manager.prototype.change = function() {
var args, cont, current, _i, _len, _ref, _results;
current = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
_ref = this.controllers;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
cont = _ref[_i];
if (cont === current) {
_results.push(cont.activate.apply(cont, args));
} else {
_results.push(cont.deactivate.apply(cont, args));
}
}
return _results;
};
return Manager;
})(Spine.Module);
Spine.Controller.include({
active: function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
if (typeof args[0] === 'function') {
this.bind('active', args[0]);
} else {
args.unshift('active');
this.trigger.apply(this, args);
}
return this;
},
isActive: function() {
return this.el.hasClass('active');
},
activate: function() {
this.el.addClass('active');
return this;
},
deactivate: function() {
this.el.removeClass('active');
return this;
}
});
Spine.Stack = (function(_super) {
__extends(Stack, _super);
Stack.prototype.controllers = {};
Stack.prototype.routes = {};
Stack.prototype.className = 'spine stack';
function Stack() {
var key, value, _fn, _ref, _ref1,
_this = this;
Stack.__super__.constructor.apply(this, arguments);
this.manager = new Spine.Manager;
_ref = this.controllers;
for (key in _ref) {
value = _ref[key];
this[key] = new value({
stack: this
});
this.add(this[key]);
}
_ref1 = this.routes;
_fn = function(key, value) {
var callback;
if (typeof value === 'function') {
callback = value;
}
callback || (callback = function() {
var _ref2;
return (_ref2 = _this[value]).active.apply(_ref2, arguments);
});
return _this.route(key, callback);
};
for (key in _ref1) {
value = _ref1[key];
_fn(key, value);
}
if (this["default"]) {
this[this["default"]].active();
}
}
Stack.prototype.add = function(controller) {
this.manager.add(controller);
return this.append(controller);
};
return Stack;
})(Spine.Controller);
if (typeof module !== "undefined" && module !== null) {
module.exports = Spine.Manager;
}
if (typeof module !== "undefined" && module !== null) {
module.exports.Stack = Spine.Stack;
}
}).call(this);
// Generated by CoffeeScript 1.3.3
(function() {
var Collection, Instance, Singleton, Spine, isArray, require, singularize, underscore,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
Spine = this.Spine || require('spine');
isArray = Spine.isArray;
require = this.require || (function(value) {
return eval(value);
});
Collection = (function(_super) {
__extends(Collection, _super);
function Collection(options) {
var key, value;
if (options == null) {
options = {};
}
for (key in options) {
value = options[key];
this[key] = value;
}
}
Collection.prototype.all = function() {
var _this = this;
return this.model.select(function(rec) {
return _this.associated(rec);
});
};
Collection.prototype.first = function() {
return this.all()[0];
};
Collection.prototype.last = function() {
var values;
values = this.all();
return values[values.length - 1];
};
Collection.prototype.find = function(id) {
var records,
_this = this;
records = this.select(function(rec) {
return rec.id + '' === id + '';
});
if (!records[0]) {
throw 'Unknown record';
}
return records[0];
};
Collection.prototype.findAllByAttribute = function(name, value) {
var _this = this;
return this.model.select(function(rec) {
return _this.associated(rec) && rec[name] === value;
});
};
Collection.prototype.findByAttribute = function(name, value) {
return this.findAllByAttribute(name, value)[0];
};
Collection.prototype.select = function(cb) {
var _this = this;
return this.model.select(function(rec) {
return _this.associated(rec) && cb(rec);
});
};
Collection.prototype.refresh = function(values) {
var record, records, _i, _j, _len, _len1, _ref;
_ref = this.all();
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
record = _ref[_i];
delete this.model.records[record.id];
}
records = this.model.fromJSON(values);
if (!isArray(records)) {
records = [records];
}
for (_j = 0, _len1 = records.length; _j < _len1; _j++) {
record = records[_j];
record.newRecord = false;
record[this.fkey] = this.record.id;
this.model.records[record.id] = record;
}
return this.model.trigger('refresh', this.model.cloneArray(records));
};
Collection.prototype.create = function(record) {
record[this.fkey] = this.record.id;
return this.model.create(record);
};
Collection.prototype.associated = function(record) {
return record[this.fkey] === this.record.id;
};
return Collection;
})(Spine.Module);
Instance = (function(_super) {
__extends(Instance, _super);
function Instance(options) {
var key, value;
if (options == null) {
options = {};
}
for (key in options) {
value = options[key];
this[key] = value;
}
}
Instance.prototype.exists = function() {
return this.record[this.fkey] && this.model.exists(this.record[this.fkey]);
};
Instance.prototype.update = function(value) {
if (!(value instanceof this.model)) {
value = new this.model(value);
}
if (value.isNew()) {
value.save();
}
return this.record[this.fkey] = value && value.id;
};
return Instance;
})(Spine.Module);
Singleton = (function(_super) {
__extends(Singleton, _super);
function Singleton(options) {
var key, value;
if (options == null) {
options = {};
}
for (key in options) {
value = options[key];
this[key] = value;
}
}
Singleton.prototype.find = function() {
return this.record.id && this.model.findByAttribute(this.fkey, this.record.id);
};
Singleton.prototype.update = function(value) {
if (!(value instanceof this.model)) {
value = this.model.fromJSON(value);
}
value[this.fkey] = this.record.id;
return value.save();
};
return Singleton;
})(Spine.Module);
singularize = function(str) {
return str.replace(/s$/, '');
};
underscore = function(str) {
return str.replace(/::/g, '/').replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2').replace(/([a-z\d])([A-Z])/g, '$1_$2').replace(/-/g, '_').toLowerCase();
};
Spine.Model.extend({
hasMany: function(name, model, fkey) {
var association;
if (fkey == null) {
fkey = "" + (underscore(this.className)) + "_id";
}
association = function(record) {
if (typeof model === 'string') {
model = require(model);
}
return new Collection({
name: name,
model: model,
record: record,
fkey: fkey
});
};
return this.prototype[name] = function(value) {
if (value != null) {
association(this).refresh(value);
}
return association(this);
};
},
belongsTo: function(name, model, fkey) {
var association;
if (fkey == null) {
fkey = "" + (singularize(name)) + "_id";
}
association = function(record) {
if (typeof model === 'string') {
model = require(model);
}
return new Instance({
name: name,
model: model,
record: record,
fkey: fkey
});
};
this.prototype[name] = function(value) {
if (value != null) {
association(this).update(value);
}
return association(this).exists();
};
return this.attributes.push(fkey);
},
hasOne: function(name, model, fkey) {
var association;
if (fkey == null) {
fkey = "" + (underscore(this.className)) + "_id";
}
association = function(record) {
if (typeof model === 'string') {
model = require(model);
}
return new Singleton({
name: name,
model: model,
record: record,
fkey: fkey
});
};
return this.prototype[name] = function(value) {
if (value != null) {
association(this).update(value);
}
return association(this).find();
};
}
});
}).call(this);
// Generated by CoffeeScript 1.3.3
(function() {
var $, Spine, escapeRegExp, hashStrip, namedParam, splatParam,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__slice = [].slice;
Spine = this.Spine || require('spine');
$ = Spine.$;
hashStrip = /^#*/;
namedParam = /:([\w\d]+)/g;
splatParam = /\*([\w\d]+)/g;
escapeRegExp = /[-[\]{}()+?.,\\^$|#\s]/g;
Spine.Route = (function(_super) {
var _ref;
__extends(Route, _super);
Route.extend(Spine.Events);
Route.historySupport = ((_ref = window.history) != null ? _ref.pushState : void 0) != null;
Route.routes = [];
Route.options = {
trigger: true,
history: false,
shim: false
};
Route.add = function(path, callback) {
var key, value, _results;
if (typeof path === 'object' && !(path instanceof RegExp)) {
_results = [];
for (key in path) {
value = path[key];
_results.push(this.add(key, value));
}
return _results;
} else {
return this.routes.push(new this(path, callback));
}
};
Route.setup = function(options) {
if (options == null) {
options = {};
}
this.options = $.extend({}, this.options, options);
if (this.options.history) {
this.history = this.historySupport && this.options.history;
}
if (this.options.shim) {
return;
}
if (this.history) {
$(window).bind('popstate', this.change);
} else {
$(window).bind('hashchange', this.change);
}
return this.change();
};
Route.unbind = function() {
if (this.history) {
return $(window).unbind('popstate', this.change);
} else {
return $(window).unbind('hashchange', this.change);
}
};
Route.navigate = function() {
var args, lastArg, options, path;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
options = {};
lastArg = args[args.length - 1];
if (typeof lastArg === 'object') {
options = args.pop();
} else if (typeof lastArg === 'boolean') {
options.trigger = args.pop();
}
options = $.extend({}, this.options, options);
path = args.join('/');
if (this.path === path) {
return;
}
this.path = path;
this.trigger('navigate', this.path);
if (options.trigger) {
this.matchRoute(this.path, options);
}
if (options.shim) {
return;
}
if (this.history) {
return history.pushState({}, document.title, this.path);
} else {
return window.location.hash = this.path;
}
};
Route.getPath = function() {
var path;
path = window.location.pathname;
if (path.substr(0, 1) !== '/') {
path = '/' + path;
}
return path;
};
Route.getHash = function() {
return window.location.hash;
};
Route.getFragment = function() {
return this.getHash().replace(hashStrip, '');
};
Route.getHost = function() {
return (document.location + '').replace(this.getPath() + this.getHash(), '');
};
Route.change = function() {
var path;
path = this.getFragment() !== '' ? this.getFragment() : this.getPath();
if (path === this.path) {
return;
}
this.path = path;
return this.matchRoute(this.path);
};
Route.matchRoute = function(path, options) {
var route, _i, _len, _ref1;
_ref1 = this.routes;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
route = _ref1[_i];
if (route.match(path, options)) {
this.trigger('change', route, path);
return route;
}
}
};
function Route(path, callback) {
var match;
this.path = path;
this.callback = callback;
this.names = [];
if (typeof path === 'string') {
namedParam.lastIndex = 0;
while ((match = namedParam.exec(path)) !== null) {
this.names.push(match[1]);
}
splatParam.lastIndex = 0;
while ((match = splatParam.exec(path)) !== null) {
this.names.push(match[1]);
}
path = path.replace(escapeRegExp, '\\$&').replace(namedParam, '([^\/]*)').replace(splatParam, '(.*?)');
this.route = new RegExp('^' + path + '$');
} else {
this.route = path;
}
}
Route.prototype.match = function(path, options) {
var i, match, param, params, _i, _len;
if (options == null) {
options = {};
}
match = this.route.exec(path);
if (!match) {
return false;
}
options.match = match;
params = match.slice(1);
if (this.names.length) {
for (i = _i = 0, _len = params.length; _i < _len; i = ++_i) {
param = params[i];
options[this.names[i]] = param;
}
}
return this.callback.call(null, options) !== false;
};
return Route;
})(Spine.Module);
Spine.Route.change = Spine.Route.proxy(Spine.Route.change);
Spine.Controller.include({
route: function(path, callback) {
return Spine.Route.add(path, this.proxy(callback));
},
routes: function(routes) {
var key, value, _results;
_results = [];
for (key in routes) {
value = routes[key];
_results.push(this.route(key, value));
}
return _results;
},
navigate: function() {
return Spine.Route.navigate.apply(Spine.Route, arguments);
}
});
if (typeof module !== "undefined" && module !== null) {
module.exports = Spine.Route;
}
}).call(this);
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment