From 11dd1125350cd5912c1032ff442cd58938739e9e Mon Sep 17 00:00:00 2001 From: Nietzsche Date: Thu, 26 Jul 2012 20:46:07 +1000 Subject: [PATCH 001/531] Added html testing, travis should fail --- .gitignore | 1 + package.json | 3 ++- test/sample.js | 21 ++++++++++++++------- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 8e3c8f7..c47dcff 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ +node_modules/ build/output diff --git a/package.json b/package.json index b03e47b..5eb3adc 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "test": "make test" } , "devDependencies": { - "mocha": "1.3.0" + "mocha": "1.3.0", + "wc3js": "0.1.4" } } \ No newline at end of file diff --git a/test/sample.js b/test/sample.js index bab25b6..f22d403 100644 --- a/test/sample.js +++ b/test/sample.js @@ -1,9 +1,16 @@ -var assert = require("assert") -describe('Array', function(){ - describe('#indexOf()', function(){ - it('should return -1 when the value is not present', function(){ - assert.equal(-1, [1,2,3].indexOf(5)); - assert.equal(-1, [1,2,3].indexOf(0)); - }) +var assert = require('assert'); +var wc3js = require('wc3js'); +describe('html validation', function(){ + it('index page should have no html errors', function(done){ + wc3js.validate({ + file: 'index.html', + callback: function (res) { + console.log(res); + if (res.messages.length > 0 ) { + throw {error: 'html errors have been found', results: res}; + }; + done(); + } + }) }) }) From 7aaaced5c84676e33873823facfcc94665758e1b Mon Sep 17 00:00:00 2001 From: Nietzsche Date: Thu, 26 Jul 2012 20:48:29 +1000 Subject: [PATCH 002/531] fixed index.html to pass build{ --- index.html | 2 -- 1 file changed, 2 deletions(-) diff --git a/index.html b/index.html index a96a30e..1187370 100644 --- a/index.html +++ b/index.html @@ -2,8 +2,6 @@ - - ApiDocco From dd013957ec024724f9ed2e5791f58abc0f4f3c43 Mon Sep 17 00:00:00 2001 From: Nietzsche Date: Thu, 26 Jul 2012 21:36:19 +1000 Subject: [PATCH 003/531] wc3 is crazy talk --- package.json | 2 +- test/sample.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 5eb3adc..0c2ecb4 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,6 @@ } , "devDependencies": { "mocha": "1.3.0", - "wc3js": "0.1.4" + "w3cjs": "0.1.4" } } \ No newline at end of file diff --git a/test/sample.js b/test/sample.js index f22d403..c79968c 100644 --- a/test/sample.js +++ b/test/sample.js @@ -1,8 +1,8 @@ var assert = require('assert'); -var wc3js = require('wc3js'); +var w3cjs = require('w3cjs'); describe('html validation', function(){ it('index page should have no html errors', function(done){ - wc3js.validate({ + w3cjs.validate({ file: 'index.html', callback: function (res) { console.log(res); From 9cae08cb4fa831d1ca625da6f542d6f322af3656 Mon Sep 17 00:00:00 2001 From: Nietzsche Date: Thu, 26 Jul 2012 21:41:37 +1000 Subject: [PATCH 004/531] updated version of w3cjs --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0c2ecb4..8b92641 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,6 @@ } , "devDependencies": { "mocha": "1.3.0", - "w3cjs": "0.1.4" + "w3cjs": "0.1.5" } } \ No newline at end of file From 41a5c5b0d46b97f22b2b02093cc83583dd26ed0d Mon Sep 17 00:00:00 2001 From: Nietzsche Date: Thu, 26 Jul 2012 21:45:36 +1000 Subject: [PATCH 005/531] fixed w3cjs --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8b92641..d2ccee8 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,6 @@ } , "devDependencies": { "mocha": "1.3.0", - "w3cjs": "0.1.5" + "w3cjs": "0.1.6" } } \ No newline at end of file From 3982a798a1bc61014a28dd5f1bc2c42276797362 Mon Sep 17 00:00:00 2001 From: Nietzsche Date: Fri, 27 Jul 2012 21:26:53 +1000 Subject: [PATCH 006/531] removed build directory from apiengine --- build/a.css | 4580 -------------- build/almond.js | 314 - build/build.js | 10 - build/build.sh | 13 - build/r.js | 15563 ---------------------------------------------- build/server | 15 - 6 files changed, 20495 deletions(-) delete mode 100644 build/a.css delete mode 100644 build/almond.js delete mode 100644 build/build.js delete mode 100755 build/build.sh delete mode 100644 build/r.js delete mode 100644 build/server diff --git a/build/a.css b/build/a.css deleted file mode 100644 index 9c8faeb..0000000 --- a/build/a.css +++ /dev/null @@ -1,4580 +0,0 @@ - -/*! - * Bootstrap v2.0.4 - * - * Copyright 2012 Twitter, Inc - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world @twitter by @mdo and @fat. - */ -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -nav, -section { - display: block; -} -audio, -canvas, -video { - display: inline-block; - *display: inline; - *zoom: 1; -} -audio:not([controls]) { - display: none; -} -html { - font-size: 100%; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} -a:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -a:hover, -a:active { - outline: 0; -} -sub, -sup { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; -} -sup { - top: -0.5em; -} -sub { - bottom: -0.25em; -} -img { - max-width: 100%; - vertical-align: middle; - border: 0; - -ms-interpolation-mode: bicubic; -} -#map_canvas img { - max-width: none; -} -button, -input, -select, -textarea { - margin: 0; - font-size: 100%; - vertical-align: middle; -} -button, -input { - *overflow: visible; - line-height: normal; -} -button::-moz-focus-inner, -input::-moz-focus-inner { - padding: 0; - border: 0; -} -button, -input[type="button"], -input[type="reset"], -input[type="submit"] { - cursor: pointer; - -webkit-appearance: button; -} -input[type="search"] { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; - -webkit-appearance: textfield; -} -input[type="search"]::-webkit-search-decoration, -input[type="search"]::-webkit-search-cancel-button { - -webkit-appearance: none; -} -textarea { - overflow: auto; - vertical-align: top; -} -.clearfix { - *zoom: 1; -} -.clearfix:before, -.clearfix:after { - display: table; - content: ""; -} -.clearfix:after { - clear: both; -} -.hide-text { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} -.input-block-level { - display: block; - width: 100%; - min-height: 28px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; -} -body { - margin: 0; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 13px; - line-height: 18px; - color: #333333; - background-color: #ffffff; -} -a { - color: #0088cc; - text-decoration: none; -} -a:hover { - color: #005580; - text-decoration: underline; -} -.row { - margin-left: -20px; - *zoom: 1; -} -.row:before, -.row:after { - display: table; - content: ""; -} -.row:after { - clear: both; -} -[class*="span"] { - float: left; - margin-left: 20px; -} -.container, -.navbar-fixed-top .container, -.navbar-fixed-bottom .container { -} -.span12 { - width: 940px; -} -.span11 { - width: 860px; -} -.span10 { - width: 780px; -} -.span9 { - width: 700px; -} -.span8 { - width: 620px; -} -.span7 { - width: 540px; -} -.span6 { - width: 460px; -} -.span5 { - width: 380px; -} -.span4 { - width: 300px; -} -.span3 { - width: 220px; -} -.span2 { - width: 140px; -} -.span1 { - width: 60px; -} -.offset12 { - margin-left: 980px; -} -.offset11 { - margin-left: 900px; -} -.offset10 { - margin-left: 820px; -} -.offset9 { - margin-left: 740px; -} -.offset8 { - margin-left: 660px; -} -.offset7 { - margin-left: 580px; -} -.offset6 { - margin-left: 500px; -} -.offset5 { - margin-left: 420px; -} -.offset4 { - margin-left: 340px; -} -.offset3 { - margin-left: 260px; -} -.offset2 { - margin-left: 180px; -} -.offset1 { - margin-left: 100px; -} -.row-fluid { - width: 100%; - *zoom: 1; -} -.row-fluid:before, -.row-fluid:after { - display: table; - content: ""; -} -.row-fluid:after { - clear: both; -} -.row-fluid [class*="span"] { - display: block; - float: left; - width: 100%; - min-height: 28px; - margin-left: 2.127659574%; - *margin-left: 2.0744680846382977%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; -} -.row-fluid [class*="span"]:first-child { - margin-left: 0; -} -.row-fluid .span12 { - width: 99.99999998999999%; - *width: 99.94680850063828%; -} -.row-fluid .span11 { - width: 91.489361693%; - *width: 91.4361702036383%; -} -.row-fluid .span10 { - width: 82.97872339599999%; - *width: 82.92553190663828%; -} -.row-fluid .span9 { - width: 74.468085099%; - *width: 74.4148936096383%; -} -.row-fluid .span8 { - width: 65.95744680199999%; - *width: 65.90425531263828%; -} -.row-fluid .span7 { - width: 57.446808505%; - *width: 57.3936170156383%; -} -.row-fluid .span6 { - width: 48.93617020799999%; - *width: 48.88297871863829%; -} -.row-fluid .span5 { - width: 40.425531911%; - *width: 40.3723404216383%; -} -.row-fluid .span4 { - width: 31.914893614%; - *width: 31.8617021246383%; -} -.row-fluid .span3 { - width: 23.404255317%; - *width: 23.3510638276383%; -} -.row-fluid .span2 { - width: 14.89361702%; - *width: 14.8404255306383%; -} -.row-fluid .span1 { - width: 6.382978723%; - *width: 6.329787233638298%; -} -.container { - margin-right: auto; - margin-left: auto; - *zoom: 1; -} -.container:before, -.container:after { - display: table; - content: ""; -} -.container:after { - clear: both; -} -.container-fluid { - padding-right: 20px; - padding-left: 20px; - *zoom: 1; -} -.container-fluid:before, -.container-fluid:after { - display: table; - content: ""; -} -.container-fluid:after { - clear: both; -} -p { - margin: 0 0 9px; -} -p small { - font-size: 11px; - color: #999999; -} -.lead { - margin-bottom: 18px; - font-size: 20px; - font-weight: 200; - line-height: 27px; -} -h1, -h2, -h3, -h4, -h5, -h6 { - margin: 0; - font-family: inherit; - font-weight: bold; - color: inherit; - text-rendering: optimizelegibility; -} -h1 small, -h2 small, -h3 small, -h4 small, -h5 small, -h6 small { - font-weight: normal; - color: #999999; -} -h1 { - font-size: 30px; - line-height: 36px; -} -h1 small { - font-size: 18px; -} -h2 { - font-size: 24px; - line-height: 36px; -} -h2 small { - font-size: 18px; -} -h3 { - font-size: 18px; - line-height: 27px; -} -h3 small { - font-size: 14px; -} -h4, -h5, -h6 { - line-height: 18px; -} -h4 { - font-size: 14px; -} -h4 small { - font-size: 12px; -} -h5 { - font-size: 12px; -} -h6 { - font-size: 11px; - color: #999999; - text-transform: uppercase; -} -.page-header { - padding-bottom: 17px; - margin: 18px 0; - border-bottom: 1px solid #eeeeee; -} -.page-header h1 { - line-height: 1; -} -ul, -ol { - padding: 0; - margin: 0 0 9px 25px; -} -ul ul, -ul ol, -ol ol, -ol ul { - margin-bottom: 0; -} -ul { - list-style: disc; -} -ol { - list-style: decimal; -} -li { - line-height: 18px; -} -ul.unstyled, -ol.unstyled { - margin-left: 0; - list-style: none; -} -dl { - margin-bottom: 18px; -} -dt, -dd { - line-height: 18px; -} -dt { - font-weight: bold; - line-height: 17px; -} -dd { - margin-left: 9px; -} -.dl-horizontal dt { - float: left; - width: 120px; - overflow: hidden; - clear: left; - text-align: right; - text-overflow: ellipsis; - white-space: nowrap; -} -.dl-horizontal dd { - margin-left: 130px; -} -hr { - margin: 18px 0; - border: 0; - border-top: 1px solid #eeeeee; - border-bottom: 1px solid #ffffff; -} -strong { - font-weight: bold; -} -em { - font-style: italic; -} -.muted { - color: #999999; -} -abbr[title] { - cursor: help; - border-bottom: 1px dotted #999999; -} -abbr.initialism { - font-size: 90%; - text-transform: uppercase; -} -blockquote { - padding: 0 0 0 15px; - margin: 0 0 18px; - border-left: 5px solid #eeeeee; -} -blockquote p { - margin-bottom: 0; - font-size: 16px; - font-weight: 300; - line-height: 22.5px; -} -blockquote small { - display: block; - line-height: 18px; - color: #999999; -} -blockquote small:before { - content: '\2014 \00A0'; -} -blockquote.pull-right { - float: right; - padding-right: 15px; - padding-left: 0; - border-right: 5px solid #eeeeee; - border-left: 0; -} -blockquote.pull-right p, -blockquote.pull-right small { - text-align: right; -} -q:before, -q:after, -blockquote:before, -blockquote:after { - content: ""; -} -address { - display: block; - margin-bottom: 18px; - font-style: normal; - line-height: 18px; -} -small { - font-size: 100%; -} -cite { - font-style: normal; -} -code, -pre { - padding: 0 3px 2px; - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; - font-size: 12px; - color: #333333; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} -code { - padding: 2px 4px; - color: #d14; - background-color: #f7f7f9; - border: 1px solid #e1e1e8; -} -pre { - display: block; - padding: 8.5px; - margin: 0 0 9px; - font-size: 12.025px; - line-height: 18px; - word-break: break-all; - word-wrap: break-word; - white-space: pre; - white-space: pre-wrap; - background-color: #f5f5f5; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.15); - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -pre.prettyprint { - margin-bottom: 18px; -} -pre code { - padding: 0; - color: inherit; - background-color: transparent; - border: 0; -} -.pre-scrollable { - max-height: 340px; - overflow-y: scroll; -} -form { - margin: 0 0 18px; -} -fieldset { - padding: 0; - margin: 0; - border: 0; -} -legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: 27px; - font-size: 19.5px; - line-height: 36px; - color: #333333; - border: 0; - border-bottom: 1px solid #e5e5e5; -} -legend small { - font-size: 13.5px; - color: #999999; -} -label, -input, -button, -select, -textarea { - font-size: 13px; - font-weight: normal; - line-height: 18px; -} -input, -button, -select, -textarea { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; -} -label { - display: block; - margin-bottom: 5px; -} -select, -textarea, -input[type="text"], -input[type="password"], -input[type="datetime"], -input[type="datetime-local"], -input[type="date"], -input[type="month"], -input[type="time"], -input[type="week"], -input[type="number"], -input[type="email"], -input[type="url"], -input[type="search"], -input[type="tel"], -input[type="color"], -.uneditable-input { - display: inline-block; - height: 18px; - padding: 4px; - margin-bottom: 9px; - font-size: 13px; - line-height: 18px; - color: #555555; -} -input, -textarea { - width: 210px; -} -textarea { - height: auto; -} -textarea, -input[type="text"], -input[type="password"], -input[type="datetime"], -input[type="datetime-local"], -input[type="date"], -input[type="month"], -input[type="time"], -input[type="week"], -input[type="number"], -input[type="email"], -input[type="url"], -input[type="search"], -input[type="tel"], -input[type="color"], -.uneditable-input { - background-color: #ffffff; - border: 1px solid #cccccc; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; - -moz-transition: border linear 0.2s, box-shadow linear 0.2s; - -ms-transition: border linear 0.2s, box-shadow linear 0.2s; - -o-transition: border linear 0.2s, box-shadow linear 0.2s; - transition: border linear 0.2s, box-shadow linear 0.2s; -} -textarea:focus, -input[type="text"]:focus, -input[type="password"]:focus, -input[type="datetime"]:focus, -input[type="datetime-local"]:focus, -input[type="date"]:focus, -input[type="month"]:focus, -input[type="time"]:focus, -input[type="week"]:focus, -input[type="number"]:focus, -input[type="email"]:focus, -input[type="url"]:focus, -input[type="search"]:focus, -input[type="tel"]:focus, -input[type="color"]:focus, -.uneditable-input:focus { - border-color: rgba(82, 168, 236, 0.8); - outline: 0; - outline: thin dotted \9; - - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); -} -input[type="radio"], -input[type="checkbox"] { - margin: 3px 0; - *margin-top: 0; - - line-height: normal; - cursor: pointer; -} -input[type="submit"], -input[type="reset"], -input[type="button"], -input[type="radio"], -input[type="checkbox"] { - width: auto; -} -.uneditable-textarea { - width: auto; - height: auto; -} -select, -input[type="file"] { - height: 28px; - - *margin-top: 4px; - - line-height: 28px; -} -select { - width: 220px; - border: 1px solid #bbb; -} -select[multiple], -select[size] { - height: auto; -} -select:focus, -input[type="file"]:focus, -input[type="radio"]:focus, -input[type="checkbox"]:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -.radio, -.checkbox { - min-height: 18px; - padding-left: 18px; -} -.radio input[type="radio"], -.checkbox input[type="checkbox"] { - float: left; - margin-left: -18px; -} -.controls > .radio:first-child, -.controls > .checkbox:first-child { - padding-top: 5px; -} -.radio.inline, -.checkbox.inline { - display: inline-block; - padding-top: 5px; - margin-bottom: 0; - vertical-align: middle; -} -.radio.inline + .radio.inline, -.checkbox.inline + .checkbox.inline { - margin-left: 10px; -} -.input-mini { - width: 60px; -} -.input-small { - width: 90px; -} -.input-medium { - width: 150px; -} -.input-large { - width: 210px; -} -.input-xlarge { - width: 270px; -} -.input-xxlarge { - width: 530px; -} -input[class*="span"], -select[class*="span"], -textarea[class*="span"], -.uneditable-input[class*="span"], -.row-fluid input[class*="span"], -.row-fluid select[class*="span"], -.row-fluid textarea[class*="span"], -.row-fluid .uneditable-input[class*="span"] { - float: none; - margin-left: 0; -} -.input-append input[class*="span"], -.input-append .uneditable-input[class*="span"], -.input-prepend input[class*="span"], -.input-prepend .uneditable-input[class*="span"], -.row-fluid .input-prepend [class*="span"], -.row-fluid .input-append [class*="span"] { - display: inline-block; -} -input, -textarea, -.uneditable-input { - margin-left: 0; -} -input.span12, -textarea.span12, -.uneditable-input.span12 { - width: 930px; -} -input.span11, -textarea.span11, -.uneditable-input.span11 { - width: 850px; -} -input.span10, -textarea.span10, -.uneditable-input.span10 { - width: 770px; -} -input.span9, -textarea.span9, -.uneditable-input.span9 { - width: 690px; -} -input.span8, -textarea.span8, -.uneditable-input.span8 { - width: 610px; -} -input.span7, -textarea.span7, -.uneditable-input.span7 { - width: 530px; -} -input.span6, -textarea.span6, -.uneditable-input.span6 { - width: 450px; -} -input.span5, -textarea.span5, -.uneditable-input.span5 { - width: 370px; -} -input.span4, -textarea.span4, -.uneditable-input.span4 { - width: 290px; -} -input.span3, -textarea.span3, -.uneditable-input.span3 { - width: 210px; -} -input.span2, -textarea.span2, -.uneditable-input.span2 { - width: 130px; -} -input.span1, -textarea.span1, -.uneditable-input.span1 { - width: 50px; -} -input[disabled], -select[disabled], -textarea[disabled], -input[readonly], -select[readonly], -textarea[readonly] { - cursor: not-allowed; - background-color: #eeeeee; - border-color: #ddd; -} -input[type="radio"][disabled], -input[type="checkbox"][disabled], -input[type="radio"][readonly], -input[type="checkbox"][readonly] { - background-color: transparent; -} -.control-group.warning > label, -.control-group.warning .help-block, -.control-group.warning .help-inline { - color: #c09853; -} -.control-group.warning .checkbox, -.control-group.warning .radio, -.control-group.warning input, -.control-group.warning select, -.control-group.warning textarea { - color: #c09853; - border-color: #c09853; -} -.control-group.warning .checkbox:focus, -.control-group.warning .radio:focus, -.control-group.warning input:focus, -.control-group.warning select:focus, -.control-group.warning textarea:focus { - border-color: #a47e3c; - -webkit-box-shadow: 0 0 6px #dbc59e; - -moz-box-shadow: 0 0 6px #dbc59e; - box-shadow: 0 0 6px #dbc59e; -} -.control-group.warning .input-prepend .add-on, -.control-group.warning .input-append .add-on { - color: #c09853; - background-color: #fcf8e3; - border-color: #c09853; -} -.control-group.error > label, -.control-group.error .help-block, -.control-group.error .help-inline { - color: #b94a48; -} -.control-group.error .checkbox, -.control-group.error .radio, -.control-group.error input, -.control-group.error select, -.control-group.error textarea { - color: #b94a48; - border-color: #b94a48; -} -.control-group.error .checkbox:focus, -.control-group.error .radio:focus, -.control-group.error input:focus, -.control-group.error select:focus, -.control-group.error textarea:focus { - border-color: #953b39; - -webkit-box-shadow: 0 0 6px #d59392; - -moz-box-shadow: 0 0 6px #d59392; - box-shadow: 0 0 6px #d59392; -} -.control-group.error .input-prepend .add-on, -.control-group.error .input-append .add-on { - color: #b94a48; - background-color: #f2dede; - border-color: #b94a48; -} -.control-group.success > label, -.control-group.success .help-block, -.control-group.success .help-inline { - color: #468847; -} -.control-group.success .checkbox, -.control-group.success .radio, -.control-group.success input, -.control-group.success select, -.control-group.success textarea { - color: #468847; - border-color: #468847; -} -.control-group.success .checkbox:focus, -.control-group.success .radio:focus, -.control-group.success input:focus, -.control-group.success select:focus, -.control-group.success textarea:focus { - border-color: #356635; - -webkit-box-shadow: 0 0 6px #7aba7b; - -moz-box-shadow: 0 0 6px #7aba7b; - box-shadow: 0 0 6px #7aba7b; -} -.control-group.success .input-prepend .add-on, -.control-group.success .input-append .add-on { - color: #468847; - background-color: #dff0d8; - border-color: #468847; -} -input:focus:required:invalid, -textarea:focus:required:invalid, -select:focus:required:invalid { - color: #b94a48; - border-color: #ee5f5b; -} -input:focus:required:invalid:focus, -textarea:focus:required:invalid:focus, -select:focus:required:invalid:focus { - border-color: #e9322d; - -webkit-box-shadow: 0 0 6px #f8b9b7; - -moz-box-shadow: 0 0 6px #f8b9b7; - box-shadow: 0 0 6px #f8b9b7; -} -.form-actions { - padding: 17px 20px 18px; - margin-top: 18px; - margin-bottom: 18px; - background-color: #f5f5f5; - border-top: 1px solid #e5e5e5; - *zoom: 1; -} -.form-actions:before, -.form-actions:after { - display: table; - content: ""; -} -.form-actions:after { - clear: both; -} -.uneditable-input { - overflow: hidden; - white-space: nowrap; - cursor: not-allowed; - background-color: #ffffff; - border-color: #eee; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); -} -:-moz-placeholder { - color: #999999; -} -:-ms-input-placeholder { - color: #999999; -} -::-webkit-input-placeholder { - color: #999999; -} -.help-block, -.help-inline { - color: #555555; -} -.help-block { - display: block; - margin-bottom: 9px; -} -.help-inline { - display: inline-block; - *display: inline; - padding-left: 5px; - vertical-align: middle; - *zoom: 1; -} -.input-prepend, -.input-append { - margin-bottom: 5px; -} -.input-prepend input, -.input-append input, -.input-prepend select, -.input-append select, -.input-prepend .uneditable-input, -.input-append .uneditable-input { - position: relative; - margin-bottom: 0; - *margin-left: 0; - vertical-align: middle; - -webkit-border-radius: 0 3px 3px 0; - -moz-border-radius: 0 3px 3px 0; - border-radius: 0 3px 3px 0; -} -.input-prepend input:focus, -.input-append input:focus, -.input-prepend select:focus, -.input-append select:focus, -.input-prepend .uneditable-input:focus, -.input-append .uneditable-input:focus { - z-index: 2; -} -.input-prepend .uneditable-input, -.input-append .uneditable-input { - border-left-color: #ccc; -} -.input-prepend .add-on, -.input-append .add-on { - display: inline-block; - width: auto; - height: 18px; - min-width: 16px; - padding: 4px 5px; - font-weight: normal; - line-height: 18px; - text-align: center; - text-shadow: 0 1px 0 #ffffff; - vertical-align: middle; - background-color: #eeeeee; - border: 1px solid #ccc; -} -.input-prepend .add-on, -.input-append .add-on, -.input-prepend .btn, -.input-append .btn { - margin-left: -1px; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} -.input-prepend .active, -.input-append .active { - background-color: #a9dba9; - border-color: #46a546; -} -.input-prepend .add-on, -.input-prepend .btn { - margin-right: -1px; -} -.input-prepend .add-on:first-child, -.input-prepend .btn:first-child { - -webkit-border-radius: 3px 0 0 3px; - -moz-border-radius: 3px 0 0 3px; - border-radius: 3px 0 0 3px; -} -.input-append input, -.input-append select, -.input-append .uneditable-input { - -webkit-border-radius: 3px 0 0 3px; - -moz-border-radius: 3px 0 0 3px; - border-radius: 3px 0 0 3px; -} -.input-append .uneditable-input { - border-right-color: #ccc; - border-left-color: #eee; -} -.input-append .add-on:last-child, -.input-append .btn:last-child { - -webkit-border-radius: 0 3px 3px 0; - -moz-border-radius: 0 3px 3px 0; - border-radius: 0 3px 3px 0; -} -.input-prepend.input-append input, -.input-prepend.input-append select, -.input-prepend.input-append .uneditable-input { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} -.input-prepend.input-append .add-on:first-child, -.input-prepend.input-append .btn:first-child { - margin-right: -1px; - -webkit-border-radius: 3px 0 0 3px; - -moz-border-radius: 3px 0 0 3px; - border-radius: 3px 0 0 3px; -} -.input-prepend.input-append .add-on:last-child, -.input-prepend.input-append .btn:last-child { - margin-left: -1px; - -webkit-border-radius: 0 3px 3px 0; - -moz-border-radius: 0 3px 3px 0; - border-radius: 0 3px 3px 0; -} -.search-query { - padding-right: 14px; - padding-right: 4px \9; - padding-left: 14px; - padding-left: 4px \9; - - margin-bottom: 0; - -webkit-border-radius: 14px; - -moz-border-radius: 14px; - border-radius: 14px; -} -.form-search input, -.form-inline input, -.form-horizontal input, -.form-search textarea, -.form-inline textarea, -.form-horizontal textarea, -.form-search select, -.form-inline select, -.form-horizontal select, -.form-search .help-inline, -.form-inline .help-inline, -.form-horizontal .help-inline, -.form-search .uneditable-input, -.form-inline .uneditable-input, -.form-horizontal .uneditable-input, -.form-search .input-prepend, -.form-inline .input-prepend, -.form-horizontal .input-prepend, -.form-search .input-append, -.form-inline .input-append, -.form-horizontal .input-append { - display: inline-block; - *display: inline; - margin-bottom: 0; - *zoom: 1; -} -.form-search .hide, -.form-inline .hide, -.form-horizontal .hide { - display: none; -} -.form-search label, -.form-inline label { - display: inline-block; -} -.form-search .input-append, -.form-inline .input-append, -.form-search .input-prepend, -.form-inline .input-prepend { - margin-bottom: 0; -} -.form-search .radio, -.form-search .checkbox, -.form-inline .radio, -.form-inline .checkbox { - padding-left: 0; - margin-bottom: 0; - vertical-align: middle; -} -.form-search .radio input[type="radio"], -.form-search .checkbox input[type="checkbox"], -.form-inline .radio input[type="radio"], -.form-inline .checkbox input[type="checkbox"] { - float: left; - margin-right: 3px; - margin-left: 0; -} -.control-group { - margin-bottom: 9px; -} -legend + .control-group { - margin-top: 18px; - -webkit-margin-top-collapse: separate; -} -.form-horizontal .control-group { - margin-bottom: 18px; - *zoom: 1; -} -.form-horizontal .control-group:before, -.form-horizontal .control-group:after { - display: table; - content: ""; -} -.form-horizontal .control-group:after { - clear: both; -} -.form-horizontal .control-label { - float: left; - width: 140px; - padding-top: 5px; - text-align: right; -} -.form-horizontal .controls { - *display: inline-block; - *padding-left: 20px; - margin-left: 160px; - *margin-left: 0; -} -.form-horizontal .controls:first-child { - *padding-left: 160px; -} -.form-horizontal .help-block { - margin-top: 9px; - margin-bottom: 0; -} -.form-horizontal .form-actions { - padding-left: 160px; -} -table { - max-width: 100%; - background-color: transparent; - border-collapse: collapse; - border-spacing: 0; -} -.table { - width: 100%; - margin-bottom: 18px; -} -.table th, -.table td { - padding: 8px; - line-height: 18px; - text-align: left; - vertical-align: top; - border-top: 1px solid #dddddd; -} -.table th { - font-weight: bold; -} -.table thead th { - vertical-align: bottom; -} -.table caption + thead tr:first-child th, -.table caption + thead tr:first-child td, -.table colgroup + thead tr:first-child th, -.table colgroup + thead tr:first-child td, -.table thead:first-child tr:first-child th, -.table thead:first-child tr:first-child td { - border-top: 0; -} -.table tbody + tbody { - border-top: 2px solid #dddddd; -} -.table-condensed th, -.table-condensed td { - padding: 4px 5px; -} -.table-bordered { - border: 1px solid #dddddd; - border-collapse: separate; - *border-collapse: collapsed; - border-left: 0; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -.table-bordered th, -.table-bordered td { - border-left: 1px solid #dddddd; -} -.table-bordered caption + thead tr:first-child th, -.table-bordered caption + tbody tr:first-child th, -.table-bordered caption + tbody tr:first-child td, -.table-bordered colgroup + thead tr:first-child th, -.table-bordered colgroup + tbody tr:first-child th, -.table-bordered colgroup + tbody tr:first-child td, -.table-bordered thead:first-child tr:first-child th, -.table-bordered tbody:first-child tr:first-child th, -.table-bordered tbody:first-child tr:first-child td { - border-top: 0; -} -.table-bordered thead:first-child tr:first-child th:first-child, -.table-bordered tbody:first-child tr:first-child td:first-child { - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-topleft: 4px; -} -.table-bordered thead:first-child tr:first-child th:last-child, -.table-bordered tbody:first-child tr:first-child td:last-child { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -moz-border-radius-topright: 4px; -} -.table-bordered thead:last-child tr:last-child th:first-child, -.table-bordered tbody:last-child tr:last-child td:first-child { - -webkit-border-radius: 0 0 0 4px; - -moz-border-radius: 0 0 0 4px; - border-radius: 0 0 0 4px; - -webkit-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; -} -.table-bordered thead:last-child tr:last-child th:last-child, -.table-bordered tbody:last-child tr:last-child td:last-child { - -webkit-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px; - -moz-border-radius-bottomright: 4px; -} -.table-striped tbody tr:nth-child(odd) td, -.table-striped tbody tr:nth-child(odd) th { - background-color: #f9f9f9; -} -.table tbody tr:hover td, -.table tbody tr:hover th { - background-color: #f5f5f5; -} -table .span1 { - float: none; - width: 44px; - margin-left: 0; -} -table .span2 { - float: none; - width: 124px; - margin-left: 0; -} -table .span3 { - float: none; - width: 204px; - margin-left: 0; -} -table .span4 { - float: none; - width: 284px; - margin-left: 0; -} -table .span5 { - float: none; - width: 364px; - margin-left: 0; -} -table .span6 { - float: none; - width: 444px; - margin-left: 0; -} -table .span7 { - float: none; - width: 524px; - margin-left: 0; -} -table .span8 { - float: none; - width: 604px; - margin-left: 0; -} -table .span9 { - float: none; - width: 684px; - margin-left: 0; -} -table .span10 { - float: none; - width: 764px; - margin-left: 0; -} -table .span11 { - float: none; - width: 844px; - margin-left: 0; -} -table .span12 { - float: none; - width: 924px; - margin-left: 0; -} -table .span13 { - float: none; - width: 1004px; - margin-left: 0; -} -table .span14 { - float: none; - width: 1084px; - margin-left: 0; -} -table .span15 { - float: none; - width: 1164px; - margin-left: 0; -} -table .span16 { - float: none; - width: 1244px; - margin-left: 0; -} -table .span17 { - float: none; - width: 1324px; - margin-left: 0; -} -table .span18 { - float: none; - width: 1404px; - margin-left: 0; -} -table .span19 { - float: none; - width: 1484px; - margin-left: 0; -} -table .span20 { - float: none; - width: 1564px; - margin-left: 0; -} -table .span21 { - float: none; - width: 1644px; - margin-left: 0; -} -table .span22 { - float: none; - width: 1724px; - margin-left: 0; -} -table .span23 { - float: none; - width: 1804px; - margin-left: 0; -} -table .span24 { - float: none; - width: 1884px; - margin-left: 0; -} -[class^="icon-"], -[class*=" icon-"] { - display: inline-block; - width: 14px; - height: 14px; - *margin-right: .3em; - line-height: 14px; - vertical-align: text-top; - background-image: url(../img/glyphicons-halflings.png); - background-position: 14px 14px; - background-repeat: no-repeat; -} -[class^="icon-"]:last-child, -[class*=" icon-"]:last-child { - *margin-left: 0; -} -.icon-white { - background-image: url(../img/glyphicons-halflings-white.png); -} -.icon-glass { - background-position: 0 0; -} -.icon-music { - background-position: -24px 0; -} -.icon-search { - background-position: -48px 0; -} -.icon-envelope { - background-position: -72px 0; -} -.icon-heart { - background-position: -96px 0; -} -.icon-star { - background-position: -120px 0; -} -.icon-star-empty { - background-position: -144px 0; -} -.icon-user { - background-position: -168px 0; -} -.icon-film { - background-position: -192px 0; -} -.icon-th-large { - background-position: -216px 0; -} -.icon-th { - background-position: -240px 0; -} -.icon-th-list { - background-position: -264px 0; -} -.icon-ok { - background-position: -288px 0; -} -.icon-remove { - background-position: -312px 0; -} -.icon-zoom-in { - background-position: -336px 0; -} -.icon-zoom-out { - background-position: -360px 0; -} -.icon-off { - background-position: -384px 0; -} -.icon-signal { - background-position: -408px 0; -} -.icon-cog { - background-position: -432px 0; -} -.icon-trash { - background-position: -456px 0; -} -.icon-home { - background-position: 0 -24px; -} -.icon-file { - background-position: -24px -24px; -} -.icon-time { - background-position: -48px -24px; -} -.icon-road { - background-position: -72px -24px; -} -.icon-download-alt { - background-position: -96px -24px; -} -.icon-download { - background-position: -120px -24px; -} -.icon-upload { - background-position: -144px -24px; -} -.icon-inbox { - background-position: -168px -24px; -} -.icon-play-circle { - background-position: -192px -24px; -} -.icon-repeat { - background-position: -216px -24px; -} -.icon-refresh { - background-position: -240px -24px; -} -.icon-list-alt { - background-position: -264px -24px; -} -.icon-lock { - background-position: -287px -24px; -} -.icon-flag { - background-position: -312px -24px; -} -.icon-headphones { - background-position: -336px -24px; -} -.icon-volume-off { - background-position: -360px -24px; -} -.icon-volume-down { - background-position: -384px -24px; -} -.icon-volume-up { - background-position: -408px -24px; -} -.icon-qrcode { - background-position: -432px -24px; -} -.icon-barcode { - background-position: -456px -24px; -} -.icon-tag { - background-position: 0 -48px; -} -.icon-tags { - background-position: -25px -48px; -} -.icon-book { - background-position: -48px -48px; -} -.icon-bookmark { - background-position: -72px -48px; -} -.icon-print { - background-position: -96px -48px; -} -.icon-camera { - background-position: -120px -48px; -} -.icon-font { - background-position: -144px -48px; -} -.icon-bold { - background-position: -167px -48px; -} -.icon-italic { - background-position: -192px -48px; -} -.icon-text-height { - background-position: -216px -48px; -} -.icon-text-width { - background-position: -240px -48px; -} -.icon-align-left { - background-position: -264px -48px; -} -.icon-align-center { - background-position: -288px -48px; -} -.icon-align-right { - background-position: -312px -48px; -} -.icon-align-justify { - background-position: -336px -48px; -} -.icon-list { - background-position: -360px -48px; -} -.icon-indent-left { - background-position: -384px -48px; -} -.icon-indent-right { - background-position: -408px -48px; -} -.icon-facetime-video { - background-position: -432px -48px; -} -.icon-picture { - background-position: -456px -48px; -} -.icon-pencil { - background-position: 0 -72px; -} -.icon-map-marker { - background-position: -24px -72px; -} -.icon-adjust { - background-position: -48px -72px; -} -.icon-tint { - background-position: -72px -72px; -} -.icon-edit { - background-position: -96px -72px; -} -.icon-share { - background-position: -120px -72px; -} -.icon-check { - background-position: -144px -72px; -} -.icon-move { - background-position: -168px -72px; -} -.icon-step-backward { - background-position: -192px -72px; -} -.icon-fast-backward { - background-position: -216px -72px; -} -.icon-backward { - background-position: -240px -72px; -} -.icon-play { - background-position: -264px -72px; -} -.icon-pause { - background-position: -288px -72px; -} -.icon-stop { - background-position: -312px -72px; -} -.icon-forward { - background-position: -336px -72px; -} -.icon-fast-forward { - background-position: -360px -72px; -} -.icon-step-forward { - background-position: -384px -72px; -} -.icon-eject { - background-position: -408px -72px; -} -.icon-chevron-left { - background-position: -432px -72px; -} -.icon-chevron-right { - background-position: -456px -72px; -} -.icon-plus-sign { - background-position: 0 -96px; -} -.icon-minus-sign { - background-position: -24px -96px; -} -.icon-remove-sign { - background-position: -48px -96px; -} -.icon-ok-sign { - background-position: -72px -96px; -} -.icon-question-sign { - background-position: -96px -96px; -} -.icon-info-sign { - background-position: -120px -96px; -} -.icon-screenshot { - background-position: -144px -96px; -} -.icon-remove-circle { - background-position: -168px -96px; -} -.icon-ok-circle { - background-position: -192px -96px; -} -.icon-ban-circle { - background-position: -216px -96px; -} -.icon-arrow-left { - background-position: -240px -96px; -} -.icon-arrow-right { - background-position: -264px -96px; -} -.icon-arrow-up { - background-position: -289px -96px; -} -.icon-arrow-down { - background-position: -312px -96px; -} -.icon-share-alt { - background-position: -336px -96px; -} -.icon-resize-full { - background-position: -360px -96px; -} -.icon-resize-small { - background-position: -384px -96px; -} -.icon-plus { - background-position: -408px -96px; -} -.icon-minus { - background-position: -433px -96px; -} -.icon-asterisk { - background-position: -456px -96px; -} -.icon-exclamation-sign { - background-position: 0 -120px; -} -.icon-gift { - background-position: -24px -120px; -} -.icon-leaf { - background-position: -48px -120px; -} -.icon-fire { - background-position: -72px -120px; -} -.icon-eye-open { - background-position: -96px -120px; -} -.icon-eye-close { - background-position: -120px -120px; -} -.icon-warning-sign { - background-position: -144px -120px; -} -.icon-plane { - background-position: -168px -120px; -} -.icon-calendar { - background-position: -192px -120px; -} -.icon-random { - background-position: -216px -120px; -} -.icon-comment { - background-position: -240px -120px; -} -.icon-magnet { - background-position: -264px -120px; -} -.icon-chevron-up { - background-position: -288px -120px; -} -.icon-chevron-down { - background-position: -313px -119px; -} -.icon-retweet { - background-position: -336px -120px; -} -.icon-shopping-cart { - background-position: -360px -120px; -} -.icon-folder-close { - background-position: -384px -120px; -} -.icon-folder-open { - background-position: -408px -120px; -} -.icon-resize-vertical { - background-position: -432px -119px; -} -.icon-resize-horizontal { - background-position: -456px -118px; -} -.icon-hdd { - background-position: 0 -144px; -} -.icon-bullhorn { - background-position: -24px -144px; -} -.icon-bell { - background-position: -48px -144px; -} -.icon-certificate { - background-position: -72px -144px; -} -.icon-thumbs-up { - background-position: -96px -144px; -} -.icon-thumbs-down { - background-position: -120px -144px; -} -.icon-hand-right { - background-position: -144px -144px; -} -.icon-hand-left { - background-position: -168px -144px; -} -.icon-hand-up { - background-position: -192px -144px; -} -.icon-hand-down { - background-position: -216px -144px; -} -.icon-circle-arrow-right { - background-position: -240px -144px; -} -.icon-circle-arrow-left { - background-position: -264px -144px; -} -.icon-circle-arrow-up { - background-position: -288px -144px; -} -.icon-circle-arrow-down { - background-position: -312px -144px; -} -.icon-globe { - background-position: -336px -144px; -} -.icon-wrench { - background-position: -360px -144px; -} -.icon-tasks { - background-position: -384px -144px; -} -.icon-filter { - background-position: -408px -144px; -} -.icon-briefcase { - background-position: -432px -144px; -} -.icon-fullscreen { - background-position: -456px -144px; -} -.dropup, -.dropdown { - position: relative; -} -.dropdown-toggle { - *margin-bottom: -3px; -} -.dropdown-toggle:active, -.open .dropdown-toggle { - outline: 0; -} -.caret { - display: inline-block; - width: 0; - height: 0; - vertical-align: top; - border-top: 4px solid #000000; - border-right: 4px solid transparent; - border-left: 4px solid transparent; - content: ""; - opacity: 0.3; - filter: alpha(opacity=30); -} -.dropdown .caret { - margin-top: 8px; - margin-left: 2px; -} -.dropdown:hover .caret, -.open .caret { - opacity: 1; - filter: alpha(opacity=100); -} -.dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 4px 0; - margin: 1px 0 0; - list-style: none; - background-color: #ffffff; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - *border-right-width: 2px; - *border-bottom-width: 2px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -webkit-background-clip: padding-box; - -moz-background-clip: padding; - background-clip: padding-box; -} -.dropdown-menu.pull-right { - right: 0; - left: auto; -} -.dropdown-menu .divider { - *width: 100%; - height: 1px; - margin: 8px 1px; - *margin: -5px 0 5px; - overflow: hidden; - background-color: #e5e5e5; - border-bottom: 1px solid #ffffff; -} -.dropdown-menu a { - display: block; - padding: 3px 15px; - clear: both; - font-weight: normal; - line-height: 18px; - color: #333333; - white-space: nowrap; -} -.dropdown-menu li > a:hover, -.dropdown-menu .active > a, -.dropdown-menu .active > a:hover { - color: #ffffff; - text-decoration: none; - background-color: #0088cc; -} -.open { - *z-index: 1000; -} -.open > .dropdown-menu { - display: block; -} -.pull-right > .dropdown-menu { - right: 0; - left: auto; -} -.dropup .caret, -.navbar-fixed-bottom .dropdown .caret { - border-top: 0; - border-bottom: 4px solid #000000; - content: "\2191"; -} -.dropup .dropdown-menu, -.navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 1px; -} -.typeahead { - margin-top: 2px; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -.well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: #f5f5f5; - border: 1px solid #eee; - border: 1px solid rgba(0, 0, 0, 0.05); - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); -} -.well blockquote { - border-color: #ddd; - border-color: rgba(0, 0, 0, 0.15); -} -.well-large { - padding: 24px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} -.well-small { - padding: 9px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} -.fade { - opacity: 0; - -webkit-transition: opacity 0.15s linear; - -moz-transition: opacity 0.15s linear; - -ms-transition: opacity 0.15s linear; - -o-transition: opacity 0.15s linear; - transition: opacity 0.15s linear; -} -.fade.in { - opacity: 1; -} -.collapse { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition: height 0.35s ease; - -moz-transition: height 0.35s ease; - -ms-transition: height 0.35s ease; - -o-transition: height 0.35s ease; - transition: height 0.35s ease; -} -.collapse.in { - height: auto; -} -.close { - float: right; - font-size: 20px; - font-weight: bold; - line-height: 18px; - color: #000000; - text-shadow: 0 1px 0 #ffffff; - opacity: 0.2; - filter: alpha(opacity=20); -} -.close:hover { - color: #000000; - text-decoration: none; - cursor: pointer; - opacity: 0.4; - filter: alpha(opacity=40); -} -button.close { - padding: 0; - cursor: pointer; - background: transparent; - border: 0; - -webkit-appearance: none; -} -.btn { - display: inline-block; - *display: inline; - padding: 4px 10px 4px; - margin-bottom: 0; - *margin-left: .3em; - font-size: 13px; - line-height: 18px; - *line-height: 20px; - color: #333333; - text-align: center; - text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); - vertical-align: middle; - cursor: pointer; - background-color: #f5f5f5; - *background-color: #e6e6e6; - background-image: -ms-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); - background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); - background-image: linear-gradient(top, #ffffff, #e6e6e6); - background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); - background-repeat: repeat-x; - border: 1px solid #cccccc; - *border: 0; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - border-color: #e6e6e6 #e6e6e6 #bfbfbf; - border-bottom-color: #b3b3b3; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); - filter: progid:dximagetransform.microsoft.gradient(enabled=false); - *zoom: 1; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} -.btn:hover, -.btn:active, -.btn.active, -.btn.disabled, -.btn[disabled] { - background-color: #e6e6e6; - *background-color: #d9d9d9; -} -.btn:active, -.btn.active { - background-color: #cccccc \9; -} -.btn:first-child { - *margin-left: 0; -} -.btn:hover { - color: #333333; - text-decoration: none; - background-color: #e6e6e6; - *background-color: #d9d9d9; - - background-position: 0 -15px; - -webkit-transition: background-position 0.1s linear; - -moz-transition: background-position 0.1s linear; - -ms-transition: background-position 0.1s linear; - -o-transition: background-position 0.1s linear; - transition: background-position 0.1s linear; -} -.btn:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -.btn.active, -.btn:active { - background-color: #e6e6e6; - background-color: #d9d9d9 \9; - background-image: none; - outline: 0; - -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -} -.btn.disabled, -.btn[disabled] { - cursor: default; - background-color: #e6e6e6; - background-image: none; - opacity: 0.65; - filter: alpha(opacity=65); - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} -.btn-large { - padding: 9px 14px; - font-size: 15px; - line-height: normal; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; -} -.btn-large [class^="icon-"] { - margin-top: 1px; -} -.btn-small { - padding: 5px 9px; - font-size: 11px; - line-height: 16px; -} -.btn-small [class^="icon-"] { - margin-top: -1px; -} -.btn-mini { - padding: 2px 6px; - font-size: 11px; - line-height: 14px; -} -.btn-primary, -.btn-primary:hover, -.btn-warning, -.btn-warning:hover, -.btn-danger, -.btn-danger:hover, -.btn-success, -.btn-success:hover, -.btn-info, -.btn-info:hover, -.btn-inverse, -.btn-inverse:hover { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); -} -.btn-primary.active, -.btn-warning.active, -.btn-danger.active, -.btn-success.active, -.btn-info.active, -.btn-inverse.active { - color: rgba(255, 255, 255, 0.75); -} -.btn { - border-color: #ccc; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); -} -.btn-primary { - background-color: #0074cc; - *background-color: #0055cc; - background-image: -ms-linear-gradient(top, #0088cc, #0055cc); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0055cc)); - background-image: -webkit-linear-gradient(top, #0088cc, #0055cc); - background-image: -o-linear-gradient(top, #0088cc, #0055cc); - background-image: -moz-linear-gradient(top, #0088cc, #0055cc); - background-image: linear-gradient(top, #0088cc, #0055cc); - background-repeat: repeat-x; - border-color: #0055cc #0055cc #003580; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#0088cc', endColorstr='#0055cc', GradientType=0); - filter: progid:dximagetransform.microsoft.gradient(enabled=false); -} -.btn-primary:hover, -.btn-primary:active, -.btn-primary.active, -.btn-primary.disabled, -.btn-primary[disabled] { - background-color: #0055cc; - *background-color: #004ab3; -} -.btn-primary:active, -.btn-primary.active { - background-color: #004099 \9; -} -.btn-warning { - background-color: #faa732; - *background-color: #f89406; - background-image: -ms-linear-gradient(top, #fbb450, #f89406); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); - background-image: -webkit-linear-gradient(top, #fbb450, #f89406); - background-image: -o-linear-gradient(top, #fbb450, #f89406); - background-image: -moz-linear-gradient(top, #fbb450, #f89406); - background-image: linear-gradient(top, #fbb450, #f89406); - background-repeat: repeat-x; - border-color: #f89406 #f89406 #ad6704; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0); - filter: progid:dximagetransform.microsoft.gradient(enabled=false); -} -.btn-warning:hover, -.btn-warning:active, -.btn-warning.active, -.btn-warning.disabled, -.btn-warning[disabled] { - background-color: #f89406; - *background-color: #df8505; -} -.btn-warning:active, -.btn-warning.active { - background-color: #c67605 \9; -} -.btn-danger { - background-color: #da4f49; - *background-color: #bd362f; - background-image: -ms-linear-gradient(top, #ee5f5b, #bd362f); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); - background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); - background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); - background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); - background-image: linear-gradient(top, #ee5f5b, #bd362f); - background-repeat: repeat-x; - border-color: #bd362f #bd362f #802420; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#bd362f', GradientType=0); - filter: progid:dximagetransform.microsoft.gradient(enabled=false); -} -.btn-danger:hover, -.btn-danger:active, -.btn-danger.active, -.btn-danger.disabled, -.btn-danger[disabled] { - background-color: #bd362f; - *background-color: #a9302a; -} -.btn-danger:active, -.btn-danger.active { - background-color: #942a25 \9; -} -.btn-success { - background-color: #5bb75b; - *background-color: #51a351; - background-image: -ms-linear-gradient(top, #62c462, #51a351); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); - background-image: -webkit-linear-gradient(top, #62c462, #51a351); - background-image: -o-linear-gradient(top, #62c462, #51a351); - background-image: -moz-linear-gradient(top, #62c462, #51a351); - background-image: linear-gradient(top, #62c462, #51a351); - background-repeat: repeat-x; - border-color: #51a351 #51a351 #387038; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#62c462', endColorstr='#51a351', GradientType=0); - filter: progid:dximagetransform.microsoft.gradient(enabled=false); -} -.btn-success:hover, -.btn-success:active, -.btn-success.active, -.btn-success.disabled, -.btn-success[disabled] { - background-color: #51a351; - *background-color: #499249; -} -.btn-success:active, -.btn-success.active { - background-color: #408140 \9; -} -.btn-info { - background-color: #49afcd; - *background-color: #2f96b4; - background-image: -ms-linear-gradient(top, #5bc0de, #2f96b4); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); - background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); - background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); - background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); - background-image: linear-gradient(top, #5bc0de, #2f96b4); - background-repeat: repeat-x; - border-color: #2f96b4 #2f96b4 #1f6377; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#5bc0de', endColorstr='#2f96b4', GradientType=0); - filter: progid:dximagetransform.microsoft.gradient(enabled=false); -} -.btn-info:hover, -.btn-info:active, -.btn-info.active, -.btn-info.disabled, -.btn-info[disabled] { - background-color: #2f96b4; - *background-color: #2a85a0; -} -.btn-info:active, -.btn-info.active { - background-color: #24748c \9; -} -.btn-inverse { - background-color: #414141; - *background-color: #222222; - background-image: -ms-linear-gradient(top, #555555, #222222); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#555555), to(#222222)); - background-image: -webkit-linear-gradient(top, #555555, #222222); - background-image: -o-linear-gradient(top, #555555, #222222); - background-image: -moz-linear-gradient(top, #555555, #222222); - background-image: linear-gradient(top, #555555, #222222); - background-repeat: repeat-x; - border-color: #222222 #222222 #000000; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#555555', endColorstr='#222222', GradientType=0); - filter: progid:dximagetransform.microsoft.gradient(enabled=false); -} -.btn-inverse:hover, -.btn-inverse:active, -.btn-inverse.active, -.btn-inverse.disabled, -.btn-inverse[disabled] { - background-color: #222222; - *background-color: #151515; -} -.btn-inverse:active, -.btn-inverse.active { - background-color: #080808 \9; -} -button.btn, -input[type="submit"].btn { - *padding-top: 2px; - *padding-bottom: 2px; -} -button.btn::-moz-focus-inner, -input[type="submit"].btn::-moz-focus-inner { - padding: 0; - border: 0; -} -button.btn.btn-large, -input[type="submit"].btn.btn-large { - *padding-top: 7px; - *padding-bottom: 7px; -} -button.btn.btn-small, -input[type="submit"].btn.btn-small { - *padding-top: 3px; - *padding-bottom: 3px; -} -button.btn.btn-mini, -input[type="submit"].btn.btn-mini { - *padding-top: 1px; - *padding-bottom: 1px; -} -.btn-group { - position: relative; - *margin-left: .3em; - *zoom: 1; -} -.btn-group:before, -.btn-group:after { - display: table; - content: ""; -} -.btn-group:after { - clear: both; -} -.btn-group:first-child { - *margin-left: 0; -} -.btn-group + .btn-group { - margin-left: 5px; -} -.btn-toolbar { - margin-top: 9px; - margin-bottom: 9px; -} -.btn-toolbar .btn-group { - display: inline-block; - *display: inline; - - *zoom: 1; -} -.btn-group > .btn { - position: relative; - float: left; - margin-left: -1px; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} -.btn-group > .btn:first-child { - margin-left: 0; - -webkit-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px; - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; - -moz-border-radius-topleft: 4px; -} -.btn-group > .btn:last-child, -.btn-group > .dropdown-toggle { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px; - -moz-border-radius-topright: 4px; - -moz-border-radius-bottomright: 4px; -} -.btn-group > .btn.large:first-child { - margin-left: 0; - -webkit-border-bottom-left-radius: 6px; - border-bottom-left-radius: 6px; - -webkit-border-top-left-radius: 6px; - border-top-left-radius: 6px; - -moz-border-radius-bottomleft: 6px; - -moz-border-radius-topleft: 6px; -} -.btn-group > .btn.large:last-child, -.btn-group > .large.dropdown-toggle { - -webkit-border-top-right-radius: 6px; - border-top-right-radius: 6px; - -webkit-border-bottom-right-radius: 6px; - border-bottom-right-radius: 6px; - -moz-border-radius-topright: 6px; - -moz-border-radius-bottomright: 6px; -} -.btn-group > .btn:hover, -.btn-group > .btn:focus, -.btn-group > .btn:active, -.btn-group > .btn.active { - z-index: 2; -} -.btn-group .dropdown-toggle:active, -.btn-group.open .dropdown-toggle { - outline: 0; -} -.btn-group > .dropdown-toggle { - *padding-top: 4px; - padding-right: 8px; - *padding-bottom: 4px; - padding-left: 8px; - -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} -.btn-group > .btn-mini.dropdown-toggle { - padding-right: 5px; - padding-left: 5px; -} -.btn-group > .btn-small.dropdown-toggle { - *padding-top: 4px; - *padding-bottom: 4px; -} -.btn-group > .btn-large.dropdown-toggle { - padding-right: 12px; - padding-left: 12px; -} -.btn-group.open .dropdown-toggle { - background-image: none; - -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -} -.btn-group.open .btn.dropdown-toggle { - background-color: #e6e6e6; -} -.btn-group.open .btn-primary.dropdown-toggle { - background-color: #0055cc; -} -.btn-group.open .btn-warning.dropdown-toggle { - background-color: #f89406; -} -.btn-group.open .btn-danger.dropdown-toggle { - background-color: #bd362f; -} -.btn-group.open .btn-success.dropdown-toggle { - background-color: #51a351; -} -.btn-group.open .btn-info.dropdown-toggle { - background-color: #2f96b4; -} -.btn-group.open .btn-inverse.dropdown-toggle { - background-color: #222222; -} -.btn .caret { - margin-top: 7px; - margin-left: 0; -} -.btn:hover .caret, -.open.btn-group .caret { - opacity: 1; - filter: alpha(opacity=100); -} -.btn-mini .caret { - margin-top: 5px; -} -.btn-small .caret { - margin-top: 6px; -} -.btn-large .caret { - margin-top: 6px; - border-top-width: 5px; - border-right-width: 5px; - border-left-width: 5px; -} -.dropup .btn-large .caret { - border-top: 0; - border-bottom: 5px solid #000000; -} -.btn-primary .caret, -.btn-warning .caret, -.btn-danger .caret, -.btn-info .caret, -.btn-success .caret, -.btn-inverse .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; - opacity: 0.75; - filter: alpha(opacity=75); -} -.alert { - padding: 8px 35px 8px 14px; - margin-bottom: 18px; - color: #c09853; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - background-color: #fcf8e3; - border: 1px solid #fbeed5; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -.alert-heading { - color: inherit; -} -.alert .close { - position: relative; - top: -2px; - right: -21px; - line-height: 18px; -} -.alert-success { - color: #468847; - background-color: #dff0d8; - border-color: #d6e9c6; -} -.alert-danger, -.alert-error { - color: #b94a48; - background-color: #f2dede; - border-color: #eed3d7; -} -.alert-info { - color: #3a87ad; - background-color: #d9edf7; - border-color: #bce8f1; -} -.alert-block { - padding-top: 14px; - padding-bottom: 14px; -} -.alert-block > p, -.alert-block > ul { - margin-bottom: 0; -} -.alert-block p + p { - margin-top: 5px; -} -.nav { - margin-bottom: 18px; - margin-left: 0; - list-style: none; -} -.nav > li > a { - display: block; -} -.nav > li > a:hover { - text-decoration: none; - background-color: #eeeeee; -} -.nav > .pull-right { - float: right; -} -.nav .nav-header { - display: block; - padding: 3px 15px; - font-size: 11px; - font-weight: bold; - line-height: 18px; - color: #999999; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - text-transform: uppercase; -} -.nav li + .nav-header { - margin-top: 9px; -} -.nav-list { - padding-right: 15px; - padding-left: 15px; - margin-bottom: 0; -} -.nav-list > li > a, -.nav-list .nav-header { - margin-right: -15px; - margin-left: -15px; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); -} -.nav-list > li > a { - padding: 3px 15px; -} -.nav-list > .active > a, -.nav-list > .active > a:hover { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); - background-color: #0088cc; -} -.nav-list [class^="icon-"] { - margin-right: 2px; -} -.nav-list .divider { - *width: 100%; - height: 1px; - margin: 8px 1px; - *margin: -5px 0 5px; - overflow: hidden; - background-color: #e5e5e5; - border-bottom: 1px solid #ffffff; -} -.nav-tabs, -.nav-pills { - *zoom: 1; -} -.nav-tabs:before, -.nav-pills:before, -.nav-tabs:after, -.nav-pills:after { - display: table; - content: ""; -} -.nav-tabs:after, -.nav-pills:after { - clear: both; -} -.nav-tabs > li, -.nav-pills > li { - float: left; -} -.nav-tabs > li > a, -.nav-pills > li > a { - padding-right: 12px; - padding-left: 12px; - margin-right: 2px; - line-height: 14px; -} -.nav-tabs { - border-bottom: 1px solid #ddd; -} -.nav-tabs > li { - margin-bottom: -1px; -} -.nav-tabs > li > a { - padding-top: 8px; - padding-bottom: 8px; - line-height: 18px; - border: 1px solid transparent; - -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; -} -.nav-tabs > li > a:hover { - border-color: #eeeeee #eeeeee #dddddd; -} -.nav-tabs > .active > a, -.nav-tabs > .active > a:hover { - color: #555555; - cursor: default; - background-color: #ffffff; - border: 1px solid #ddd; - border-bottom-color: transparent; -} -.nav-pills > li > a { - padding-top: 8px; - padding-bottom: 8px; - margin-top: 2px; - margin-bottom: 2px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; -} -.nav-pills > .active > a, -.nav-pills > .active > a:hover { - color: #ffffff; - background-color: #0088cc; -} -.nav-stacked > li { - float: none; -} -.nav-stacked > li > a { - margin-right: 0; -} -.nav-tabs.nav-stacked { - border-bottom: 0; -} -.nav-tabs.nav-stacked > li > a { - border: 1px solid #ddd; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} -.nav-tabs.nav-stacked > li:first-child > a { - -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; -} -.nav-tabs.nav-stacked > li:last-child > a { - -webkit-border-radius: 0 0 4px 4px; - -moz-border-radius: 0 0 4px 4px; - border-radius: 0 0 4px 4px; -} -.nav-tabs.nav-stacked > li > a:hover { - z-index: 2; - border-color: #ddd; -} -.nav-pills.nav-stacked > li > a { - margin-bottom: 3px; -} -.nav-pills.nav-stacked > li:last-child > a { - margin-bottom: 1px; -} -.nav-tabs .dropdown-menu { - -webkit-border-radius: 0 0 5px 5px; - -moz-border-radius: 0 0 5px 5px; - border-radius: 0 0 5px 5px; -} -.nav-pills .dropdown-menu { - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -.nav-tabs .dropdown-toggle .caret, -.nav-pills .dropdown-toggle .caret { - margin-top: 6px; - border-top-color: #0088cc; - border-bottom-color: #0088cc; -} -.nav-tabs .dropdown-toggle:hover .caret, -.nav-pills .dropdown-toggle:hover .caret { - border-top-color: #005580; - border-bottom-color: #005580; -} -.nav-tabs .active .dropdown-toggle .caret, -.nav-pills .active .dropdown-toggle .caret { - border-top-color: #333333; - border-bottom-color: #333333; -} -.nav > .dropdown.active > a:hover { - color: #000000; - cursor: pointer; -} -.nav-tabs .open .dropdown-toggle, -.nav-pills .open .dropdown-toggle, -.nav > li.dropdown.open.active > a:hover { - color: #ffffff; - background-color: #999999; - border-color: #999999; -} -.nav li.dropdown.open .caret, -.nav li.dropdown.open.active .caret, -.nav li.dropdown.open a:hover .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; - opacity: 1; - filter: alpha(opacity=100); -} -.tabs-stacked .open > a:hover { - border-color: #999999; -} -.tabbable { - *zoom: 1; -} -.tabbable:before, -.tabbable:after { - display: table; - content: ""; -} -.tabbable:after { - clear: both; -} -.tab-content { - overflow: auto; -} -.tabs-below > .nav-tabs, -.tabs-right > .nav-tabs, -.tabs-left > .nav-tabs { - border-bottom: 0; -} -.tab-content > .tab-pane, -.pill-content > .pill-pane { - display: none; -} -.tab-content > .active, -.pill-content > .active { - display: block; -} -.tabs-below > .nav-tabs { - border-top: 1px solid #ddd; -} -.tabs-below > .nav-tabs > li { - margin-top: -1px; - margin-bottom: 0; -} -.tabs-below > .nav-tabs > li > a { - -webkit-border-radius: 0 0 4px 4px; - -moz-border-radius: 0 0 4px 4px; - border-radius: 0 0 4px 4px; -} -.tabs-below > .nav-tabs > li > a:hover { - border-top-color: #ddd; - border-bottom-color: transparent; -} -.tabs-below > .nav-tabs > .active > a, -.tabs-below > .nav-tabs > .active > a:hover { - border-color: transparent #ddd #ddd #ddd; -} -.tabs-left > .nav-tabs > li, -.tabs-right > .nav-tabs > li { - float: none; -} -.tabs-left > .nav-tabs > li > a, -.tabs-right > .nav-tabs > li > a { - min-width: 74px; - margin-right: 0; - margin-bottom: 3px; -} -.tabs-left > .nav-tabs { - float: left; - margin-right: 19px; - border-right: 1px solid #ddd; -} -.tabs-left > .nav-tabs > li > a { - margin-right: -1px; - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} -.tabs-left > .nav-tabs > li > a:hover { - border-color: #eeeeee #dddddd #eeeeee #eeeeee; -} -.tabs-left > .nav-tabs .active > a, -.tabs-left > .nav-tabs .active > a:hover { - border-color: #ddd transparent #ddd #ddd; - *border-right-color: #ffffff; -} -.tabs-right > .nav-tabs { - float: right; - margin-left: 19px; - border-left: 1px solid #ddd; -} -.tabs-right > .nav-tabs > li > a { - margin-left: -1px; - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} -.tabs-right > .nav-tabs > li > a:hover { - border-color: #eeeeee #eeeeee #eeeeee #dddddd; -} -.tabs-right > .nav-tabs .active > a, -.tabs-right > .nav-tabs .active > a:hover { - border-color: #ddd #ddd #ddd transparent; - *border-left-color: #ffffff; -} -.navbar { - *position: relative; - *z-index: 2; - margin-bottom: 18px; - overflow: visible; -} -.navbar-inner { - min-height: 40px; - padding-right: 20px; - padding-left: 20px; - background-color: #2c2c2c; - background-image: -moz-linear-gradient(top, #333333, #222222); - background-image: -ms-linear-gradient(top, #333333, #222222); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222)); - background-image: -webkit-linear-gradient(top, #333333, #222222); - background-image: -o-linear-gradient(top, #333333, #222222); - background-image: linear-gradient(top, #333333, #222222); - background-repeat: repeat-x; - - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); -} -.navbar .container { - width: auto; -} -.nav-collapse.collapse { - height: auto; -} -.navbar { - color: #999999; -} -.navbar .brand:hover { - text-decoration: none; -} -.navbar .brand { - display: block; - float: left; - padding: 8px 20px 12px; - margin-left: -20px; - font-size: 20px; - font-weight: 200; - line-height: 1; - color: #999999; -} -.navbar .navbar-text { - margin-bottom: 0; - line-height: 40px; -} -.navbar .navbar-link { - color: #999999; -} -.navbar .navbar-link:hover { - color: #ffffff; -} -.navbar .btn, -.navbar .btn-group { - margin-top: 5px; -} -.navbar .btn-group .btn { - margin: 0; -} -.navbar-form { - margin-bottom: 0; - *zoom: 1; -} -.navbar-form:before, -.navbar-form:after { - display: table; - content: ""; -} -.navbar-form:after { - clear: both; -} -.navbar-form input, -.navbar-form select, -.navbar-form .radio, -.navbar-form .checkbox { - margin-top: 5px; -} -.navbar-form input, -.navbar-form select { - display: inline-block; - margin-bottom: 0; -} -.navbar-form input[type="image"], -.navbar-form input[type="checkbox"], -.navbar-form input[type="radio"] { - margin-top: 3px; -} -.navbar-form .input-append, -.navbar-form .input-prepend { - margin-top: 6px; - white-space: nowrap; -} -.navbar-form .input-append input, -.navbar-form .input-prepend input { - margin-top: 0; -} -.navbar-search { - position: relative; - float: left; - margin-top: 6px; - margin-bottom: 0; -} -.navbar-search .search-query { - padding: 4px 9px; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 13px; - font-weight: normal; - line-height: 1; - color: #ffffff; - background-color: #626262; - border: 1px solid #151515; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - -webkit-transition: none; - -moz-transition: none; - -ms-transition: none; - -o-transition: none; - transition: none; -} -.navbar-search .search-query:-moz-placeholder { - color: #cccccc; -} -.navbar-search .search-query:-ms-input-placeholder { - color: #cccccc; -} -.navbar-search .search-query::-webkit-input-placeholder { - color: #cccccc; -} -.navbar-search .search-query:focus, -.navbar-search .search-query.focused { - padding: 5px 10px; - color: #333333; - text-shadow: 0 1px 0 #ffffff; - background-color: #ffffff; - border: 0; - outline: 0; - -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); - -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); - box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); -} -.navbar-fixed-top, -.navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - z-index: 1030; - margin-bottom: 0; -} -.navbar-fixed-top .navbar-inner, -.navbar-fixed-bottom .navbar-inner { - padding-right: 0; - padding-left: 0; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} -.navbar-fixed-top .container, -.navbar-fixed-bottom .container { - width: 940px; -} -.navbar-fixed-top { - top: 0; -} -.navbar-fixed-bottom { - bottom: 0; -} -.navbar .nav { - position: relative; - left: 0; - display: block; - float: left; - margin: 0 10px 0 0; -} -.navbar .nav.pull-right { - float: right; -} -.navbar .nav > li { - display: block; - float: left; -} -.navbar .nav > li > a { - float: none; - padding: 9px 10px 11px; - line-height: 19px; - color: #999999; - text-decoration: none; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); -} -.navbar .btn { - display: inline-block; - padding: 4px 10px 4px; - margin: 5px 5px 6px; - line-height: 18px; -} -.navbar .btn-group { - padding: 5px 5px 6px; - margin: 0; -} -.navbar .nav > li > a:hover { - color: #ffffff; - text-decoration: none; - background-color: transparent; -} -.navbar .nav .active > a, -.navbar .nav .active > a:hover { - color: #ffffff; - text-decoration: none; - background-color: #222222; -} -.navbar .divider-vertical { - width: 1px; - height: 40px; - margin: 0 9px; - overflow: hidden; - background-color: #222222; - border-right: 1px solid #333333; -} -.navbar .nav.pull-right { - margin-right: 0; - margin-left: 10px; -} -.navbar .btn-navbar { - display: none; - float: right; - padding: 7px 10px; - margin-right: 5px; - margin-left: 5px; - background-color: #2c2c2c; - *background-color: #222222; - background-image: -ms-linear-gradient(top, #333333, #222222); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222)); - background-image: -webkit-linear-gradient(top, #333333, #222222); - background-image: -o-linear-gradient(top, #333333, #222222); - background-image: linear-gradient(top, #333333, #222222); - background-image: -moz-linear-gradient(top, #333333, #222222); - background-repeat: repeat-x; - border-color: #222222 #222222 #000000; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); - filter: progid:dximagetransform.microsoft.gradient(enabled=false); - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); -} -.navbar .btn-navbar:hover, -.navbar .btn-navbar:active, -.navbar .btn-navbar.active, -.navbar .btn-navbar.disabled, -.navbar .btn-navbar[disabled] { - background-color: #222222; - *background-color: #151515; -} -.navbar .btn-navbar:active, -.navbar .btn-navbar.active { - background-color: #080808 \9; -} -.navbar .btn-navbar .icon-bar { - display: block; - width: 18px; - height: 2px; - background-color: #f5f5f5; - -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; - -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); - -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); -} -.btn-navbar .icon-bar + .icon-bar { - margin-top: 3px; -} -.navbar .dropdown-menu:before { - position: absolute; - top: -7px; - left: 9px; - display: inline-block; - border-right: 7px solid transparent; - border-bottom: 7px solid #ccc; - border-left: 7px solid transparent; - border-bottom-color: rgba(0, 0, 0, 0.2); - content: ''; -} -.navbar .dropdown-menu:after { - position: absolute; - top: -6px; - left: 10px; - display: inline-block; - border-right: 6px solid transparent; - border-bottom: 6px solid #ffffff; - border-left: 6px solid transparent; - content: ''; -} -.navbar-fixed-bottom .dropdown-menu:before { - top: auto; - bottom: -7px; - border-top: 7px solid #ccc; - border-bottom: 0; - border-top-color: rgba(0, 0, 0, 0.2); -} -.navbar-fixed-bottom .dropdown-menu:after { - top: auto; - bottom: -6px; - border-top: 6px solid #ffffff; - border-bottom: 0; -} -.navbar .nav li.dropdown .dropdown-toggle .caret, -.navbar .nav li.dropdown.open .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} -.navbar .nav li.dropdown.active .caret { - opacity: 1; - filter: alpha(opacity=100); -} -.navbar .nav li.dropdown.open > .dropdown-toggle, -.navbar .nav li.dropdown.active > .dropdown-toggle, -.navbar .nav li.dropdown.open.active > .dropdown-toggle { - background-color: transparent; -} -.navbar .nav li.dropdown.active > .dropdown-toggle:hover { - color: #ffffff; -} -.navbar .pull-right .dropdown-menu, -.navbar .dropdown-menu.pull-right { - right: 0; - left: auto; -} -.navbar .pull-right .dropdown-menu:before, -.navbar .dropdown-menu.pull-right:before { - right: 12px; - left: auto; -} -.navbar .pull-right .dropdown-menu:after, -.navbar .dropdown-menu.pull-right:after { - right: 13px; - left: auto; -} -.breadcrumb { - padding: 7px 14px; - margin: 0 0 18px; - list-style: none; - background-color: #fbfbfb; - background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5); - background-image: -ms-linear-gradient(top, #ffffff, #f5f5f5); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f5f5f5)); - background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5); - background-image: -o-linear-gradient(top, #ffffff, #f5f5f5); - background-image: linear-gradient(top, #ffffff, #f5f5f5); - background-repeat: repeat-x; - border: 1px solid #ddd; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0); - -webkit-box-shadow: inset 0 1px 0 #ffffff; - -moz-box-shadow: inset 0 1px 0 #ffffff; - box-shadow: inset 0 1px 0 #ffffff; -} -.breadcrumb li { - display: inline-block; - *display: inline; - text-shadow: 0 1px 0 #ffffff; - *zoom: 1; -} -.breadcrumb .divider { - padding: 0 5px; - color: #999999; -} -.breadcrumb .active a { - color: #333333; -} -.pagination { - height: 36px; - margin: 18px 0; -} -.pagination ul { - display: inline-block; - *display: inline; - margin-bottom: 0; - margin-left: 0; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - *zoom: 1; - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); -} -.pagination li { - display: inline; -} -.pagination a { - float: left; - padding: 0 14px; - line-height: 34px; - text-decoration: none; - border: 1px solid #ddd; - border-left-width: 0; -} -.pagination a:hover, -.pagination .active a { - background-color: #f5f5f5; -} -.pagination .active a { - color: #999999; - cursor: default; -} -.pagination .disabled span, -.pagination .disabled a, -.pagination .disabled a:hover { - color: #999999; - cursor: default; - background-color: transparent; -} -.pagination li:first-child a { - border-left-width: 1px; - -webkit-border-radius: 3px 0 0 3px; - -moz-border-radius: 3px 0 0 3px; - border-radius: 3px 0 0 3px; -} -.pagination li:last-child a { - -webkit-border-radius: 0 3px 3px 0; - -moz-border-radius: 0 3px 3px 0; - border-radius: 0 3px 3px 0; -} -.pagination-centered { - text-align: center; -} -.pagination-right { - text-align: right; -} -.pager { - margin-bottom: 18px; - margin-left: 0; - text-align: center; - list-style: none; - *zoom: 1; -} -.pager:before, -.pager:after { - display: table; - content: ""; -} -.pager:after { - clear: both; -} -.pager li { - display: inline; -} -.pager a { - display: inline-block; - padding: 5px 14px; - background-color: #fff; - border: 1px solid #ddd; - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; -} -.pager a:hover { - text-decoration: none; - background-color: #f5f5f5; -} -.pager .next a { - float: right; -} -.pager .previous a { - float: left; -} -.pager .disabled a, -.pager .disabled a:hover { - color: #999999; - cursor: default; - background-color: #fff; -} -.modal-open .dropdown-menu { - z-index: 2050; -} -.modal-open .dropdown.open { - *z-index: 2050; -} -.modal-open .popover { - z-index: 2060; -} -.modal-open .tooltip { - z-index: 2070; -} -.modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - background-color: #000000; -} -.modal-backdrop.fade { - opacity: 0; -} -.modal-backdrop, -.modal-backdrop.fade.in { - opacity: 0.8; - filter: alpha(opacity=80); -} -.modal { - position: fixed; - top: 50%; - left: 50%; - z-index: 1050; - width: 560px; - margin: -250px 0 0 -280px; - overflow: auto; - background-color: #ffffff; - border: 1px solid #999; - border: 1px solid rgba(0, 0, 0, 0.3); - *border: 1px solid #999; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -webkit-background-clip: padding-box; - -moz-background-clip: padding-box; - background-clip: padding-box; -} -.modal.fade { - top: -25%; - -webkit-transition: opacity 0.3s linear, top 0.3s ease-out; - -moz-transition: opacity 0.3s linear, top 0.3s ease-out; - -ms-transition: opacity 0.3s linear, top 0.3s ease-out; - -o-transition: opacity 0.3s linear, top 0.3s ease-out; - transition: opacity 0.3s linear, top 0.3s ease-out; -} -.modal.fade.in { - top: 50%; -} -.modal-header { - padding: 9px 15px; - border-bottom: 1px solid #eee; -} -.modal-header .close { - margin-top: 2px; -} -.modal-body { - max-height: 400px; - padding: 15px; - overflow-y: auto; -} -.modal-form { - margin-bottom: 0; -} -.modal-footer { - padding: 14px 15px 15px; - margin-bottom: 0; - text-align: right; - background-color: #f5f5f5; - border-top: 1px solid #ddd; - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; - *zoom: 1; - -webkit-box-shadow: inset 0 1px 0 #ffffff; - -moz-box-shadow: inset 0 1px 0 #ffffff; - box-shadow: inset 0 1px 0 #ffffff; -} -.modal-footer:before, -.modal-footer:after { - display: table; - content: ""; -} -.modal-footer:after { - clear: both; -} -.modal-footer .btn + .btn { - margin-bottom: 0; - margin-left: 5px; -} -.modal-footer .btn-group .btn + .btn { - margin-left: -1px; -} -.tooltip { - position: absolute; - z-index: 1020; - display: block; - padding: 5px; - font-size: 11px; - opacity: 0; - filter: alpha(opacity=0); - visibility: visible; -} -.tooltip.in { - opacity: 0.8; - filter: alpha(opacity=80); -} -.tooltip.top { - margin-top: -2px; -} -.tooltip.right { - margin-left: 2px; -} -.tooltip.bottom { - margin-top: 2px; -} -.tooltip.left { - margin-left: -2px; -} -.tooltip.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-top: 5px solid #000000; - border-right: 5px solid transparent; - border-left: 5px solid transparent; -} -.tooltip.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-top: 5px solid transparent; - border-bottom: 5px solid transparent; - border-left: 5px solid #000000; -} -.tooltip.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-right: 5px solid transparent; - border-bottom: 5px solid #000000; - border-left: 5px solid transparent; -} -.tooltip.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-top: 5px solid transparent; - border-right: 5px solid #000000; - border-bottom: 5px solid transparent; -} -.tooltip-inner { - max-width: 200px; - padding: 3px 8px; - color: #ffffff; - text-align: center; - text-decoration: none; - background-color: #000000; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; -} -.popover { - position: absolute; - top: 0; - left: 0; - z-index: 1010; - display: none; - padding: 5px; -} -.popover.top { - margin-top: -5px; -} -.popover.right { - margin-left: 5px; -} -.popover.bottom { - margin-top: 5px; -} -.popover.left { - margin-left: -5px; -} -.popover.top .arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-top: 5px solid #000000; - border-right: 5px solid transparent; - border-left: 5px solid transparent; -} -.popover.right .arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-top: 5px solid transparent; - border-right: 5px solid #000000; - border-bottom: 5px solid transparent; -} -.popover.bottom .arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-right: 5px solid transparent; - border-bottom: 5px solid #000000; - border-left: 5px solid transparent; -} -.popover.left .arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-top: 5px solid transparent; - border-bottom: 5px solid transparent; - border-left: 5px solid #000000; -} -.popover .arrow { - position: absolute; - width: 0; - height: 0; -} -.popover-inner { - width: 280px; - padding: 3px; - overflow: hidden; - background: #000000; - background: rgba(0, 0, 0, 0.8); - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); -} -.popover-title { - padding: 9px 15px; - line-height: 1; - background-color: #f5f5f5; - border-bottom: 1px solid #eee; - -webkit-border-radius: 3px 3px 0 0; - -moz-border-radius: 3px 3px 0 0; - border-radius: 3px 3px 0 0; -} -.popover-content { - padding: 14px; - background-color: #ffffff; - -webkit-border-radius: 0 0 3px 3px; - -moz-border-radius: 0 0 3px 3px; - border-radius: 0 0 3px 3px; - -webkit-background-clip: padding-box; - -moz-background-clip: padding-box; - background-clip: padding-box; -} -.popover-content p, -.popover-content ul, -.popover-content ol { - margin-bottom: 0; -} -.thumbnails { - margin-left: -20px; - list-style: none; - *zoom: 1; -} -.thumbnails:before, -.thumbnails:after { - display: table; - content: ""; -} -.thumbnails:after { - clear: both; -} -.row-fluid .thumbnails { - margin-left: 0; -} -.thumbnails > li { - float: left; - margin-bottom: 18px; - margin-left: 20px; -} -.thumbnail { - display: block; - padding: 4px; - line-height: 1; - border: 1px solid #ddd; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); -} -a.thumbnail:hover { - border-color: #0088cc; - -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); - -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); - box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); -} -.thumbnail > img { - display: block; - max-width: 100%; - margin-right: auto; - margin-left: auto; -} -.thumbnail .caption { - padding: 9px; -} -.label, -.badge { - font-size: 10.998px; - font-weight: bold; - line-height: 14px; - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - white-space: nowrap; - vertical-align: baseline; - background-color: #999999; -} -.label { - padding: 1px 4px 2px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} -.badge-method-type { - border-radius: 0 !important; - width: 47px; -text-align: center; - line-height: 20px; - font-weight: normal; -} -.badge { - padding: 1px 9px 2px; - -webkit-border-radius: 9px; - -moz-border-radius: 9px; - border-radius: 9px; -} -a.label:hover, -a.badge:hover { - color: #ffffff; - text-decoration: none; - cursor: pointer; -} -.label-important, -.badge-important { - background-color: #b94a48; -} -.badge-DELETE, -.label-important[href], -.badge-important[href] { - background-color: #953b39; -} -.label-warning, -.badge-warning { - background-color: #f89406; -} -.badge-PUT, -.label-warning[href], -.badge-warning[href] { - background-color: #c67605; -} -.badge-POST, -.label-success, -.badge-success { - background-color: #468847; -} -.label-success[href], -.badge-success[href] { - background-color: #356635; -} -.badge-GET, -.label-info, -.badge-info { - background-color: #3a87ad; -} -.label-info[href], -.badge-info[href] { - background-color: #2d6987; -} -.label-inverse, -.badge-inverse { - background-color: #333333; -} -.label-inverse[href], -.badge-inverse[href] { - background-color: #1a1a1a; -} -@-webkit-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -@-moz-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -@-ms-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -@-o-keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} -@keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -.progress { - height: 18px; - margin-bottom: 18px; - overflow: hidden; - background-color: #f7f7f7; - background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: -ms-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); - background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: linear-gradient(top, #f5f5f5, #f9f9f9); - background-repeat: repeat-x; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#f5f5f5', endColorstr='#f9f9f9', GradientType=0); - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -} -.progress .bar { - width: 0; - height: 18px; - font-size: 12px; - color: #ffffff; - text-align: center; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #0e90d2; - background-image: -moz-linear-gradient(top, #149bdf, #0480be); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); - background-image: -webkit-linear-gradient(top, #149bdf, #0480be); - background-image: -o-linear-gradient(top, #149bdf, #0480be); - background-image: linear-gradient(top, #149bdf, #0480be); - background-image: -ms-linear-gradient(top, #149bdf, #0480be); - background-repeat: repeat-x; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#149bdf', endColorstr='#0480be', GradientType=0); - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; - -webkit-transition: width 0.6s ease; - -moz-transition: width 0.6s ease; - -ms-transition: width 0.6s ease; - -o-transition: width 0.6s ease; - transition: width 0.6s ease; -} -.progress-striped .bar { - background-color: #149bdf; - background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - -webkit-background-size: 40px 40px; - -moz-background-size: 40px 40px; - -o-background-size: 40px 40px; - background-size: 40px 40px; -} -.progress.active .bar { - -webkit-animation: progress-bar-stripes 2s linear infinite; - -moz-animation: progress-bar-stripes 2s linear infinite; - -ms-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; -} -.progress-danger .bar { - background-color: #dd514c; - background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); - background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); - background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); - background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); - background-image: linear-gradient(top, #ee5f5b, #c43c35); - background-repeat: repeat-x; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0); -} -.progress-danger.progress-striped .bar { - background-color: #ee5f5b; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} -.progress-success .bar { - background-color: #5eb95e; - background-image: -moz-linear-gradient(top, #62c462, #57a957); - background-image: -ms-linear-gradient(top, #62c462, #57a957); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); - background-image: -webkit-linear-gradient(top, #62c462, #57a957); - background-image: -o-linear-gradient(top, #62c462, #57a957); - background-image: linear-gradient(top, #62c462, #57a957); - background-repeat: repeat-x; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0); -} -.progress-success.progress-striped .bar { - background-color: #62c462; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} -.progress-info .bar { - background-color: #4bb1cf; - background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); - background-image: -ms-linear-gradient(top, #5bc0de, #339bb9); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); - background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); - background-image: -o-linear-gradient(top, #5bc0de, #339bb9); - background-image: linear-gradient(top, #5bc0de, #339bb9); - background-repeat: repeat-x; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0); -} -.progress-info.progress-striped .bar { - background-color: #5bc0de; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} -.progress-warning .bar { - background-color: #faa732; - background-image: -moz-linear-gradient(top, #fbb450, #f89406); - background-image: -ms-linear-gradient(top, #fbb450, #f89406); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); - background-image: -webkit-linear-gradient(top, #fbb450, #f89406); - background-image: -o-linear-gradient(top, #fbb450, #f89406); - background-image: linear-gradient(top, #fbb450, #f89406); - background-repeat: repeat-x; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0); -} -.progress-warning.progress-striped .bar { - background-color: #fbb450; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} -.accordion { - margin-bottom: 18px; -} -.accordion-group { - margin-bottom: 2px; - border: 1px solid #e5e5e5; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -.accordion-heading { - border-bottom: 0; -} -.accordion-heading .accordion-toggle { - display: block; - padding: 8px 15px; -} -.accordion-toggle { - cursor: pointer; -} -.accordion-inner { - padding: 9px 15px; - border-top: 1px solid #e5e5e5; -} -.carousel { - position: relative; - margin-bottom: 18px; - line-height: 1; -} -.carousel-inner { - position: relative; - width: 100%; - overflow: hidden; -} -.carousel .item { - position: relative; - display: none; - -webkit-transition: 0.6s ease-in-out left; - -moz-transition: 0.6s ease-in-out left; - -ms-transition: 0.6s ease-in-out left; - -o-transition: 0.6s ease-in-out left; - transition: 0.6s ease-in-out left; -} -.carousel .item > img { - display: block; - line-height: 1; -} -.carousel .active, -.carousel .next, -.carousel .prev { - display: block; -} -.carousel .active { - left: 0; -} -.carousel .next, -.carousel .prev { - position: absolute; - top: 0; - width: 100%; -} -.carousel .next { - left: 100%; -} -.carousel .prev { - left: -100%; -} -.carousel .next.left, -.carousel .prev.right { - left: 0; -} -.carousel .active.left { - left: -100%; -} -.carousel .active.right { - left: 100%; -} -.carousel-control { - position: absolute; - top: 40%; - left: 15px; - width: 40px; - height: 40px; - margin-top: -20px; - font-size: 60px; - font-weight: 100; - line-height: 30px; - color: #ffffff; - text-align: center; - background: #222222; - border: 3px solid #ffffff; - -webkit-border-radius: 23px; - -moz-border-radius: 23px; - border-radius: 23px; - opacity: 0.5; - filter: alpha(opacity=50); -} -.carousel-control.right { - right: 15px; - left: auto; -} -.carousel-control:hover { - color: #ffffff; - text-decoration: none; - opacity: 0.9; - filter: alpha(opacity=90); -} -.carousel-caption { - position: absolute; - right: 0; - bottom: 0; - left: 0; - padding: 10px 15px 5px; - background: #333333; - background: rgba(0, 0, 0, 0.75); -} -.carousel-caption h4, -.carousel-caption p { - color: #ffffff; -} -.hero-unit { - padding: 60px; - margin-bottom: 30px; - background-color: #eeeeee; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} -.btn-superlarge { - font-size: 20px; - font-weight: normal; - padding: 14px 24px; - margin-right: 10px; - -webkit-border-radius: 6px; - border-radius: 6px; -} -.hero-unit h1 { - margin-bottom: 0; - font-size: 60px; - line-height: 1; - letter-spacing: -1px; - color: inherit; -} -.hero-unit p { - font-size: 18px; - font-weight: 200; - line-height: 27px; - color: inherit; -} -.pull-right { - float: right; -} -.pull-left { - float: left; -} -.hide { - display: none; -} -.show { - display: block; -} -.invisible { - visibility: hidden; -} -html { - overflow-y: scroll; -} -.autoresize { - width: 400px; - min-height: 120px; - max-height: 300px; - _height: 120px; - margin-left: auto; - margin-right: auto; - padding: 3px; - outline: 0; - border: 1px solid #a0b3d6; - font-size: 12px; - word-wrap: break-word; - overflow-x: hidden; - overflow-y: auto; -} -.logo { - width: 257px; - height: 257px; - background-size: 257px; - background: url(../img/logo.jpg) no-repeat; -} -/* -github.com style (c) Vasily Polovnyov -*/ -pre code { - display: block; padding: 0.5em; - color: #000; - background: #f8f8ff -} -pre .comment, -pre .template_comment, -pre .diff .header, -pre .javadoc { - color: #998; - font-style: italic -} -pre .keyword, -pre .css .rule .keyword, -pre .winutils, -pre .javascript .title, -pre .lisp .title, -pre .nginx .title, -pre .subst, -pre .request, -pre .status { - color: #000; - font-weight: bold -} -pre .number, -pre .hexcolor { - color: #40a070 -} -pre .string, -pre .tag .value, -pre .phpdoc, -pre .tex .formula { - color: #d14 -} -pre .title, -pre .id { - color: #900; - font-weight: bold -} -pre .javascript .title, -pre .lisp .title, -pre .subst { - font-weight: normal -} -pre .class .title, -pre .haskell .type, -pre .vhdl .literal, -pre .tex .command { - color: #458; - font-weight: bold -} -pre .tag, -pre .tag .title, -pre .rules .property, -pre .django .tag .keyword { - color: #000080; - font-weight: normal -} -pre .attribute, -pre .variable, -pre .instancevar, -pre .lisp .body { - color: #008080 -} -pre .regexp { - color: #009926 -} -pre .class { - color: #458; - font-weight: bold -} -pre .symbol, -pre .ruby .symbol .string, -pre .ruby .symbol .keyword, -pre .ruby .symbol .keymethods, -pre .lisp .keyword, -pre .tex .special, -pre .input_number { - color: #990073 -} -pre .builtin, -pre .built_in, -pre .lisp .title { - color: #0086b3 -} -pre .preprocessor, -pre .pi, -pre .doctype, -pre .shebang, -pre .cdata { - color: #999; - font-weight: bold -} -pre .deletion { - background: #fdd -} -pre .addition { - background: #dfd -} -pre .diff .change { - background: #0086b3 -} -pre .chunk { - color: #aaa -} -pre .tex .formula { - opacity: 0.5; -} -.jsoneditor-field, .jsoneditor-value, .jsoneditor-field-readonly, .jsoneditor-readonly { - border: 1px solid transparent; - min-height: 16px; - min-width: 24px; - padding: 2px; - margin: 1px; - outline: none; -} -.jsoneditor-empty { - background-color: #E5E5E5; -} -.jsoneditor-separator { - padding: 3px 0px; - vertical-align: top; -} -.jsoneditor-value:focus, .jsoneditor-field:focus, - .jsoneditor-value:hover, .jsoneditor-field:hover { - background-color: #FFFFAB; - border: 1px solid lightgray; - border: 1px solid yellow; -} -.jsoneditor-field-readonly:hover { - border: 1px solid white; -} -.jsoneditor-readonly { - color: gray; -} -button.jsoneditor-collapsed { - background: url(img/treeRightTriangleBlack.png) no-repeat center; -} -button.jsoneditor-expanded { - background: url(img/treeDownTriangleBlack.png) no-repeat center; -} -button.jsoneditor-invisible { - visibility: hidden; - background: none; -} -button.jsoneditor-remove, button.jsoneditor-append, button.jsoneditor-duplicate, - button.jsoneditor-collapsed, button.jsoneditor-expanded, - button.jsoneditor-invisible, button.jsoneditor-dragarea, - button.jsoneditor-type-auto, button.jsoneditor-type-string, - button.jsoneditor-type-array, button.jsoneditor-type-object { - width: 24px; - height: 24px; - padding: 0px; - margin: 0px; - border: none; - cursor: pointer; -} -button.jsoneditor-collapsed, button.jsoneditor-expanded, - button.jsoneditor-invisible { - float: left; -} -button.jsoneditor-remove { - background: url(img/delete_gray.png) no-repeat center; -} -button.jsoneditor-remove:hover { - background: url(img/delete_red.png) no-repeat center; -} -button.jsoneditor-append { - background: url(img/add_gray.png) no-repeat center; -} -button.jsoneditor-append:hover { - background: url(img/add_green.png) no-repeat center; -} -button.jsoneditor-duplicate { - background: url(img/duplicate_gray.png) no-repeat center; -} -button.jsoneditor-duplicate:hover { - background: url(img/duplicate_blue.png) no-repeat center; -} -button.jsoneditor-type-string { - background: url(img/string_gray.png) no-repeat center; -} -button.jsoneditor-type-string:hover { - background: url(img/string_blue.png) no-repeat center; -} -button.jsoneditor-type-auto { - background: url(img/auto_gray.png) no-repeat center; -} -button.jsoneditor-type-auto:hover { - background: url(img/auto_blue.png) no-repeat center; -} -button.jsoneditor-type-object { - background: url(img/object_gray.png) no-repeat center; -} -button.jsoneditor-type-object:hover { - background: url(img/object_blue.png) no-repeat center; -} -button.jsoneditor-type-array { - background: url(img/array_gray.png) no-repeat center; -} -button.jsoneditor-type-array:hover { - background: url(img/array_blue.png) no-repeat center; -} -div.jsoneditor-select { - border: 1px solid gray; - background-color: white; - box-shadow: 4px 4px 10px lightgray; -} -div.jsoneditor-option { - color: #4D4D4D; - background-color: white; - border: none; - margin: 0px; - display: block; - text-align: left; - cursor: pointer; -} -div.jsoneditor-option:hover { - background-color: #FFFFAB; - color: black; -} -div.jsoneditor-option-string, div.jsoneditor-option-auto, - div.jsoneditor-option-object, div.jsoneditor-option-array { - padding: 4px 12px 4px 24px; - background-repeat:no-repeat; - background-position: 4px center; -} -div.jsoneditor-option-string { - background-image: url(img/string_blue.png); -} -div.jsoneditor-option-auto { - background-image: url(img/auto_blue.png); -} -div.jsoneditor-option-object { - background-image: url(img/object_blue.png); -} -div.jsoneditor-option-array { - background-image: url(img/array_blue.png); -} -div.jsoneditor-option-selected { - background-color: #D5DDF6; -} -div.jsoneditor-frame { - color: #1A1A1A; - border: 1px solid #97B0F8; - width: 100%; - height: 100%; - overflow: auto; - position: relative; -} -table.jsoneditor-table { - border-collapse: collapse; - border-spacing: 0px; - width: 100%; -} -div.jsoneditor-content-outer, div.jsonformatter-content { - width: 100%; - height: 100%; - margin: -32px 0px 0px 0px; - padding: 32px 0px 0px 0px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; - - overflow: hidden; -} -div.jsoneditor-content { - width: 100%; - height: 100%; - position: relative; - overflow: auto; -} -textarea.jsonformatter-textarea { - width: 100%; - height: 100%; - margin: 0px; - - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; - - border: none; - background-color: white; - resize: none; -} -tr.jsoneditor-tr-highlight { - background-color: #FFFFAB; -} -button.jsoneditor-dragarea { - width: 16px; - height: 16px; - margin: 3px 0px; - background: url(img/dots_gray.gif) top center; - background-repeat: repeat-y; - display: block; - cursor: move; -} -table.jsoneditor-menu { - width: 100%; - height: 32px; - left: 0px; - top: 0px; - border-collapse: collapse; -} -td.jsoneditor-menu { - font-weight: bold; - background-color: #D5DDF6; - border-bottom: 1px solid #97B0F8; - text-align: left; - padding: 0px 3px; -} -tr, th, td { - padding: 0px; - margin: 0px; -} -td.jsoneditor-td { - vertical-align: middle; - vertical-align: top; -} -td.jsoneditor-td { - padding: 0px 3px; -} -td.jsoneditor-td-edit { - background-color: #F5F5F5; - padding: 0px; -} -td.jsoneditor-td-tree { - vertical-align: top; -} -td.jsoneditor-droparea { - height: 24px; - border-top: 1px dashed gray; - border-bottom: 1px dashed gray; - background-color: #FFFF80; -} -.jsoneditor-field, .jsoneditor-value, .jsoneditor-td, .jsoneditor-th, - .jsoneditor-type, - .jsonformatter-textarea { - font-family: droid sans mono, monospace, courier new, courier; - font-size: 10pt; -} diff --git a/build/almond.js b/build/almond.js deleted file mode 100644 index f530767..0000000 --- a/build/almond.js +++ /dev/null @@ -1,314 +0,0 @@ -/** - * almond 0.1.1 Copyright (c) 2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/almond for details - */ -//Going sloppy to avoid 'use strict' string cost, but strict practices should -//be followed. -/*jslint sloppy: true */ -/*global setTimeout: false */ - -var requirejs, require, define; -(function (undef) { - var defined = {}, - waiting = {}, - config = {}, - defining = {}, - aps = [].slice, - main, req; - - /** - * Given a relative module name, like ./something, normalize it to - * a real name that can be mapped to a path. - * @param {String} name the relative name - * @param {String} baseName a real name that the name arg is relative - * to. - * @returns {String} normalized name - */ - function normalize(name, baseName) { - var baseParts = baseName && baseName.split("/"), - map = config.map, - starMap = (map && map['*']) || {}, - nameParts, nameSegment, mapValue, foundMap, i, j, part; - - //Adjust any relative paths. - if (name && name.charAt(0) === ".") { - //If have a base name, try to normalize against it, - //otherwise, assume it is a top-level require that will - //be relative to baseUrl in the end. - if (baseName) { - //Convert baseName to array, and lop off the last part, - //so that . matches that "directory" and not name of the baseName's - //module. For instance, baseName of "one/two/three", maps to - //"one/two/three.js", but we want the directory, "one/two" for - //this normalization. - baseParts = baseParts.slice(0, baseParts.length - 1); - - name = baseParts.concat(name.split("/")); - - //start trimDots - for (i = 0; (part = name[i]); i++) { - if (part === ".") { - name.splice(i, 1); - i -= 1; - } else if (part === "..") { - if (i === 1 && (name[2] === '..' || name[0] === '..')) { - //End of the line. Keep at least one non-dot - //path segment at the front so it can be mapped - //correctly to disk. Otherwise, there is likely - //no path mapping for a path starting with '..'. - //This can still fail, but catches the most reasonable - //uses of .. - return true; - } else if (i > 0) { - name.splice(i - 1, 2); - i -= 2; - } - } - } - //end trimDots - - name = name.join("/"); - } - } - - //Apply map config if available. - if ((baseParts || starMap) && map) { - nameParts = name.split('/'); - - for (i = nameParts.length; i > 0; i -= 1) { - nameSegment = nameParts.slice(0, i).join("/"); - - if (baseParts) { - //Find the longest baseName segment match in the config. - //So, do joins on the biggest to smallest lengths of baseParts. - for (j = baseParts.length; j > 0; j -= 1) { - mapValue = map[baseParts.slice(0, j).join('/')]; - - //baseName segment has config, find if it has one for - //this name. - if (mapValue) { - mapValue = mapValue[nameSegment]; - if (mapValue) { - //Match, update name to the new value. - foundMap = mapValue; - break; - } - } - } - } - - foundMap = foundMap || starMap[nameSegment]; - - if (foundMap) { - nameParts.splice(0, i, foundMap); - name = nameParts.join('/'); - break; - } - } - } - - return name; - } - - function makeRequire(relName, forceSync) { - return function () { - //A version of a require function that passes a moduleName - //value for items that may need to - //look up paths relative to the moduleName - return req.apply(undef, aps.call(arguments, 0).concat([relName, forceSync])); - }; - } - - function makeNormalize(relName) { - return function (name) { - return normalize(name, relName); - }; - } - - function makeLoad(depName) { - return function (value) { - defined[depName] = value; - }; - } - - function callDep(name) { - if (waiting.hasOwnProperty(name)) { - var args = waiting[name]; - delete waiting[name]; - defining[name] = true; - main.apply(undef, args); - } - - if (!defined.hasOwnProperty(name)) { - throw new Error('No ' + name); - } - return defined[name]; - } - - /** - * Makes a name map, normalizing the name, and using a plugin - * for normalization if necessary. Grabs a ref to plugin - * too, as an optimization. - */ - function makeMap(name, relName) { - var prefix, plugin, - index = name.indexOf('!'); - - if (index !== -1) { - prefix = normalize(name.slice(0, index), relName); - name = name.slice(index + 1); - plugin = callDep(prefix); - - //Normalize according - if (plugin && plugin.normalize) { - name = plugin.normalize(name, makeNormalize(relName)); - } else { - name = normalize(name, relName); - } - } else { - name = normalize(name, relName); - } - - //Using ridiculous property names for space reasons - return { - f: prefix ? prefix + '!' + name : name, //fullName - n: name, - p: plugin - }; - } - - function makeConfig(name) { - return function () { - return (config && config.config && config.config[name]) || {}; - }; - } - - main = function (name, deps, callback, relName) { - var args = [], - usingExports, - cjsModule, depName, ret, map, i; - - //Use name if no relName - relName = relName || name; - - //Call the callback to define the module, if necessary. - if (typeof callback === 'function') { - - //Pull out the defined dependencies and pass the ordered - //values to the callback. - //Default to [require, exports, module] if no deps - deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps; - for (i = 0; i < deps.length; i++) { - map = makeMap(deps[i], relName); - depName = map.f; - - //Fast path CommonJS standard dependencies. - if (depName === "require") { - args[i] = makeRequire(name); - } else if (depName === "exports") { - //CommonJS module spec 1.1 - args[i] = defined[name] = {}; - usingExports = true; - } else if (depName === "module") { - //CommonJS module spec 1.1 - cjsModule = args[i] = { - id: name, - uri: '', - exports: defined[name], - config: makeConfig(name) - }; - } else if (defined.hasOwnProperty(depName) || waiting.hasOwnProperty(depName)) { - args[i] = callDep(depName); - } else if (map.p) { - map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {}); - args[i] = defined[depName]; - } else if (!defining[depName]) { - throw new Error(name + ' missing ' + depName); - } - } - - ret = callback.apply(defined[name], args); - - if (name) { - //If setting exports via "module" is in play, - //favor that over return value and exports. After that, - //favor a non-undefined return value over exports use. - if (cjsModule && cjsModule.exports !== undef && - cjsModule.exports !== defined[name]) { - defined[name] = cjsModule.exports; - } else if (ret !== undef || !usingExports) { - //Use the return value from the function. - defined[name] = ret; - } - } - } else if (name) { - //May just be an object definition for the module. Only - //worry about defining if have a module name. - defined[name] = callback; - } - }; - - requirejs = require = req = function (deps, callback, relName, forceSync) { - if (typeof deps === "string") { - //Just return the module wanted. In this scenario, the - //deps arg is the module name, and second arg (if passed) - //is just the relName. - //Normalize module name, if it contains . or .. - return callDep(makeMap(deps, callback).f); - } else if (!deps.splice) { - //deps is a config object, not an array. - config = deps; - if (callback.splice) { - //callback is an array, which means it is a dependency list. - //Adjust args if there are dependencies - deps = callback; - callback = relName; - relName = null; - } else { - deps = undef; - } - } - - //Support require(['a']) - callback = callback || function () {}; - - //Simulate async callback; - if (forceSync) { - main(undef, deps, callback, relName); - } else { - setTimeout(function () { - main(undef, deps, callback, relName); - }, 15); - } - - return req; - }; - - /** - * Just drops the config on the floor, but returns req in case - * the config return value is used. - */ - req.config = function (cfg) { - config = cfg; - return req; - }; - - define = function (name, deps, callback) { - - //This module may not have dependencies - if (!deps.splice) { - //deps is not an array, so probably means - //an object literal or factory function for - //the value. Adjust args. - callback = deps; - deps = []; - } - - waiting[name] = [name, deps, callback]; - }; - - define.amd = { - jQuery: true - }; -}()); diff --git a/build/build.js b/build/build.js deleted file mode 100644 index 9919870..0000000 --- a/build/build.js +++ /dev/null @@ -1,10 +0,0 @@ -({ - name: 'almond', - include: ['../js/main'], - baseUrl: '../js', - out: 'output/js/main.js', - findNestedDependencies: true, - mainConfigFile: '../js/main.js', - wrap: true, - insertRequire: ['../js/main'] -}) diff --git a/build/build.sh b/build/build.sh deleted file mode 100755 index e1dac5c..0000000 --- a/build/build.sh +++ /dev/null @@ -1,13 +0,0 @@ -rm -rf output -node r.js -o build.js -mkdir output/js/libs -mkdir output/js/libs/require -cp ../js/libs/require/require.js output/js/libs/require/require.js -cp -r ../css/* output/css -node r.js -o cssIn=../css/styles.css out=output/css/styles.css -mkdir output/img -cp -r ../img output -cp ../index.html output/index.html -sed -i 's/js\/libs\/require\/require.js/js\/main.js/g' output/index.html -sed -i 's/ data-main="js\/main"//g' output/index.html -s3cmd put --recursive --acl-public --add-header=Cache-Control:max-age=604800 output/* s3://apiengine \ No newline at end of file diff --git a/build/r.js b/build/r.js deleted file mode 100644 index e5de2f8..0000000 --- a/build/r.js +++ /dev/null @@ -1,15563 +0,0 @@ -/** - * @license r.js 2.0.4 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 - */ - -/* - * This is a bootstrap script to allow running RequireJS in the command line - * in either a Java/Rhino or Node environment. It is modified by the top-level - * dist.js file to inject other files to completely enable this file. It is - * the shell of the r.js file. - */ - -/*jslint evil: true, nomen: true, sloppy: true */ -/*global readFile: true, process: false, Packages: false, print: false, -console: false, java: false, module: false, requirejsVars */ - -var requirejs, require, define; -(function (console, args, readFileFunc) { - - var fileName, env, fs, vm, path, exec, rhinoContext, dir, nodeRequire, - nodeDefine, exists, reqMain, loadedOptimizedLib, existsForNode, - version = '2.0.4', - jsSuffixRegExp = /\.js$/, - commandOption = '', - useLibLoaded = {}, - //Used by jslib/rhino/args.js - rhinoArgs = args, - readFile = typeof readFileFunc !== 'undefined' ? readFileFunc : null; - - function showHelp() { - console.log('See https://github.com/jrburke/r.js for usage.'); - } - - if (typeof Packages !== 'undefined') { - env = 'rhino'; - - fileName = args[0]; - - if (fileName && fileName.indexOf('-') === 0) { - commandOption = fileName.substring(1); - fileName = args[1]; - } - - //Set up execution context. - rhinoContext = Packages.org.mozilla.javascript.ContextFactory.getGlobal().enterContext(); - - exec = function (string, name) { - return rhinoContext.evaluateString(this, string, name, 0, null); - }; - - exists = function (fileName) { - return (new java.io.File(fileName)).exists(); - }; - - //Define a console.log for easier logging. Don't - //get fancy though. - if (typeof console === 'undefined') { - console = { - log: function () { - print.apply(undefined, arguments); - } - }; - } - } else if (typeof process !== 'undefined') { - env = 'node'; - - //Get the fs module via Node's require before it - //gets replaced. Used in require/node.js - fs = require('fs'); - vm = require('vm'); - path = require('path'); - //In Node 0.7+ existsSync is on fs. - existsForNode = fs.existsSync || path.existsSync; - - nodeRequire = require; - nodeDefine = define; - reqMain = require.main; - - //Temporarily hide require and define to allow require.js to define - //them. - require = undefined; - define = undefined; - - readFile = function (path) { - return fs.readFileSync(path, 'utf8'); - }; - - exec = function (string, name) { - return vm.runInThisContext(this.requirejsVars.require.makeNodeWrapper(string), - name ? fs.realpathSync(name) : ''); - }; - - exists = function (fileName) { - return existsForNode(fileName); - }; - - - fileName = process.argv[2]; - - if (fileName && fileName.indexOf('-') === 0) { - commandOption = fileName.substring(1); - fileName = process.argv[3]; - } - } - - /** vim: et:ts=4:sw=4:sts=4 - * @license RequireJS 2.0.4 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 - */ -/*jslint regexp: true, nomen: true */ -/*global window, navigator, document, importScripts, jQuery, setTimeout, opera */ - - -(function (global) { - 'use strict'; - - var version = '2.0.4', - commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg, - cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g, - jsSuffixRegExp = /\.js$/, - currDirRegExp = /^\.\//, - ostring = Object.prototype.toString, - ap = Array.prototype, - aps = ap.slice, - apsp = ap.splice, - isBrowser = !!(typeof window !== 'undefined' && navigator && document), - isWebWorker = !isBrowser && typeof importScripts !== 'undefined', - //PS3 indicates loaded and complete, but need to wait for complete - //specifically. Sequence is 'loading', 'loaded', execution, - // then 'complete'. The UA check is unfortunate, but not sure how - //to feature test w/o causing perf issues. - readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ? - /^complete$/ : /^(complete|loaded)$/, - defContextName = '_', - //Oh the tragedy, detecting opera. See the usage of isOpera for reason. - isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]', - contexts = {}, - cfg = {}, - globalDefQueue = [], - useInteractive = false, - req, s, head, baseElement, dataMain, src, - interactiveScript, currentlyAddingScript, mainScript, subPath; - - function isFunction(it) { - return ostring.call(it) === '[object Function]'; - } - - function isArray(it) { - return ostring.call(it) === '[object Array]'; - } - - /** - * Helper function for iterating over an array. If the func returns - * a true value, it will break out of the loop. - */ - function each(ary, func) { - if (ary) { - var i; - for (i = 0; i < ary.length; i += 1) { - if (ary[i] && func(ary[i], i, ary)) { - break; - } - } - } - } - - /** - * Helper function for iterating over an array backwards. If the func - * returns a true value, it will break out of the loop. - */ - function eachReverse(ary, func) { - if (ary) { - var i; - for (i = ary.length - 1; i > -1; i -= 1) { - if (ary[i] && func(ary[i], i, ary)) { - break; - } - } - } - } - - function hasProp(obj, prop) { - return obj.hasOwnProperty(prop); - } - - /** - * Cycles over properties in an object and calls a function for each - * property value. If the function returns a truthy value, then the - * iteration is stopped. - */ - function eachProp(obj, func) { - var prop; - for (prop in obj) { - if (obj.hasOwnProperty(prop)) { - if (func(obj[prop], prop)) { - break; - } - } - } - } - - /** - * Simple function to mix in properties from source into target, - * but only if target does not already have a property of the same name. - * This is not robust in IE for transferring methods that match - * Object.prototype names, but the uses of mixin here seem unlikely to - * trigger a problem related to that. - */ - function mixin(target, source, force, deepStringMixin) { - if (source) { - eachProp(source, function (value, prop) { - if (force || !hasProp(target, prop)) { - if (deepStringMixin && typeof value !== 'string') { - if (!target[prop]) { - target[prop] = {}; - } - mixin(target[prop], value, force, deepStringMixin); - } else { - target[prop] = value; - } - } - }); - } - return target; - } - - //Similar to Function.prototype.bind, but the 'this' object is specified - //first, since it is easier to read/figure out what 'this' will be. - function bind(obj, fn) { - return function () { - return fn.apply(obj, arguments); - }; - } - - function scripts() { - return document.getElementsByTagName('script'); - } - - //Allow getting a global that expressed in - //dot notation, like 'a.b.c'. - function getGlobal(value) { - if (!value) { - return value; - } - var g = global; - each(value.split('.'), function (part) { - g = g[part]; - }); - return g; - } - - function makeContextModuleFunc(func, relMap, enableBuildCallback) { - return function () { - //A version of a require function that passes a moduleName - //value for items that may need to - //look up paths relative to the moduleName - var args = aps.call(arguments, 0), lastArg; - if (enableBuildCallback && - isFunction((lastArg = args[args.length - 1]))) { - lastArg.__requireJsBuild = true; - } - args.push(relMap); - return func.apply(null, args); - }; - } - - function addRequireMethods(req, context, relMap) { - each([ - ['toUrl'], - ['undef'], - ['defined', 'requireDefined'], - ['specified', 'requireSpecified'] - ], function (item) { - var prop = item[1] || item[0]; - req[item[0]] = context ? makeContextModuleFunc(context[prop], relMap) : - //If no context, then use default context. Reference from - //contexts instead of early binding to default context, so - //that during builds, the latest instance of the default - //context with its config gets used. - function () { - var ctx = contexts[defContextName]; - return ctx[prop].apply(ctx, arguments); - }; - }); - } - - /** - * Constructs an error with a pointer to an URL with more information. - * @param {String} id the error ID that maps to an ID on a web page. - * @param {String} message human readable error. - * @param {Error} [err] the original error, if there is one. - * - * @returns {Error} - */ - function makeError(id, msg, err, requireModules) { - var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id); - e.requireType = id; - e.requireModules = requireModules; - if (err) { - e.originalError = err; - } - return e; - } - - if (typeof define !== 'undefined') { - //If a define is already in play via another AMD loader, - //do not overwrite. - return; - } - - if (typeof requirejs !== 'undefined') { - if (isFunction(requirejs)) { - //Do not overwrite and existing requirejs instance. - return; - } - cfg = requirejs; - requirejs = undefined; - } - - //Allow for a require config object - if (typeof require !== 'undefined' && !isFunction(require)) { - //assume it is a config object. - cfg = require; - require = undefined; - } - - function newContext(contextName) { - var config = { - waitSeconds: 7, - baseUrl: './', - paths: {}, - pkgs: {}, - shim: {} - }, - registry = {}, - undefEvents = {}, - defQueue = [], - defined = {}, - urlFetched = {}, - requireCounter = 1, - unnormalizedCounter = 1, - //Used to track the order in which modules - //should be executed, by the order they - //load. Important for consistent cycle resolution - //behavior. - waitAry = [], - inCheckLoaded, Module, context, handlers, - checkLoadedTimeoutId; - - /** - * Trims the . and .. from an array of path segments. - * It will keep a leading path segment if a .. will become - * the first path segment, to help with module name lookups, - * which act like paths, but can be remapped. But the end result, - * all paths that use this function should look normalized. - * NOTE: this method MODIFIES the input array. - * @param {Array} ary the array of path segments. - */ - function trimDots(ary) { - var i, part; - for (i = 0; ary[i]; i+= 1) { - part = ary[i]; - if (part === '.') { - ary.splice(i, 1); - i -= 1; - } else if (part === '..') { - if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { - //End of the line. Keep at least one non-dot - //path segment at the front so it can be mapped - //correctly to disk. Otherwise, there is likely - //no path mapping for a path starting with '..'. - //This can still fail, but catches the most reasonable - //uses of .. - break; - } else if (i > 0) { - ary.splice(i - 1, 2); - i -= 2; - } - } - } - } - - /** - * Given a relative module name, like ./something, normalize it to - * a real name that can be mapped to a path. - * @param {String} name the relative name - * @param {String} baseName a real name that the name arg is relative - * to. - * @param {Boolean} applyMap apply the map config to the value. Should - * only be done if this normalization is for a dependency ID. - * @returns {String} normalized name - */ - function normalize(name, baseName, applyMap) { - var baseParts = baseName && baseName.split('/'), - normalizedBaseParts = baseParts, - map = config.map, - starMap = map && map['*'], - pkgName, pkgConfig, mapValue, nameParts, i, j, nameSegment, - foundMap; - - //Adjust any relative paths. - if (name && name.charAt(0) === '.') { - //If have a base name, try to normalize against it, - //otherwise, assume it is a top-level require that will - //be relative to baseUrl in the end. - if (baseName) { - if (config.pkgs[baseName]) { - //If the baseName is a package name, then just treat it as one - //name to concat the name with. - normalizedBaseParts = baseParts = [baseName]; - } else { - //Convert baseName to array, and lop off the last part, - //so that . matches that 'directory' and not name of the baseName's - //module. For instance, baseName of 'one/two/three', maps to - //'one/two/three.js', but we want the directory, 'one/two' for - //this normalization. - normalizedBaseParts = baseParts.slice(0, baseParts.length - 1); - } - - name = normalizedBaseParts.concat(name.split('/')); - trimDots(name); - - //Some use of packages may use a . path to reference the - //'main' module name, so normalize for that. - pkgConfig = config.pkgs[(pkgName = name[0])]; - name = name.join('/'); - if (pkgConfig && name === pkgName + '/' + pkgConfig.main) { - name = pkgName; - } - } else if (name.indexOf('./') === 0) { - // No baseName, so this is ID is resolved relative - // to baseUrl, pull off the leading dot. - name = name.substring(2); - } - } - - //Apply map config if available. - if (applyMap && (baseParts || starMap) && map) { - nameParts = name.split('/'); - - for (i = nameParts.length; i > 0; i -= 1) { - nameSegment = nameParts.slice(0, i).join('/'); - - if (baseParts) { - //Find the longest baseName segment match in the config. - //So, do joins on the biggest to smallest lengths of baseParts. - for (j = baseParts.length; j > 0; j -= 1) { - mapValue = map[baseParts.slice(0, j).join('/')]; - - //baseName segment has config, find if it has one for - //this name. - if (mapValue) { - mapValue = mapValue[nameSegment]; - if (mapValue) { - //Match, update name to the new value. - foundMap = mapValue; - break; - } - } - } - } - - if (!foundMap && starMap && starMap[nameSegment]) { - foundMap = starMap[nameSegment]; - } - - if (foundMap) { - nameParts.splice(0, i, foundMap); - name = nameParts.join('/'); - break; - } - } - } - - return name; - } - - function removeScript(name) { - if (isBrowser) { - each(scripts(), function (scriptNode) { - if (scriptNode.getAttribute('data-requiremodule') === name && - scriptNode.getAttribute('data-requirecontext') === context.contextName) { - scriptNode.parentNode.removeChild(scriptNode); - return true; - } - }); - } - } - - function hasPathFallback(id) { - var pathConfig = config.paths[id]; - if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) { - removeScript(id); - //Pop off the first array value, since it failed, and - //retry - pathConfig.shift(); - context.undef(id); - context.require([id]); - return true; - } - } - - /** - * Creates a module mapping that includes plugin prefix, module - * name, and path. If parentModuleMap is provided it will - * also normalize the name via require.normalize() - * - * @param {String} name the module name - * @param {String} [parentModuleMap] parent module map - * for the module name, used to resolve relative names. - * @param {Boolean} isNormalized: is the ID already normalized. - * This is true if this call is done for a define() module ID. - * @param {Boolean} applyMap: apply the map config to the ID. - * Should only be true if this map is for a dependency. - * - * @returns {Object} - */ - function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) { - var index = name ? name.indexOf('!') : -1, - prefix = null, - parentName = parentModuleMap ? parentModuleMap.name : null, - originalName = name, - isDefine = true, - normalizedName = '', - url, pluginModule, suffix; - - //If no name, then it means it is a require call, generate an - //internal name. - if (!name) { - isDefine = false; - name = '_@r' + (requireCounter += 1); - } - - if (index !== -1) { - prefix = name.substring(0, index); - name = name.substring(index + 1, name.length); - } - - if (prefix) { - prefix = normalize(prefix, parentName, applyMap); - pluginModule = defined[prefix]; - } - - //Account for relative paths if there is a base name. - if (name) { - if (prefix) { - if (pluginModule && pluginModule.normalize) { - //Plugin is loaded, use its normalize method. - normalizedName = pluginModule.normalize(name, function (name) { - return normalize(name, parentName, applyMap); - }); - } else { - normalizedName = normalize(name, parentName, applyMap); - } - } else { - //A regular module. - normalizedName = normalize(name, parentName, applyMap); - url = context.nameToUrl(normalizedName); - } - } - - //If the id is a plugin id that cannot be determined if it needs - //normalization, stamp it with a unique ID so two matching relative - //ids that may conflict can be separate. - suffix = prefix && !pluginModule && !isNormalized ? - '_unnormalized' + (unnormalizedCounter += 1) : - ''; - - return { - prefix: prefix, - name: normalizedName, - parentMap: parentModuleMap, - unnormalized: !!suffix, - url: url, - originalName: originalName, - isDefine: isDefine, - id: (prefix ? - prefix + '!' + normalizedName : - normalizedName) + suffix - }; - } - - function getModule(depMap) { - var id = depMap.id, - mod = registry[id]; - - if (!mod) { - mod = registry[id] = new context.Module(depMap); - } - - return mod; - } - - function on(depMap, name, fn) { - var id = depMap.id, - mod = registry[id]; - - if (hasProp(defined, id) && - (!mod || mod.defineEmitComplete)) { - if (name === 'defined') { - fn(defined[id]); - } - } else { - getModule(depMap).on(name, fn); - } - } - - function onError(err, errback) { - var ids = err.requireModules, - notified = false; - - if (errback) { - errback(err); - } else { - each(ids, function (id) { - var mod = registry[id]; - if (mod) { - //Set error on module, so it skips timeout checks. - mod.error = err; - if (mod.events.error) { - notified = true; - mod.emit('error', err); - } - } - }); - - if (!notified) { - req.onError(err); - } - } - } - - /** - * Internal method to transfer globalQueue items to this context's - * defQueue. - */ - function takeGlobalQueue() { - //Push all the globalDefQueue items into the context's defQueue - if (globalDefQueue.length) { - //Array splice in the values since the context code has a - //local var ref to defQueue, so cannot just reassign the one - //on context. - apsp.apply(defQueue, - [defQueue.length - 1, 0].concat(globalDefQueue)); - globalDefQueue = []; - } - } - - /** - * Helper function that creates a require function object to give to - * modules that ask for it as a dependency. It needs to be specific - * per module because of the implication of path mappings that may - * need to be relative to the module name. - */ - function makeRequire(mod, enableBuildCallback, altRequire) { - var relMap = mod && mod.map, - modRequire = makeContextModuleFunc(altRequire || context.require, - relMap, - enableBuildCallback); - - addRequireMethods(modRequire, context, relMap); - modRequire.isBrowser = isBrowser; - - return modRequire; - } - - handlers = { - 'require': function (mod) { - return makeRequire(mod); - }, - 'exports': function (mod) { - mod.usingExports = true; - if (mod.map.isDefine) { - return (mod.exports = defined[mod.map.id] = {}); - } - }, - 'module': function (mod) { - return (mod.module = { - id: mod.map.id, - uri: mod.map.url, - config: function () { - return (config.config && config.config[mod.map.id]) || {}; - }, - exports: defined[mod.map.id] - }); - } - }; - - function removeWaiting(id) { - //Clean up machinery used for waiting modules. - delete registry[id]; - - each(waitAry, function (mod, i) { - if (mod.map.id === id) { - waitAry.splice(i, 1); - if (!mod.defined) { - context.waitCount -= 1; - } - return true; - } - }); - } - - function findCycle(mod, traced) { - var id = mod.map.id, - depArray = mod.depMaps, - foundModule; - - //Do not bother with unitialized modules or not yet enabled - //modules. - if (!mod.inited) { - return; - } - - //Found the cycle. - if (traced[id]) { - return mod; - } - - traced[id] = true; - - //Trace through the dependencies. - each(depArray, function (depMap) { - var depId = depMap.id, - depMod = registry[depId]; - - if (!depMod) { - return; - } - - if (!depMod.inited || !depMod.enabled) { - //Dependency is not inited, so this cannot - //be used to determine a cycle. - foundModule = null; - delete traced[id]; - return true; - } - - //mixin traced to a new object for each dependency, so that - //sibling dependencies in this object to not generate a - //false positive match on a cycle. Ideally an Object.create - //type of prototype delegation would be used here, but - //optimizing for file size vs. execution speed since hopefully - //the trees are small for circular dependency scans relative - //to the full app perf. - return (foundModule = findCycle(depMod, mixin({}, traced))); - }); - - return foundModule; - } - - function forceExec(mod, traced, uninited) { - var id = mod.map.id, - depArray = mod.depMaps; - - if (!mod.inited || !mod.map.isDefine) { - return; - } - - if (traced[id]) { - return defined[id]; - } - - traced[id] = mod; - - each(depArray, function(depMap) { - var depId = depMap.id, - depMod = registry[depId], - value; - - if (handlers[depId]) { - return; - } - - if (depMod) { - if (!depMod.inited || !depMod.enabled) { - //Dependency is not inited, - //so this module cannot be - //given a forced value yet. - uninited[id] = true; - return; - } - - //Get the value for the current dependency - value = forceExec(depMod, traced, uninited); - - //Even with forcing it may not be done, - //in particular if the module is waiting - //on a plugin resource. - if (!uninited[depId]) { - mod.defineDepById(depId, value); - } - } - }); - - mod.check(true); - - return defined[id]; - } - - function modCheck(mod) { - mod.check(); - } - - function checkLoaded() { - var waitInterval = config.waitSeconds * 1000, - //It is possible to disable the wait interval by using waitSeconds of 0. - expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(), - noLoads = [], - stillLoading = false, - needCycleCheck = true, - map, modId, err, usingPathFallback; - - //Do not bother if this call was a result of a cycle break. - if (inCheckLoaded) { - return; - } - - inCheckLoaded = true; - - //Figure out the state of all the modules. - eachProp(registry, function (mod) { - map = mod.map; - modId = map.id; - - //Skip things that are not enabled or in error state. - if (!mod.enabled) { - return; - } - - if (!mod.error) { - //If the module should be executed, and it has not - //been inited and time is up, remember it. - if (!mod.inited && expired) { - if (hasPathFallback(modId)) { - usingPathFallback = true; - stillLoading = true; - } else { - noLoads.push(modId); - removeScript(modId); - } - } else if (!mod.inited && mod.fetched && map.isDefine) { - stillLoading = true; - if (!map.prefix) { - //No reason to keep looking for unfinished - //loading. If the only stillLoading is a - //plugin resource though, keep going, - //because it may be that a plugin resource - //is waiting on a non-plugin cycle. - return (needCycleCheck = false); - } - } - } - }); - - if (expired && noLoads.length) { - //If wait time expired, throw error of unloaded modules. - err = makeError('timeout', 'Load timeout for modules: ' + noLoads, null, noLoads); - err.contextName = context.contextName; - return onError(err); - } - - //Not expired, check for a cycle. - if (needCycleCheck) { - - each(waitAry, function (mod) { - if (mod.defined) { - return; - } - - var cycleMod = findCycle(mod, {}), - traced = {}; - - if (cycleMod) { - forceExec(cycleMod, traced, {}); - - //traced modules may have been - //removed from the registry, but - //their listeners still need to - //be called. - eachProp(traced, modCheck); - } - }); - - //Now that dependencies have - //been satisfied, trigger the - //completion check that then - //notifies listeners. - eachProp(registry, modCheck); - } - - //If still waiting on loads, and the waiting load is something - //other than a plugin resource, or there are still outstanding - //scripts, then just try back later. - if ((!expired || usingPathFallback) && stillLoading) { - //Something is still waiting to load. Wait for it, but only - //if a timeout is not already in effect. - if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) { - checkLoadedTimeoutId = setTimeout(function () { - checkLoadedTimeoutId = 0; - checkLoaded(); - }, 50); - } - } - - inCheckLoaded = false; - } - - Module = function (map) { - this.events = undefEvents[map.id] || {}; - this.map = map; - this.shim = config.shim[map.id]; - this.depExports = []; - this.depMaps = []; - this.depMatched = []; - this.pluginMaps = {}; - this.depCount = 0; - - /* this.exports this.factory - this.depMaps = [], - this.enabled, this.fetched - */ - }; - - Module.prototype = { - init: function(depMaps, factory, errback, options) { - options = options || {}; - - //Do not do more inits if already done. Can happen if there - //are multiple define calls for the same module. That is not - //a normal, common case, but it is also not unexpected. - if (this.inited) { - return; - } - - this.factory = factory; - - if (errback) { - //Register for errors on this module. - this.on('error', errback); - } else if (this.events.error) { - //If no errback already, but there are error listeners - //on this module, set up an errback to pass to the deps. - errback = bind(this, function (err) { - this.emit('error', err); - }); - } - - //Do a copy of the dependency array, so that - //source inputs are not modified. For example - //"shim" deps are passed in here directly, and - //doing a direct modification of the depMaps array - //would affect that config. - this.depMaps = depMaps && depMaps.slice(0); - this.depMaps.rjsSkipMap = depMaps.rjsSkipMap; - - this.errback = errback; - - //Indicate this module has be initialized - this.inited = true; - - this.ignore = options.ignore; - - //Could have option to init this module in enabled mode, - //or could have been previously marked as enabled. However, - //the dependencies are not known until init is called. So - //if enabled previously, now trigger dependencies as enabled. - if (options.enabled || this.enabled) { - //Enable this module and dependencies. - //Will call this.check() - this.enable(); - } else { - this.check(); - } - }, - - defineDepById: function (id, depExports) { - var i; - - //Find the index for this dependency. - each(this.depMaps, function (map, index) { - if (map.id === id) { - i = index; - return true; - } - }); - - return this.defineDep(i, depExports); - }, - - defineDep: function (i, depExports) { - //Because of cycles, defined callback for a given - //export can be called more than once. - if (!this.depMatched[i]) { - this.depMatched[i] = true; - this.depCount -= 1; - this.depExports[i] = depExports; - } - }, - - fetch: function () { - if (this.fetched) { - return; - } - this.fetched = true; - - context.startTime = (new Date()).getTime(); - - var map = this.map; - - //If the manager is for a plugin managed resource, - //ask the plugin to load it now. - if (this.shim) { - makeRequire(this, true)(this.shim.deps || [], bind(this, function () { - return map.prefix ? this.callPlugin() : this.load(); - })); - } else { - //Regular dependency. - return map.prefix ? this.callPlugin() : this.load(); - } - }, - - load: function() { - var url = this.map.url; - - //Regular dependency. - if (!urlFetched[url]) { - urlFetched[url] = true; - context.load(this.map.id, url); - } - }, - - /** - * Checks is the module is ready to define itself, and if so, - * define it. If the silent argument is true, then it will just - * define, but not notify listeners, and not ask for a context-wide - * check of all loaded modules. That is useful for cycle breaking. - */ - check: function (silent) { - if (!this.enabled || this.enabling) { - return; - } - - var id = this.map.id, - depExports = this.depExports, - exports = this.exports, - factory = this.factory, - err, cjsModule; - - if (!this.inited) { - this.fetch(); - } else if (this.error) { - this.emit('error', this.error); - } else if (!this.defining) { - //The factory could trigger another require call - //that would result in checking this module to - //define itself again. If already in the process - //of doing that, skip this work. - this.defining = true; - - if (this.depCount < 1 && !this.defined) { - if (isFunction(factory)) { - //If there is an error listener, favor passing - //to that instead of throwing an error. - if (this.events.error) { - try { - exports = context.execCb(id, factory, depExports, exports); - } catch (e) { - err = e; - } - } else { - exports = context.execCb(id, factory, depExports, exports); - } - - if (this.map.isDefine) { - //If setting exports via 'module' is in play, - //favor that over return value and exports. After that, - //favor a non-undefined return value over exports use. - cjsModule = this.module; - if (cjsModule && - cjsModule.exports !== undefined && - //Make sure it is not already the exports value - cjsModule.exports !== this.exports) { - exports = cjsModule.exports; - } else if (exports === undefined && this.usingExports) { - //exports already set the defined value. - exports = this.exports; - } - } - - if (err) { - err.requireMap = this.map; - err.requireModules = [this.map.id]; - err.requireType = 'define'; - return onError((this.error = err)); - } - - } else { - //Just a literal value - exports = factory; - } - - this.exports = exports; - - if (this.map.isDefine && !this.ignore) { - defined[id] = exports; - - if (req.onResourceLoad) { - req.onResourceLoad(context, this.map, this.depMaps); - } - } - - //Clean up - delete registry[id]; - - this.defined = true; - context.waitCount -= 1; - if (context.waitCount === 0) { - //Clear the wait array used for cycles. - waitAry = []; - } - } - - //Finished the define stage. Allow calling check again - //to allow define notifications below in the case of a - //cycle. - this.defining = false; - - if (!silent) { - if (this.defined && !this.defineEmitted) { - this.defineEmitted = true; - this.emit('defined', this.exports); - this.defineEmitComplete = true; - } - } - } - }, - - callPlugin: function() { - var map = this.map, - id = map.id, - pluginMap = makeModuleMap(map.prefix, null, false, true); - - on(pluginMap, 'defined', bind(this, function (plugin) { - var name = this.map.name, - parentName = this.map.parentMap ? this.map.parentMap.name : null, - load, normalizedMap, normalizedMod; - - //If current map is not normalized, wait for that - //normalized name to load instead of continuing. - if (this.map.unnormalized) { - //Normalize the ID if the plugin allows it. - if (plugin.normalize) { - name = plugin.normalize(name, function (name) { - return normalize(name, parentName, true); - }) || ''; - } - - normalizedMap = makeModuleMap(map.prefix + '!' + name, - this.map.parentMap, - false, - true); - on(normalizedMap, - 'defined', bind(this, function (value) { - this.init([], function () { return value; }, null, { - enabled: true, - ignore: true - }); - })); - normalizedMod = registry[normalizedMap.id]; - if (normalizedMod) { - if (this.events.error) { - normalizedMod.on('error', bind(this, function (err) { - this.emit('error', err); - })); - } - normalizedMod.enable(); - } - - return; - } - - load = bind(this, function (value) { - this.init([], function () { return value; }, null, { - enabled: true - }); - }); - - load.error = bind(this, function (err) { - this.inited = true; - this.error = err; - err.requireModules = [id]; - - //Remove temp unnormalized modules for this module, - //since they will never be resolved otherwise now. - eachProp(registry, function (mod) { - if (mod.map.id.indexOf(id + '_unnormalized') === 0) { - removeWaiting(mod.map.id); - } - }); - - onError(err); - }); - - //Allow plugins to load other code without having to know the - //context or how to 'complete' the load. - load.fromText = function (moduleName, text) { - /*jslint evil: true */ - var hasInteractive = useInteractive; - - //Turn off interactive script matching for IE for any define - //calls in the text, then turn it back on at the end. - if (hasInteractive) { - useInteractive = false; - } - - //Prime the system by creating a module instance for - //it. - getModule(makeModuleMap(moduleName)); - - req.exec(text); - - if (hasInteractive) { - useInteractive = true; - } - - //Support anonymous modules. - context.completeLoad(moduleName); - }; - - //Use parentName here since the plugin's name is not reliable, - //could be some weird string with no path that actually wants to - //reference the parentName's path. - plugin.load(map.name, makeRequire(map.parentMap, true, function (deps, cb) { - deps.rjsSkipMap = true; - return context.require(deps, cb); - }), load, config); - })); - - context.enable(pluginMap, this); - this.pluginMaps[pluginMap.id] = pluginMap; - }, - - enable: function () { - this.enabled = true; - - if (!this.waitPushed) { - waitAry.push(this); - context.waitCount += 1; - this.waitPushed = true; - } - - //Set flag mentioning that the module is enabling, - //so that immediate calls to the defined callbacks - //for dependencies do not trigger inadvertent load - //with the depCount still being zero. - this.enabling = true; - - //Enable each dependency - each(this.depMaps, bind(this, function (depMap, i) { - var id, mod, handler; - - if (typeof depMap === 'string') { - //Dependency needs to be converted to a depMap - //and wired up to this module. - depMap = makeModuleMap(depMap, - (this.map.isDefine ? this.map : this.map.parentMap), - false, - !this.depMaps.rjsSkipMap); - this.depMaps[i] = depMap; - - handler = handlers[depMap.id]; - - if (handler) { - this.depExports[i] = handler(this); - return; - } - - this.depCount += 1; - - on(depMap, 'defined', bind(this, function (depExports) { - this.defineDep(i, depExports); - this.check(); - })); - - if (this.errback) { - on(depMap, 'error', this.errback); - } - } - - id = depMap.id; - mod = registry[id]; - - //Skip special modules like 'require', 'exports', 'module' - //Also, don't call enable if it is already enabled, - //important in circular dependency cases. - if (!handlers[id] && mod && !mod.enabled) { - context.enable(depMap, this); - } - })); - - //Enable each plugin that is used in - //a dependency - eachProp(this.pluginMaps, bind(this, function (pluginMap) { - var mod = registry[pluginMap.id]; - if (mod && !mod.enabled) { - context.enable(pluginMap, this); - } - })); - - this.enabling = false; - - this.check(); - }, - - on: function(name, cb) { - var cbs = this.events[name]; - if (!cbs) { - cbs = this.events[name] = []; - } - cbs.push(cb); - }, - - emit: function (name, evt) { - each(this.events[name], function (cb) { - cb(evt); - }); - if (name === 'error') { - //Now that the error handler was triggered, remove - //the listeners, since this broken Module instance - //can stay around for a while in the registry/waitAry. - delete this.events[name]; - } - } - }; - - function callGetModule(args) { - getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]); - } - - function removeListener(node, func, name, ieName) { - //Favor detachEvent because of IE9 - //issue, see attachEvent/addEventListener comment elsewhere - //in this file. - if (node.detachEvent && !isOpera) { - //Probably IE. If not it will throw an error, which will be - //useful to know. - if (ieName) { - node.detachEvent(ieName, func); - } - } else { - node.removeEventListener(name, func, false); - } - } - - /** - * Given an event from a script node, get the requirejs info from it, - * and then removes the event listeners on the node. - * @param {Event} evt - * @returns {Object} - */ - function getScriptData(evt) { - //Using currentTarget instead of target for Firefox 2.0's sake. Not - //all old browsers will be supported, but this one was easy enough - //to support and still makes sense. - var node = evt.currentTarget || evt.srcElement; - - //Remove the listeners once here. - removeListener(node, context.onScriptLoad, 'load', 'onreadystatechange'); - removeListener(node, context.onScriptError, 'error'); - - return { - node: node, - id: node && node.getAttribute('data-requiremodule') - }; - } - - return (context = { - config: config, - contextName: contextName, - registry: registry, - defined: defined, - urlFetched: urlFetched, - waitCount: 0, - defQueue: defQueue, - Module: Module, - makeModuleMap: makeModuleMap, - - /** - * Set a configuration for the context. - * @param {Object} cfg config object to integrate. - */ - configure: function (cfg) { - //Make sure the baseUrl ends in a slash. - if (cfg.baseUrl) { - if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== '/') { - cfg.baseUrl += '/'; - } - } - - //Save off the paths and packages since they require special processing, - //they are additive. - var pkgs = config.pkgs, - shim = config.shim, - paths = config.paths, - map = config.map; - - //Mix in the config values, favoring the new values over - //existing ones in context.config. - mixin(config, cfg, true); - - //Merge paths. - config.paths = mixin(paths, cfg.paths, true); - - //Merge map - if (cfg.map) { - config.map = mixin(map || {}, cfg.map, true, true); - } - - //Merge shim - if (cfg.shim) { - eachProp(cfg.shim, function (value, id) { - //Normalize the structure - if (isArray(value)) { - value = { - deps: value - }; - } - if (value.exports && !value.exports.__buildReady) { - value.exports = context.makeShimExports(value.exports); - } - shim[id] = value; - }); - config.shim = shim; - } - - //Adjust packages if necessary. - if (cfg.packages) { - each(cfg.packages, function (pkgObj) { - var location; - - pkgObj = typeof pkgObj === 'string' ? { name: pkgObj } : pkgObj; - location = pkgObj.location; - - //Create a brand new object on pkgs, since currentPackages can - //be passed in again, and config.pkgs is the internal transformed - //state for all package configs. - pkgs[pkgObj.name] = { - name: pkgObj.name, - location: location || pkgObj.name, - //Remove leading dot in main, so main paths are normalized, - //and remove any trailing .js, since different package - //envs have different conventions: some use a module name, - //some use a file name. - main: (pkgObj.main || 'main') - .replace(currDirRegExp, '') - .replace(jsSuffixRegExp, '') - }; - }); - - //Done with modifications, assing packages back to context config - config.pkgs = pkgs; - } - - //If there are any "waiting to execute" modules in the registry, - //update the maps for them, since their info, like URLs to load, - //may have changed. - eachProp(registry, function (mod, id) { - mod.map = makeModuleMap(id); - }); - - //If a deps array or a config callback is specified, then call - //require with those args. This is useful when require is defined as a - //config object before require.js is loaded. - if (cfg.deps || cfg.callback) { - context.require(cfg.deps || [], cfg.callback); - } - }, - - makeShimExports: function (exports) { - var func; - if (typeof exports === 'string') { - func = function () { - return getGlobal(exports); - }; - //Save the exports for use in nodefine checking. - func.exports = exports; - return func; - } else { - return function () { - return exports.apply(global, arguments); - }; - } - }, - - requireDefined: function (id, relMap) { - return hasProp(defined, makeModuleMap(id, relMap, false, true).id); - }, - - requireSpecified: function (id, relMap) { - id = makeModuleMap(id, relMap, false, true).id; - return hasProp(defined, id) || hasProp(registry, id); - }, - - require: function (deps, callback, errback, relMap) { - var moduleName, id, map, requireMod, args; - if (typeof deps === 'string') { - if (isFunction(callback)) { - //Invalid call - return onError(makeError('requireargs', 'Invalid require call'), errback); - } - - //Synchronous access to one module. If require.get is - //available (as in the Node adapter), prefer that. - //In this case deps is the moduleName and callback is - //the relMap - if (req.get) { - return req.get(context, deps, callback); - } - - //Just return the module wanted. In this scenario, the - //second arg (if passed) is just the relMap. - moduleName = deps; - relMap = callback; - - //Normalize module name, if it contains . or .. - map = makeModuleMap(moduleName, relMap, false, true); - id = map.id; - - if (!hasProp(defined, id)) { - return onError(makeError('notloaded', 'Module name "' + - id + - '" has not been loaded yet for context: ' + - contextName)); - } - return defined[id]; - } - - //Callback require. Normalize args. if callback or errback is - //not a function, it means it is a relMap. Test errback first. - if (errback && !isFunction(errback)) { - relMap = errback; - errback = undefined; - } - if (callback && !isFunction(callback)) { - relMap = callback; - callback = undefined; - } - - //Any defined modules in the global queue, intake them now. - takeGlobalQueue(); - - //Make sure any remaining defQueue items get properly processed. - while (defQueue.length) { - args = defQueue.shift(); - if (args[0] === null) { - return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1])); - } else { - //args are id, deps, factory. Should be normalized by the - //define() function. - callGetModule(args); - } - } - - //Mark all the dependencies as needing to be loaded. - requireMod = getModule(makeModuleMap(null, relMap)); - - requireMod.init(deps, callback, errback, { - enabled: true - }); - - checkLoaded(); - - return context.require; - }, - - undef: function (id) { - var map = makeModuleMap(id, null, true), - mod = registry[id]; - - delete defined[id]; - delete urlFetched[map.url]; - delete undefEvents[id]; - - if (mod) { - //Hold on to listeners in case the - //module will be attempted to be reloaded - //using a different config. - if (mod.events.defined) { - undefEvents[id] = mod.events; - } - - removeWaiting(id); - } - }, - - /** - * Called to enable a module if it is still in the registry - * awaiting enablement. parent module is passed in for context, - * used by the optimizer. - */ - enable: function (depMap, parent) { - var mod = registry[depMap.id]; - if (mod) { - getModule(depMap).enable(); - } - }, - - /** - * Internal method used by environment adapters to complete a load event. - * A load event could be a script load or just a load pass from a synchronous - * load call. - * @param {String} moduleName the name of the module to potentially complete. - */ - completeLoad: function (moduleName) { - var shim = config.shim[moduleName] || {}, - shExports = shim.exports && shim.exports.exports, - found, args, mod; - - takeGlobalQueue(); - - while (defQueue.length) { - args = defQueue.shift(); - if (args[0] === null) { - args[0] = moduleName; - //If already found an anonymous module and bound it - //to this name, then this is some other anon module - //waiting for its completeLoad to fire. - if (found) { - break; - } - found = true; - } else if (args[0] === moduleName) { - //Found matching define call for this script! - found = true; - } - - callGetModule(args); - } - - //Do this after the cycle of callGetModule in case the result - //of those calls/init calls changes the registry. - mod = registry[moduleName]; - - if (!found && - !defined[moduleName] && - mod && !mod.inited) { - if (config.enforceDefine && (!shExports || !getGlobal(shExports))) { - if (hasPathFallback(moduleName)) { - return; - } else { - return onError(makeError('nodefine', - 'No define call for ' + moduleName, - null, - [moduleName])); - } - } else { - //A script that does not call define(), so just simulate - //the call for it. - callGetModule([moduleName, (shim.deps || []), shim.exports]); - } - } - - checkLoaded(); - }, - - /** - * Converts a module name + .extension into an URL path. - * *Requires* the use of a module name. It does not support using - * plain URLs like nameToUrl. - */ - toUrl: function (moduleNamePlusExt, relModuleMap) { - var index = moduleNamePlusExt.lastIndexOf('.'), - ext = null; - - if (index !== -1) { - ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length); - moduleNamePlusExt = moduleNamePlusExt.substring(0, index); - } - - return context.nameToUrl(normalize(moduleNamePlusExt, relModuleMap && relModuleMap.id, true), - ext); - }, - - /** - * Converts a module name to a file path. Supports cases where - * moduleName may actually be just an URL. - * Note that it **does not** call normalize on the moduleName, - * it is assumed to have already been normalized. This is an - * internal API, not a public one. Use toUrl for the public API. - */ - nameToUrl: function (moduleName, ext) { - var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url, - parentPath; - - //If a colon is in the URL, it indicates a protocol is used and it is just - //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?) - //or ends with .js, then assume the user meant to use an url and not a module id. - //The slash is important for protocol-less URLs as well as full paths. - if (req.jsExtRegExp.test(moduleName)) { - //Just a plain path, not module name lookup, so just return it. - //Add extension if it is included. This is a bit wonky, only non-.js things pass - //an extension, this method probably needs to be reworked. - url = moduleName + (ext || ''); - } else { - //A module that needs to be converted to a path. - paths = config.paths; - pkgs = config.pkgs; - - syms = moduleName.split('/'); - //For each module name segment, see if there is a path - //registered for it. Start with most specific name - //and work up from it. - for (i = syms.length; i > 0; i -= 1) { - parentModule = syms.slice(0, i).join('/'); - pkg = pkgs[parentModule]; - parentPath = paths[parentModule]; - if (parentPath) { - //If an array, it means there are a few choices, - //Choose the one that is desired - if (isArray(parentPath)) { - parentPath = parentPath[0]; - } - syms.splice(0, i, parentPath); - break; - } else if (pkg) { - //If module name is just the package name, then looking - //for the main module. - if (moduleName === pkg.name) { - pkgPath = pkg.location + '/' + pkg.main; - } else { - pkgPath = pkg.location; - } - syms.splice(0, i, pkgPath); - break; - } - } - - //Join the path parts together, then figure out if baseUrl is needed. - url = syms.join('/') + (ext || '.js'); - url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url; - } - - return config.urlArgs ? url + - ((url.indexOf('?') === -1 ? '?' : '&') + - config.urlArgs) : url; - }, - - //Delegates to req.load. Broken out as a separate function to - //allow overriding in the optimizer. - load: function (id, url) { - req.load(context, id, url); - }, - - /** - * Executes a module callack function. Broken out as a separate function - * solely to allow the build system to sequence the files in the built - * layer in the right sequence. - * - * @private - */ - execCb: function (name, callback, args, exports) { - return callback.apply(exports, args); - }, - - /** - * callback for script loads, used to check status of loading. - * - * @param {Event} evt the event from the browser for the script - * that was loaded. - */ - onScriptLoad: function (evt) { - //Using currentTarget instead of target for Firefox 2.0's sake. Not - //all old browsers will be supported, but this one was easy enough - //to support and still makes sense. - if (evt.type === 'load' || - (readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) { - //Reset interactive script so a script node is not held onto for - //to long. - interactiveScript = null; - - //Pull out the name of the module and the context. - var data = getScriptData(evt); - context.completeLoad(data.id); - } - }, - - /** - * Callback for script errors. - */ - onScriptError: function (evt) { - var data = getScriptData(evt); - if (!hasPathFallback(data.id)) { - return onError(makeError('scripterror', 'Script error', evt, [data.id])); - } - } - }); - } - - /** - * Main entry point. - * - * If the only argument to require is a string, then the module that - * is represented by that string is fetched for the appropriate context. - * - * If the first argument is an array, then it will be treated as an array - * of dependency string names to fetch. An optional function callback can - * be specified to execute when all of those dependencies are available. - * - * Make a local req variable to help Caja compliance (it assumes things - * on a require that are not standardized), and to give a short - * name for minification/local scope use. - */ - req = requirejs = function (deps, callback, errback, optional) { - - //Find the right context, use default - var contextName = defContextName, - context, config; - - // Determine if have config object in the call. - if (!isArray(deps) && typeof deps !== 'string') { - // deps is a config object - config = deps; - if (isArray(callback)) { - // Adjust args if there are dependencies - deps = callback; - callback = errback; - errback = optional; - } else { - deps = []; - } - } - - if (config && config.context) { - contextName = config.context; - } - - context = contexts[contextName]; - if (!context) { - context = contexts[contextName] = req.s.newContext(contextName); - } - - if (config) { - context.configure(config); - } - - return context.require(deps, callback, errback); - }; - - /** - * Support require.config() to make it easier to cooperate with other - * AMD loaders on globally agreed names. - */ - req.config = function (config) { - return req(config); - }; - - /** - * Export require as a global, but only if it does not already exist. - */ - if (!require) { - require = req; - } - - req.version = version; - - //Used to filter out dependencies that are already paths. - req.jsExtRegExp = /^\/|:|\?|\.js$/; - req.isBrowser = isBrowser; - s = req.s = { - contexts: contexts, - newContext: newContext - }; - - //Create default context. - req({}); - - //Exports some context-sensitive methods on global require, using - //default context if no context specified. - addRequireMethods(req); - - if (isBrowser) { - head = s.head = document.getElementsByTagName('head')[0]; - //If BASE tag is in play, using appendChild is a problem for IE6. - //When that browser dies, this can be removed. Details in this jQuery bug: - //http://dev.jquery.com/ticket/2709 - baseElement = document.getElementsByTagName('base')[0]; - if (baseElement) { - head = s.head = baseElement.parentNode; - } - } - - /** - * Any errors that require explicitly generates will be passed to this - * function. Intercept/override it if you want custom error handling. - * @param {Error} err the error object. - */ - req.onError = function (err) { - throw err; - }; - - /** - * Does the request to load a module for the browser case. - * Make this a separate function to allow other environments - * to override it. - * - * @param {Object} context the require context to find state. - * @param {String} moduleName the name of the module. - * @param {Object} url the URL to the module. - */ - req.load = function (context, moduleName, url) { - var config = (context && context.config) || {}, - node; - if (isBrowser) { - //In the browser so use a script tag - node = config.xhtml ? - document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') : - document.createElement('script'); - node.type = config.scriptType || 'text/javascript'; - node.charset = 'utf-8'; - node.async = true; - - node.setAttribute('data-requirecontext', context.contextName); - node.setAttribute('data-requiremodule', moduleName); - - //Set up load listener. Test attachEvent first because IE9 has - //a subtle issue in its addEventListener and script onload firings - //that do not match the behavior of all other browsers with - //addEventListener support, which fire the onload event for a - //script right after the script execution. See: - //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution - //UNFORTUNATELY Opera implements attachEvent but does not follow the script - //script execution mode. - if (node.attachEvent && - //Check if node.attachEvent is artificially added by custom script or - //natively supported by browser - //read https://github.com/jrburke/requirejs/issues/187 - //if we can NOT find [native code] then it must NOT natively supported. - //in IE8, node.attachEvent does not have toString() - //Note the test for "[native code" with no closing brace, see: - //https://github.com/jrburke/requirejs/issues/273 - !(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) && - !isOpera) { - //Probably IE. IE (at least 6-8) do not fire - //script onload right after executing the script, so - //we cannot tie the anonymous define call to a name. - //However, IE reports the script as being in 'interactive' - //readyState at the time of the define call. - useInteractive = true; - - node.attachEvent('onreadystatechange', context.onScriptLoad); - //It would be great to add an error handler here to catch - //404s in IE9+. However, onreadystatechange will fire before - //the error handler, so that does not help. If addEvenListener - //is used, then IE will fire error before load, but we cannot - //use that pathway given the connect.microsoft.com issue - //mentioned above about not doing the 'script execute, - //then fire the script load event listener before execute - //next script' that other browsers do. - //Best hope: IE10 fixes the issues, - //and then destroys all installs of IE 6-9. - //node.attachEvent('onerror', context.onScriptError); - } else { - node.addEventListener('load', context.onScriptLoad, false); - node.addEventListener('error', context.onScriptError, false); - } - node.src = url; - - //For some cache cases in IE 6-8, the script executes before the end - //of the appendChild execution, so to tie an anonymous define - //call to the module name (which is stored on the node), hold on - //to a reference to this node, but clear after the DOM insertion. - currentlyAddingScript = node; - if (baseElement) { - head.insertBefore(node, baseElement); - } else { - head.appendChild(node); - } - currentlyAddingScript = null; - - return node; - } else if (isWebWorker) { - //In a web worker, use importScripts. This is not a very - //efficient use of importScripts, importScripts will block until - //its script is downloaded and evaluated. However, if web workers - //are in play, the expectation that a build has been done so that - //only one script needs to be loaded anyway. This may need to be - //reevaluated if other use cases become common. - importScripts(url); - - //Account for anonymous modules - context.completeLoad(moduleName); - } - }; - - function getInteractiveScript() { - if (interactiveScript && interactiveScript.readyState === 'interactive') { - return interactiveScript; - } - - eachReverse(scripts(), function (script) { - if (script.readyState === 'interactive') { - return (interactiveScript = script); - } - }); - return interactiveScript; - } - - //Look for a data-main script attribute, which could also adjust the baseUrl. - if (isBrowser) { - //Figure out baseUrl. Get it from the script tag with require.js in it. - eachReverse(scripts(), function (script) { - //Set the 'head' where we can append children by - //using the script's parent. - if (!head) { - head = script.parentNode; - } - - //Look for a data-main attribute to set main script for the page - //to load. If it is there, the path to data main becomes the - //baseUrl, if it is not already set. - dataMain = script.getAttribute('data-main'); - if (dataMain) { - //Set final baseUrl if there is not already an explicit one. - if (!cfg.baseUrl) { - //Pull off the directory of data-main for use as the - //baseUrl. - src = dataMain.split('/'); - mainScript = src.pop(); - subPath = src.length ? src.join('/') + '/' : './'; - - cfg.baseUrl = subPath; - dataMain = mainScript; - } - - //Strip off any trailing .js since dataMain is now - //like a module name. - dataMain = dataMain.replace(jsSuffixRegExp, ''); - - //Put the data-main script in the files to load. - cfg.deps = cfg.deps ? cfg.deps.concat(dataMain) : [dataMain]; - - return true; - } - }); - } - - /** - * The function that handles definitions of modules. Differs from - * require() in that a string for the module should be the first argument, - * and the function to execute after dependencies are loaded should - * return a value to define the module corresponding to the first argument's - * name. - */ - define = function (name, deps, callback) { - var node, context; - - //Allow for anonymous functions - if (typeof name !== 'string') { - //Adjust args appropriately - callback = deps; - deps = name; - name = null; - } - - //This module may not have dependencies - if (!isArray(deps)) { - callback = deps; - deps = []; - } - - //If no name, and callback is a function, then figure out if it a - //CommonJS thing with dependencies. - if (!deps.length && isFunction(callback)) { - //Remove comments from the callback string, - //look for require calls, and pull them into the dependencies, - //but only if there are function args. - if (callback.length) { - callback - .toString() - .replace(commentRegExp, '') - .replace(cjsRequireRegExp, function (match, dep) { - deps.push(dep); - }); - - //May be a CommonJS thing even without require calls, but still - //could use exports, and module. Avoid doing exports and module - //work though if it just needs require. - //REQUIRES the function to expect the CommonJS variables in the - //order listed below. - deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps); - } - } - - //If in IE 6-8 and hit an anonymous define() call, do the interactive - //work. - if (useInteractive) { - node = currentlyAddingScript || getInteractiveScript(); - if (node) { - if (!name) { - name = node.getAttribute('data-requiremodule'); - } - context = contexts[node.getAttribute('data-requirecontext')]; - } - } - - //Always save off evaluating the def call until the script onload handler. - //This allows multiple modules to be in a file without prematurely - //tracing dependencies, and allows for anonymous module support, - //where the module name is not known until the script onload event - //occurs. If no context, use the global queue, and get it processed - //in the onscript load callback. - (context ? context.defQueue : globalDefQueue).push([name, deps, callback]); - }; - - define.amd = { - jQuery: true - }; - - - /** - * Executes the text. Normally just uses eval, but can be modified - * to use a better, environment-specific call. Only used for transpiling - * loader plugins, not for plain JS modules. - * @param {String} text the text to execute/evaluate. - */ - req.exec = function (text) { - /*jslint evil: true */ - return eval(text); - }; - - //Set up with config info. - req(cfg); -}(this)); - - - if (env === 'rhino') { - /** - * @license RequireJS rhino Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint */ -/*global require: false, java: false, load: false */ - -(function () { - 'use strict'; - require.load = function (context, moduleName, url) { - - load(url); - - //Support anonymous modules. - context.completeLoad(moduleName); - }; - -}()); - } else if (env === 'node') { - this.requirejsVars = { - require: require, - requirejs: require, - define: define, - nodeRequire: nodeRequire - }; - require.nodeRequire = nodeRequire; - - /** - * @license RequireJS node Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint regexp: false */ -/*global require: false, define: false, requirejsVars: false, process: false */ - -/** - * This adapter assumes that x.js has loaded it and set up - * some variables. This adapter just allows limited RequireJS - * usage from within the requirejs directory. The general - * node adapater is r.js. - */ - -(function () { - 'use strict'; - - var nodeReq = requirejsVars.nodeRequire, - req = requirejsVars.require, - def = requirejsVars.define, - fs = nodeReq('fs'), - path = nodeReq('path'), - vm = nodeReq('vm'), - //In Node 0.7+ existsSync is on fs. - exists = fs.existsSync || path.existsSync; - - //Supply an implementation that allows synchronous get of a module. - req.get = function (context, moduleName, relModuleMap) { - if (moduleName === "require" || moduleName === "exports" || moduleName === "module") { - req.onError(new Error("Explicit require of " + moduleName + " is not allowed.")); - } - - var ret, - moduleMap = context.makeModuleMap(moduleName, relModuleMap); - - //Normalize module name, if it contains . or .. - moduleName = moduleMap.id; - - if (context.defined.hasOwnProperty(moduleName)) { - ret = context.defined[moduleName]; - } else { - if (ret === undefined) { - //Try to dynamically fetch it. - req.load(context, moduleName, moduleMap.url); - //The above call is sync, so can do the next thing safely. - ret = context.defined[moduleName]; - } - } - - return ret; - }; - - //Add wrapper around the code so that it gets the requirejs - //API instead of the Node API, and it is done lexically so - //that it survives later execution. - req.makeNodeWrapper = function (contents) { - return '(function (require, requirejs, define) { ' + - contents + - '\n}(requirejsVars.require, requirejsVars.requirejs, requirejsVars.define));'; - }; - - req.load = function (context, moduleName, url) { - var contents, err; - - if (exists(url)) { - contents = fs.readFileSync(url, 'utf8'); - - contents = req.makeNodeWrapper(contents); - try { - vm.runInThisContext(contents, fs.realpathSync(url)); - } catch (e) { - err = new Error('Evaluating ' + url + ' as module "' + - moduleName + '" failed with error: ' + e); - err.originalError = e; - err.moduleName = moduleName; - err.fileName = url; - return req.onError(err); - } - } else { - def(moduleName, function () { - try { - return (context.config.nodeRequire || req.nodeRequire)(moduleName); - } catch (e) { - err = new Error('Calling node\'s require("' + - moduleName + '") failed with error: ' + e); - err.originalError = e; - err.moduleName = moduleName; - return req.onError(err); - } - }); - } - - //Support anonymous modules. - context.completeLoad(moduleName); - }; - - //Override to provide the function wrapper for define/require. - req.exec = function (text) { - /*jslint evil: true */ - text = req.makeNodeWrapper(text); - return eval(text); - }; -}()); - - } - - //Support a default file name to execute. Useful for hosted envs - //like Joyent where it defaults to a server.js as the only executed - //script. But only do it if this is not an optimization run. - if (commandOption !== 'o' && (!fileName || !jsSuffixRegExp.test(fileName))) { - fileName = 'main.js'; - } - - /** - * Loads the library files that can be used for the optimizer, or for other - * tasks. - */ - function loadLib() { - /** - * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint strict: false */ -/*global Packages: false, process: false, window: false, navigator: false, - document: false, define: false */ - -/** - * A plugin that modifies any /env/ path to be the right path based on - * the host environment. Right now only works for Node, Rhino and browser. - */ -(function () { - var pathRegExp = /(\/|^)env\/|\{env\}/, - env = 'unknown'; - - if (typeof Packages !== 'undefined') { - env = 'rhino'; - } else if (typeof process !== 'undefined') { - env = 'node'; - } else if (typeof window !== "undefined" && navigator && document) { - env = 'browser'; - } - - define('env', { - load: function (name, req, load, config) { - //Allow override in the config. - if (config.env) { - env = config.env; - } - - name = name.replace(pathRegExp, function (match, prefix) { - if (match.indexOf('{') === -1) { - return prefix + env + '/'; - } else { - return env; - } - }); - - req([name], function (mod) { - load(mod); - }); - } - }); -}()); -if(env === 'node') { -/** - * @license RequireJS Copyright (c) 2012, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint strict: false */ -/*global define: false, load: false */ - -//Needed so that rhino/assert can return a stub for uglify's consolidator.js -define('node/assert', ['assert'], function (assert) { - return assert; -}); - -} - -if(env === 'rhino') { -/** - * @license RequireJS Copyright (c) 2012, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint strict: false */ -/*global define: false, load: false */ - -//Just a stub for use with uglify's consolidator.js -define('rhino/assert', function () { - return {}; -}); - -} - -if(env === 'node') { -/** - * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint strict: false */ -/*global define: false, process: false */ - -define('node/args', function () { - //Do not return the "node" or "r.js" arguments - var args = process.argv.slice(2); - - //Ignore any command option used for rq.js - if (args[0] && args[0].indexOf('-' === 0)) { - args = args.slice(1); - } - - return args; -}); - -} - -if(env === 'rhino') { -/** - * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint strict: false */ -/*global define: false, process: false */ - -var jsLibRhinoArgs = (typeof rhinoArgs !== 'undefined' && rhinoArgs) || [].concat(Array.prototype.slice.call(arguments, 0)); - -define('rhino/args', function () { - var args = jsLibRhinoArgs; - - //Ignore any command option used for rq.js - if (args[0] && args[0].indexOf('-' === 0)) { - args = args.slice(1); - } - - return args; -}); - -} - -if(env === 'node') { -/** - * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint strict: false */ -/*global define: false, console: false */ - -define('node/load', ['fs'], function (fs) { - function load(fileName) { - var contents = fs.readFileSync(fileName, 'utf8'); - process.compile(contents, fileName); - } - - return load; -}); - -} - -if(env === 'rhino') { -/** - * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint strict: false */ -/*global define: false, load: false */ - -define('rhino/load', function () { - return load; -}); - -} - -if(env === 'node') { -/** - * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint plusplus: false, octal:false, strict: false */ -/*global define: false, process: false */ - -define('node/file', ['fs', 'path'], function (fs, path) { - - var isWindows = process.platform === 'win32', - windowsDriveRegExp = /^[a-zA-Z]\:\/$/, - file; - - function frontSlash(path) { - return path.replace(/\\/g, '/'); - } - - function exists(path) { - if (isWindows && path.charAt(path.length - 1) === '/' && - path.charAt(path.length - 2) !== ':') { - path = path.substring(0, path.length - 1); - } - - try { - fs.statSync(path); - return true; - } catch (e) { - return false; - } - } - - function mkDir(dir) { - if (!exists(dir) && (!isWindows || !windowsDriveRegExp.test(dir))) { - fs.mkdirSync(dir, 511); - } - } - - function mkFullDir(dir) { - var parts = dir.split('/'), - currDir = '', - first = true; - - parts.forEach(function (part) { - //First part may be empty string if path starts with a slash. - currDir += part + '/'; - first = false; - - if (part) { - mkDir(currDir); - } - }); - } - - file = { - backSlashRegExp: /\\/g, - exclusionRegExp: /^\./, - getLineSeparator: function () { - return '/'; - }, - - exists: function (fileName) { - return exists(fileName); - }, - - parent: function (fileName) { - var parts = fileName.split('/'); - parts.pop(); - return parts.join('/'); - }, - - /** - * Gets the absolute file path as a string, normalized - * to using front slashes for path separators. - * @param {String} fileName - */ - absPath: function (fileName) { - return frontSlash(path.normalize(frontSlash(fs.realpathSync(fileName)))); - }, - - normalize: function (fileName) { - return frontSlash(path.normalize(fileName)); - }, - - isFile: function (path) { - return fs.statSync(path).isFile(); - }, - - isDirectory: function (path) { - return fs.statSync(path).isDirectory(); - }, - - getFilteredFileList: function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths) { - //summary: Recurses startDir and finds matches to the files that match regExpFilters.include - //and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters, - //and it will be treated as the "include" case. - //Ignores files/directories that start with a period (.) unless exclusionRegExp - //is set to another value. - var files = [], topDir, regExpInclude, regExpExclude, dirFileArray, - i, stat, filePath, ok, dirFiles, fileName; - - topDir = startDir; - - regExpInclude = regExpFilters.include || regExpFilters; - regExpExclude = regExpFilters.exclude || null; - - if (file.exists(topDir)) { - dirFileArray = fs.readdirSync(topDir); - for (i = 0; i < dirFileArray.length; i++) { - fileName = dirFileArray[i]; - filePath = path.join(topDir, fileName); - stat = fs.statSync(filePath); - if (stat.isFile()) { - if (makeUnixPaths) { - //Make sure we have a JS string. - if (filePath.indexOf("/") === -1) { - filePath = frontSlash(filePath); - } - } - - ok = true; - if (regExpInclude) { - ok = filePath.match(regExpInclude); - } - if (ok && regExpExclude) { - ok = !filePath.match(regExpExclude); - } - - if (ok && (!file.exclusionRegExp || - !file.exclusionRegExp.test(fileName))) { - files.push(filePath); - } - } else if (stat.isDirectory() && - (!file.exclusionRegExp || !file.exclusionRegExp.test(fileName))) { - dirFiles = this.getFilteredFileList(filePath, regExpFilters, makeUnixPaths); - files.push.apply(files, dirFiles); - } - } - } - - return files; //Array - }, - - copyDir: function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) { - //summary: copies files from srcDir to destDir using the regExpFilter to determine if the - //file should be copied. Returns a list file name strings of the destinations that were copied. - regExpFilter = regExpFilter || /\w/; - - //Normalize th directory names, but keep front slashes. - //path module on windows now returns backslashed paths. - srcDir = frontSlash(path.normalize(srcDir)); - destDir = frontSlash(path.normalize(destDir)); - - var fileNames = file.getFilteredFileList(srcDir, regExpFilter, true), - copiedFiles = [], i, srcFileName, destFileName; - - for (i = 0; i < fileNames.length; i++) { - srcFileName = fileNames[i]; - destFileName = srcFileName.replace(srcDir, destDir); - - if (file.copyFile(srcFileName, destFileName, onlyCopyNew)) { - copiedFiles.push(destFileName); - } - } - - return copiedFiles.length ? copiedFiles : null; //Array or null - }, - - copyFile: function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) { - //summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if - //srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred. - var parentDir; - - //logger.trace("Src filename: " + srcFileName); - //logger.trace("Dest filename: " + destFileName); - - //If onlyCopyNew is true, then compare dates and only copy if the src is newer - //than dest. - if (onlyCopyNew) { - if (file.exists(destFileName) && fs.statSync(destFileName).mtime.getTime() >= fs.statSync(srcFileName).mtime.getTime()) { - return false; //Boolean - } - } - - //Make sure destination dir exists. - parentDir = path.dirname(destFileName); - if (!file.exists(parentDir)) { - mkFullDir(parentDir); - } - - fs.writeFileSync(destFileName, fs.readFileSync(srcFileName, 'binary'), 'binary'); - - return true; //Boolean - }, - - /** - * Renames a file. May fail if "to" already exists or is on another drive. - */ - renameFile: function (from, to) { - return fs.renameSync(from, to); - }, - - /** - * Reads a *text* file. - */ - readFile: function (/*String*/path, /*String?*/encoding) { - if (encoding === 'utf-8') { - encoding = 'utf8'; - } - if (!encoding) { - encoding = 'utf8'; - } - - var text = fs.readFileSync(path, encoding); - - //Hmm, would not expect to get A BOM, but it seems to happen, - //remove it just in case. - if (text.indexOf('\uFEFF') === 0) { - text = text.substring(1, text.length); - } - - return text; - }, - - saveUtf8File: function (/*String*/fileName, /*String*/fileContents) { - //summary: saves a *text* file using UTF-8 encoding. - file.saveFile(fileName, fileContents, "utf8"); - }, - - saveFile: function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) { - //summary: saves a *text* file. - var parentDir; - - if (encoding === 'utf-8') { - encoding = 'utf8'; - } - if (!encoding) { - encoding = 'utf8'; - } - - //Make sure destination directories exist. - parentDir = path.dirname(fileName); - if (!file.exists(parentDir)) { - mkFullDir(parentDir); - } - - fs.writeFileSync(fileName, fileContents, encoding); - }, - - deleteFile: function (/*String*/fileName) { - //summary: deletes a file or directory if it exists. - var files, i, stat; - if (file.exists(fileName)) { - stat = fs.statSync(fileName); - if (stat.isDirectory()) { - files = fs.readdirSync(fileName); - for (i = 0; i < files.length; i++) { - this.deleteFile(path.join(fileName, files[i])); - } - fs.rmdirSync(fileName); - } else { - fs.unlinkSync(fileName); - } - } - }, - - - /** - * Deletes any empty directories under the given directory. - */ - deleteEmptyDirs: function (startDir) { - var dirFileArray, i, fileName, filePath, stat; - - if (file.exists(startDir)) { - dirFileArray = fs.readdirSync(startDir); - for (i = 0; i < dirFileArray.length; i++) { - fileName = dirFileArray[i]; - filePath = path.join(startDir, fileName); - stat = fs.statSync(filePath); - if (stat.isDirectory()) { - file.deleteEmptyDirs(filePath); - } - } - - //If directory is now empty, remove it. - if (fs.readdirSync(startDir).length === 0) { - file.deleteFile(startDir); - } - } - } - }; - - return file; - -}); - -} - -if(env === 'rhino') { -/** - * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ -//Helper functions to deal with file I/O. - -/*jslint plusplus: false, strict: true */ -/*global java: false, define: false */ - -define('rhino/file', function () { - var file = { - backSlashRegExp: /\\/g, - - exclusionRegExp: /^\./, - - getLineSeparator: function () { - return file.lineSeparator; - }, - - lineSeparator: java.lang.System.getProperty("line.separator"), //Java String - - exists: function (fileName) { - return (new java.io.File(fileName)).exists(); - }, - - parent: function (fileName) { - return file.absPath((new java.io.File(fileName)).getParentFile()); - }, - - normalize: function (fileName) { - return file.absPath(fileName); - }, - - isFile: function (path) { - return (new java.io.File(path)).isFile(); - }, - - isDirectory: function (path) { - return (new java.io.File(path)).isDirectory(); - }, - - /** - * Gets the absolute file path as a string, normalized - * to using front slashes for path separators. - * @param {java.io.File||String} file - */ - absPath: function (fileObj) { - if (typeof fileObj === "string") { - fileObj = new java.io.File(fileObj); - } - return (fileObj.getCanonicalPath() + "").replace(file.backSlashRegExp, "/"); - }, - - getFilteredFileList: function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths, /*boolean?*/startDirIsJavaObject) { - //summary: Recurses startDir and finds matches to the files that match regExpFilters.include - //and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters, - //and it will be treated as the "include" case. - //Ignores files/directories that start with a period (.) unless exclusionRegExp - //is set to another value. - var files = [], topDir, regExpInclude, regExpExclude, dirFileArray, - i, fileObj, filePath, ok, dirFiles; - - topDir = startDir; - if (!startDirIsJavaObject) { - topDir = new java.io.File(startDir); - } - - regExpInclude = regExpFilters.include || regExpFilters; - regExpExclude = regExpFilters.exclude || null; - - if (topDir.exists()) { - dirFileArray = topDir.listFiles(); - for (i = 0; i < dirFileArray.length; i++) { - fileObj = dirFileArray[i]; - if (fileObj.isFile()) { - filePath = fileObj.getPath(); - if (makeUnixPaths) { - //Make sure we have a JS string. - filePath = String(filePath); - if (filePath.indexOf("/") === -1) { - filePath = filePath.replace(/\\/g, "/"); - } - } - - ok = true; - if (regExpInclude) { - ok = filePath.match(regExpInclude); - } - if (ok && regExpExclude) { - ok = !filePath.match(regExpExclude); - } - - if (ok && (!file.exclusionRegExp || - !file.exclusionRegExp.test(fileObj.getName()))) { - files.push(filePath); - } - } else if (fileObj.isDirectory() && - (!file.exclusionRegExp || !file.exclusionRegExp.test(fileObj.getName()))) { - dirFiles = this.getFilteredFileList(fileObj, regExpFilters, makeUnixPaths, true); - files.push.apply(files, dirFiles); - } - } - } - - return files; //Array - }, - - copyDir: function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) { - //summary: copies files from srcDir to destDir using the regExpFilter to determine if the - //file should be copied. Returns a list file name strings of the destinations that were copied. - regExpFilter = regExpFilter || /\w/; - - var fileNames = file.getFilteredFileList(srcDir, regExpFilter, true), - copiedFiles = [], i, srcFileName, destFileName; - - for (i = 0; i < fileNames.length; i++) { - srcFileName = fileNames[i]; - destFileName = srcFileName.replace(srcDir, destDir); - - if (file.copyFile(srcFileName, destFileName, onlyCopyNew)) { - copiedFiles.push(destFileName); - } - } - - return copiedFiles.length ? copiedFiles : null; //Array or null - }, - - copyFile: function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) { - //summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if - //srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred. - var destFile = new java.io.File(destFileName), srcFile, parentDir, - srcChannel, destChannel; - - //logger.trace("Src filename: " + srcFileName); - //logger.trace("Dest filename: " + destFileName); - - //If onlyCopyNew is true, then compare dates and only copy if the src is newer - //than dest. - if (onlyCopyNew) { - srcFile = new java.io.File(srcFileName); - if (destFile.exists() && destFile.lastModified() >= srcFile.lastModified()) { - return false; //Boolean - } - } - - //Make sure destination dir exists. - parentDir = destFile.getParentFile(); - if (!parentDir.exists()) { - if (!parentDir.mkdirs()) { - throw "Could not create directory: " + parentDir.getCanonicalPath(); - } - } - - //Java's version of copy file. - srcChannel = new java.io.FileInputStream(srcFileName).getChannel(); - destChannel = new java.io.FileOutputStream(destFileName).getChannel(); - destChannel.transferFrom(srcChannel, 0, srcChannel.size()); - srcChannel.close(); - destChannel.close(); - - return true; //Boolean - }, - - /** - * Renames a file. May fail if "to" already exists or is on another drive. - */ - renameFile: function (from, to) { - return (new java.io.File(from)).renameTo((new java.io.File(to))); - }, - - readFile: function (/*String*/path, /*String?*/encoding) { - //A file read function that can deal with BOMs - encoding = encoding || "utf-8"; - var fileObj = new java.io.File(path), - input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(fileObj), encoding)), - stringBuffer, line; - try { - stringBuffer = new java.lang.StringBuffer(); - line = input.readLine(); - - // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324 - // http://www.unicode.org/faq/utf_bom.html - - // Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK: - // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058 - if (line && line.length() && line.charAt(0) === 0xfeff) { - // Eat the BOM, since we've already found the encoding on this file, - // and we plan to concatenating this buffer with others; the BOM should - // only appear at the top of a file. - line = line.substring(1); - } - while (line !== null) { - stringBuffer.append(line); - stringBuffer.append(file.lineSeparator); - line = input.readLine(); - } - //Make sure we return a JavaScript string and not a Java string. - return String(stringBuffer.toString()); //String - } finally { - input.close(); - } - }, - - saveUtf8File: function (/*String*/fileName, /*String*/fileContents) { - //summary: saves a file using UTF-8 encoding. - file.saveFile(fileName, fileContents, "utf-8"); - }, - - saveFile: function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) { - //summary: saves a file. - var outFile = new java.io.File(fileName), outWriter, parentDir, os; - - parentDir = outFile.getAbsoluteFile().getParentFile(); - if (!parentDir.exists()) { - if (!parentDir.mkdirs()) { - throw "Could not create directory: " + parentDir.getAbsolutePath(); - } - } - - if (encoding) { - outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile), encoding); - } else { - outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile)); - } - - os = new java.io.BufferedWriter(outWriter); - try { - os.write(fileContents); - } finally { - os.close(); - } - }, - - deleteFile: function (/*String*/fileName) { - //summary: deletes a file or directory if it exists. - var fileObj = new java.io.File(fileName), files, i; - if (fileObj.exists()) { - if (fileObj.isDirectory()) { - files = fileObj.listFiles(); - for (i = 0; i < files.length; i++) { - this.deleteFile(files[i]); - } - } - fileObj["delete"](); - } - }, - - /** - * Deletes any empty directories under the given directory. - * The startDirIsJavaObject is private to this implementation's - * recursion needs. - */ - deleteEmptyDirs: function (startDir, startDirIsJavaObject) { - var topDir = startDir, - dirFileArray, i, fileObj; - - if (!startDirIsJavaObject) { - topDir = new java.io.File(startDir); - } - - if (topDir.exists()) { - dirFileArray = topDir.listFiles(); - for (i = 0; i < dirFileArray.length; i++) { - fileObj = dirFileArray[i]; - if (fileObj.isDirectory()) { - file.deleteEmptyDirs(fileObj, true); - } - } - - //If the directory is empty now, delete it. - if (topDir.listFiles().length === 0) { - file.deleteFile(String(topDir.getPath())); - } - } - } - }; - - return file; -}); - -} - -if(env === 'node') { -/*global process */ -define('node/quit', function () { - 'use strict'; - return function (code) { - return process.exit(code); - }; -}); -} - -if(env === 'rhino') { -/*global quit */ -define('rhino/quit', function () { - 'use strict'; - return function (code) { - return quit(code); - }; -}); - -} -/** - * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint plusplus: true */ -/*global define */ - -define('lang', function () { - 'use strict'; - - var lang = { - backSlashRegExp: /\\/g, - ostring: Object.prototype.toString, - - isArray: Array.isArray || function (it) { - return lang.ostring.call(it) === "[object Array]"; - }, - - isFunction: function(it) { - return lang.ostring.call(it) === "[object Function]"; - }, - - isRegExp: function(it) { - return it && it instanceof RegExp; - }, - - _mixin: function(dest, source, override){ - var name; - for (name in source) { - if(source.hasOwnProperty(name) - && (override || !dest.hasOwnProperty(name))) { - dest[name] = source[name]; - } - } - - return dest; // Object - }, - - /** - * mixin({}, obj1, obj2) is allowed. If the last argument is a boolean, - * then the source objects properties are force copied over to dest. - */ - mixin: function(dest){ - var parameters = Array.prototype.slice.call(arguments), - override, i, l; - - if (!dest) { dest = {}; } - - if (parameters.length > 2 && typeof arguments[parameters.length-1] === 'boolean') { - override = parameters.pop(); - } - - for (i = 1, l = parameters.length; i < l; i++) { - lang._mixin(dest, parameters[i], override); - } - return dest; // Object - }, - - delegate: (function () { - // boodman/crockford delegation w/ cornford optimization - function TMP() {} - return function (obj, props) { - TMP.prototype = obj; - var tmp = new TMP(); - TMP.prototype = null; - if (props) { - lang.mixin(tmp, props); - } - return tmp; // Object - }; - }()), - - /** - * Helper function for iterating over an array. If the func returns - * a true value, it will break out of the loop. - */ - each: function each(ary, func) { - if (ary) { - var i; - for (i = 0; i < ary.length; i += 1) { - if (func(ary[i], i, ary)) { - break; - } - } - } - }, - - /** - * Cycles over properties in an object and calls a function for each - * property value. If the function returns a truthy value, then the - * iteration is stopped. - */ - eachProp: function eachProp(obj, func) { - var prop; - for (prop in obj) { - if (obj.hasOwnProperty(prop)) { - if (func(obj[prop], prop)) { - break; - } - } - } - }, - - //Similar to Function.prototype.bind, but the "this" object is specified - //first, since it is easier to read/figure out what "this" will be. - bind: function bind(obj, fn) { - return function () { - return fn.apply(obj, arguments); - }; - }, - - //Escapes a content string to be be a string that has characters escaped - //for inclusion as part of a JS string. - jsEscape: function (content) { - return content.replace(/(["'\\])/g, '\\$1') - .replace(/[\f]/g, "\\f") - .replace(/[\b]/g, "\\b") - .replace(/[\n]/g, "\\n") - .replace(/[\t]/g, "\\t") - .replace(/[\r]/g, "\\r"); - } - }; - return lang; -}); - -if(env === 'node') { -/** - * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint strict: false */ -/*global define: false, console: false */ - -define('node/print', function () { - function print(msg) { - console.log(msg); - } - - return print; -}); - -} - -if(env === 'rhino') { -/** - * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint strict: false */ -/*global define: false, print: false */ - -define('rhino/print', function () { - return print; -}); - -} -/** - * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint nomen: false, strict: false */ -/*global define: false */ - -define('logger', ['env!env/print'], function (print) { - var logger = { - TRACE: 0, - INFO: 1, - WARN: 2, - ERROR: 3, - SILENT: 4, - level: 0, - logPrefix: "", - - logLevel: function( level ) { - this.level = level; - }, - - trace: function (message) { - if (this.level <= this.TRACE) { - this._print(message); - } - }, - - info: function (message) { - if (this.level <= this.INFO) { - this._print(message); - } - }, - - warn: function (message) { - if (this.level <= this.WARN) { - this._print(message); - } - }, - - error: function (message) { - if (this.level <= this.ERROR) { - this._print(message); - } - }, - - _print: function (message) { - this._sysPrint((this.logPrefix ? (this.logPrefix + " ") : "") + message); - }, - - _sysPrint: function (message) { - print(message); - } - }; - - return logger; -}); -//Just a blank file to use when building the optimizer with the optimizer, -//so that the build does not attempt to inline some env modules, -//like Node's fs and path. - -//Just a blank file to use when building the optimizer with the optimizer, -//so that the build does not attempt to inline some env modules, -//like Node's fs and path. - -//Commit d72ed0a000c455290fde6f8114fe38f4aaf31469 on May 15, 2012 -define('esprima', ['exports'], function(exports) { -/* - Copyright (C) 2012 Ariya Hidayat - Copyright (C) 2012 Mathias Bynens - Copyright (C) 2012 Joost-Wim Boekesteijn - Copyright (C) 2012 Kris Kowal - Copyright (C) 2012 Yusuke Suzuki - Copyright (C) 2012 Arpad Borsos - Copyright (C) 2011 Ariya Hidayat - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/*jslint bitwise:true plusplus:true */ -/*global esprima:true, exports:true, -throwError: true, createLiteral: true, generateStatement: true, -parseAssignmentExpression: true, parseBlock: true, parseExpression: true, -parseFunctionDeclaration: true, parseFunctionExpression: true, -parseFunctionSourceElements: true, parseVariableIdentifier: true, -parseLeftHandSideExpression: true, -parseStatement: true, parseSourceElement: true */ - -(function (exports) { - 'use strict'; - - var Token, - TokenName, - Syntax, - PropertyKind, - Messages, - Regex, - source, - strict, - index, - lineNumber, - lineStart, - length, - buffer, - state, - extra; - - Token = { - BooleanLiteral: 1, - EOF: 2, - Identifier: 3, - Keyword: 4, - NullLiteral: 5, - NumericLiteral: 6, - Punctuator: 7, - StringLiteral: 8 - }; - - TokenName = {}; - TokenName[Token.BooleanLiteral] = 'Boolean'; - TokenName[Token.EOF] = ''; - TokenName[Token.Identifier] = 'Identifier'; - TokenName[Token.Keyword] = 'Keyword'; - TokenName[Token.NullLiteral] = 'Null'; - TokenName[Token.NumericLiteral] = 'Numeric'; - TokenName[Token.Punctuator] = 'Punctuator'; - TokenName[Token.StringLiteral] = 'String'; - - Syntax = { - AssignmentExpression: 'AssignmentExpression', - ArrayExpression: 'ArrayExpression', - BlockStatement: 'BlockStatement', - BinaryExpression: 'BinaryExpression', - BreakStatement: 'BreakStatement', - CallExpression: 'CallExpression', - CatchClause: 'CatchClause', - ConditionalExpression: 'ConditionalExpression', - ContinueStatement: 'ContinueStatement', - DoWhileStatement: 'DoWhileStatement', - DebuggerStatement: 'DebuggerStatement', - EmptyStatement: 'EmptyStatement', - ExpressionStatement: 'ExpressionStatement', - ForStatement: 'ForStatement', - ForInStatement: 'ForInStatement', - FunctionDeclaration: 'FunctionDeclaration', - FunctionExpression: 'FunctionExpression', - Identifier: 'Identifier', - IfStatement: 'IfStatement', - Literal: 'Literal', - LabeledStatement: 'LabeledStatement', - LogicalExpression: 'LogicalExpression', - MemberExpression: 'MemberExpression', - NewExpression: 'NewExpression', - ObjectExpression: 'ObjectExpression', - Program: 'Program', - Property: 'Property', - ReturnStatement: 'ReturnStatement', - SequenceExpression: 'SequenceExpression', - SwitchStatement: 'SwitchStatement', - SwitchCase: 'SwitchCase', - ThisExpression: 'ThisExpression', - ThrowStatement: 'ThrowStatement', - TryStatement: 'TryStatement', - UnaryExpression: 'UnaryExpression', - UpdateExpression: 'UpdateExpression', - VariableDeclaration: 'VariableDeclaration', - VariableDeclarator: 'VariableDeclarator', - WhileStatement: 'WhileStatement', - WithStatement: 'WithStatement' - }; - - PropertyKind = { - Data: 1, - Get: 2, - Set: 4 - }; - - // Error messages should be identical to V8. - Messages = { - UnexpectedToken: 'Unexpected token %0', - UnexpectedNumber: 'Unexpected number', - UnexpectedString: 'Unexpected string', - UnexpectedIdentifier: 'Unexpected identifier', - UnexpectedReserved: 'Unexpected reserved word', - UnexpectedEOS: 'Unexpected end of input', - NewlineAfterThrow: 'Illegal newline after throw', - InvalidRegExp: 'Invalid regular expression', - UnterminatedRegExp: 'Invalid regular expression: missing /', - InvalidLHSInAssignment: 'Invalid left-hand side in assignment', - InvalidLHSInForIn: 'Invalid left-hand side in for-in', - NoCatchOrFinally: 'Missing catch or finally after try', - UnknownLabel: 'Undefined label \'%0\'', - Redeclaration: '%0 \'%1\' has already been declared', - IllegalContinue: 'Illegal continue statement', - IllegalBreak: 'Illegal break statement', - IllegalReturn: 'Illegal return statement', - StrictModeWith: 'Strict mode code may not include a with statement', - StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', - StrictVarName: 'Variable name may not be eval or arguments in strict mode', - StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', - StrictParamDupe: 'Strict mode function may not have duplicate parameter names', - StrictFunctionName: 'Function name may not be eval or arguments in strict mode', - StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', - StrictDelete: 'Delete of an unqualified identifier in strict mode.', - StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode', - AccessorDataProperty: 'Object literal may not have data and accessor property with the same name', - AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name', - StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', - StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', - StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', - StrictReservedWord: 'Use of future reserved word in strict mode' - }; - - // See also tools/generate-unicode-regex.py. - Regex = { - NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'), - NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]') - }; - - // Ensure the condition is true, otherwise throw an error. - // This is only to have a better contract semantic, i.e. another safety net - // to catch a logic error. The condition shall be fulfilled in normal case. - // Do NOT use this to enforce a certain condition on any user input. - - function assert(condition, message) { - if (!condition) { - throw new Error('ASSERT: ' + message); - } - } - - function sliceSource(from, to) { - return source.slice(from, to); - } - - if (typeof 'esprima'[0] === 'undefined') { - sliceSource = function sliceArraySource(from, to) { - return source.slice(from, to).join(''); - }; - } - - function isDecimalDigit(ch) { - return '0123456789'.indexOf(ch) >= 0; - } - - function isHexDigit(ch) { - return '0123456789abcdefABCDEF'.indexOf(ch) >= 0; - } - - function isOctalDigit(ch) { - return '01234567'.indexOf(ch) >= 0; - } - - - // 7.2 White Space - - function isWhiteSpace(ch) { - return (ch === ' ') || (ch === '\u0009') || (ch === '\u000B') || - (ch === '\u000C') || (ch === '\u00A0') || - (ch.charCodeAt(0) >= 0x1680 && - '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(ch) >= 0); - } - - // 7.3 Line Terminators - - function isLineTerminator(ch) { - return (ch === '\n' || ch === '\r' || ch === '\u2028' || ch === '\u2029'); - } - - // 7.6 Identifier Names and Identifiers - - function isIdentifierStart(ch) { - return (ch === '$') || (ch === '_') || (ch === '\\') || - (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || - ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierStart.test(ch)); - } - - function isIdentifierPart(ch) { - return (ch === '$') || (ch === '_') || (ch === '\\') || - (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || - ((ch >= '0') && (ch <= '9')) || - ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierPart.test(ch)); - } - - // 7.6.1.2 Future Reserved Words - - function isFutureReservedWord(id) { - switch (id) { - - // Future reserved words. - case 'class': - case 'enum': - case 'export': - case 'extends': - case 'import': - case 'super': - return true; - } - - return false; - } - - function isStrictModeReservedWord(id) { - switch (id) { - - // Strict Mode reserved words. - case 'implements': - case 'interface': - case 'package': - case 'private': - case 'protected': - case 'public': - case 'static': - case 'yield': - case 'let': - return true; - } - - return false; - } - - function isRestrictedWord(id) { - return id === 'eval' || id === 'arguments'; - } - - // 7.6.1.1 Keywords - - function isKeyword(id) { - var keyword = false; - switch (id.length) { - case 2: - keyword = (id === 'if') || (id === 'in') || (id === 'do'); - break; - case 3: - keyword = (id === 'var') || (id === 'for') || (id === 'new') || (id === 'try'); - break; - case 4: - keyword = (id === 'this') || (id === 'else') || (id === 'case') || (id === 'void') || (id === 'with'); - break; - case 5: - keyword = (id === 'while') || (id === 'break') || (id === 'catch') || (id === 'throw'); - break; - case 6: - keyword = (id === 'return') || (id === 'typeof') || (id === 'delete') || (id === 'switch'); - break; - case 7: - keyword = (id === 'default') || (id === 'finally'); - break; - case 8: - keyword = (id === 'function') || (id === 'continue') || (id === 'debugger'); - break; - case 10: - keyword = (id === 'instanceof'); - break; - } - - if (keyword) { - return true; - } - - switch (id) { - // Future reserved words. - // 'const' is specialized as Keyword in V8. - case 'const': - return true; - - // For compatiblity to SpiderMonkey and ES.next - case 'yield': - case 'let': - return true; - } - - if (strict && isStrictModeReservedWord(id)) { - return true; - } - - return isFutureReservedWord(id); - } - - // Return the next character and move forward. - - function nextChar() { - return source[index++]; - } - - // 7.4 Comments - - function skipComment() { - var ch, blockComment, lineComment; - - blockComment = false; - lineComment = false; - - while (index < length) { - ch = source[index]; - - if (lineComment) { - ch = nextChar(); - if (isLineTerminator(ch)) { - lineComment = false; - if (ch === '\r' && source[index] === '\n') { - ++index; - } - ++lineNumber; - lineStart = index; - } - } else if (blockComment) { - if (isLineTerminator(ch)) { - if (ch === '\r' && source[index + 1] === '\n') { - ++index; - } - ++lineNumber; - ++index; - lineStart = index; - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } else { - ch = nextChar(); - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - if (ch === '*') { - ch = source[index]; - if (ch === '/') { - ++index; - blockComment = false; - } - } - } - } else if (ch === '/') { - ch = source[index + 1]; - if (ch === '/') { - index += 2; - lineComment = true; - } else if (ch === '*') { - index += 2; - blockComment = true; - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } else { - break; - } - } else if (isWhiteSpace(ch)) { - ++index; - } else if (isLineTerminator(ch)) { - ++index; - if (ch === '\r' && source[index] === '\n') { - ++index; - } - ++lineNumber; - lineStart = index; - } else { - break; - } - } - } - - function scanHexEscape(prefix) { - var i, len, ch, code = 0; - - len = (prefix === 'u') ? 4 : 2; - for (i = 0; i < len; ++i) { - if (index < length && isHexDigit(source[index])) { - ch = nextChar(); - code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); - } else { - return ''; - } - } - return String.fromCharCode(code); - } - - function scanIdentifier() { - var ch, start, id, restore; - - ch = source[index]; - if (!isIdentifierStart(ch)) { - return; - } - - start = index; - if (ch === '\\') { - ++index; - if (source[index] !== 'u') { - return; - } - ++index; - restore = index; - ch = scanHexEscape('u'); - if (ch) { - if (ch === '\\' || !isIdentifierStart(ch)) { - return; - } - id = ch; - } else { - index = restore; - id = 'u'; - } - } else { - id = nextChar(); - } - - while (index < length) { - ch = source[index]; - if (!isIdentifierPart(ch)) { - break; - } - if (ch === '\\') { - ++index; - if (source[index] !== 'u') { - return; - } - ++index; - restore = index; - ch = scanHexEscape('u'); - if (ch) { - if (ch === '\\' || !isIdentifierPart(ch)) { - return; - } - id += ch; - } else { - index = restore; - id += 'u'; - } - } else { - id += nextChar(); - } - } - - // There is no keyword or literal with only one character. - // Thus, it must be an identifier. - if (id.length === 1) { - return { - type: Token.Identifier, - value: id, - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - if (isKeyword(id)) { - return { - type: Token.Keyword, - value: id, - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - // 7.8.1 Null Literals - - if (id === 'null') { - return { - type: Token.NullLiteral, - value: id, - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - // 7.8.2 Boolean Literals - - if (id === 'true' || id === 'false') { - return { - type: Token.BooleanLiteral, - value: id, - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - return { - type: Token.Identifier, - value: id, - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - // 7.7 Punctuators - - function scanPunctuator() { - var start = index, - ch1 = source[index], - ch2, - ch3, - ch4; - - // Check for most common single-character punctuators. - - if (ch1 === ';' || ch1 === '{' || ch1 === '}') { - ++index; - return { - type: Token.Punctuator, - value: ch1, - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - if (ch1 === ',' || ch1 === '(' || ch1 === ')') { - ++index; - return { - type: Token.Punctuator, - value: ch1, - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - // Dot (.) can also start a floating-point number, hence the need - // to check the next character. - - ch2 = source[index + 1]; - if (ch1 === '.' && !isDecimalDigit(ch2)) { - return { - type: Token.Punctuator, - value: nextChar(), - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - // Peek more characters. - - ch3 = source[index + 2]; - ch4 = source[index + 3]; - - // 4-character punctuator: >>>= - - if (ch1 === '>' && ch2 === '>' && ch3 === '>') { - if (ch4 === '=') { - index += 4; - return { - type: Token.Punctuator, - value: '>>>=', - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - } - - // 3-character punctuators: === !== >>> <<= >>= - - if (ch1 === '=' && ch2 === '=' && ch3 === '=') { - index += 3; - return { - type: Token.Punctuator, - value: '===', - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - if (ch1 === '!' && ch2 === '=' && ch3 === '=') { - index += 3; - return { - type: Token.Punctuator, - value: '!==', - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - if (ch1 === '>' && ch2 === '>' && ch3 === '>') { - index += 3; - return { - type: Token.Punctuator, - value: '>>>', - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - if (ch1 === '<' && ch2 === '<' && ch3 === '=') { - index += 3; - return { - type: Token.Punctuator, - value: '<<=', - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - if (ch1 === '>' && ch2 === '>' && ch3 === '=') { - index += 3; - return { - type: Token.Punctuator, - value: '>>=', - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - // 2-character punctuators: <= >= == != ++ -- << >> && || - // += -= *= %= &= |= ^= /= - - if (ch2 === '=') { - if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) { - index += 2; - return { - type: Token.Punctuator, - value: ch1 + ch2, - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - } - - if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) { - if ('+-<>&|'.indexOf(ch2) >= 0) { - index += 2; - return { - type: Token.Punctuator, - value: ch1 + ch2, - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - } - - // The remaining 1-character punctuators. - - if ('[]<>+-*%&|^!~?:=/'.indexOf(ch1) >= 0) { - return { - type: Token.Punctuator, - value: nextChar(), - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - } - - // 7.8.3 Numeric Literals - - function scanNumericLiteral() { - var number, start, ch; - - ch = source[index]; - assert(isDecimalDigit(ch) || (ch === '.'), - 'Numeric literal must start with a decimal digit or a decimal point'); - - start = index; - number = ''; - if (ch !== '.') { - number = nextChar(); - ch = source[index]; - - // Hex number starts with '0x'. - // Octal number starts with '0'. - if (number === '0') { - if (ch === 'x' || ch === 'X') { - number += nextChar(); - while (index < length) { - ch = source[index]; - if (!isHexDigit(ch)) { - break; - } - number += nextChar(); - } - - if (number.length <= 2) { - // only 0x - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - - if (index < length) { - ch = source[index]; - if (isIdentifierStart(ch)) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } - return { - type: Token.NumericLiteral, - value: parseInt(number, 16), - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } else if (isOctalDigit(ch)) { - number += nextChar(); - while (index < length) { - ch = source[index]; - if (!isOctalDigit(ch)) { - break; - } - number += nextChar(); - } - - if (index < length) { - ch = source[index]; - if (isIdentifierStart(ch) || isDecimalDigit(ch)) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } - return { - type: Token.NumericLiteral, - value: parseInt(number, 8), - octal: true, - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - // decimal number starts with '0' such as '09' is illegal. - if (isDecimalDigit(ch)) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } - - while (index < length) { - ch = source[index]; - if (!isDecimalDigit(ch)) { - break; - } - number += nextChar(); - } - } - - if (ch === '.') { - number += nextChar(); - while (index < length) { - ch = source[index]; - if (!isDecimalDigit(ch)) { - break; - } - number += nextChar(); - } - } - - if (ch === 'e' || ch === 'E') { - number += nextChar(); - - ch = source[index]; - if (ch === '+' || ch === '-') { - number += nextChar(); - } - - ch = source[index]; - if (isDecimalDigit(ch)) { - number += nextChar(); - while (index < length) { - ch = source[index]; - if (!isDecimalDigit(ch)) { - break; - } - number += nextChar(); - } - } else { - ch = 'character ' + ch; - if (index >= length) { - ch = ''; - } - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } - - if (index < length) { - ch = source[index]; - if (isIdentifierStart(ch)) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } - - return { - type: Token.NumericLiteral, - value: parseFloat(number), - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - // 7.8.4 String Literals - - function scanStringLiteral() { - var str = '', quote, start, ch, code, unescaped, restore, octal = false; - - quote = source[index]; - assert((quote === '\'' || quote === '"'), - 'String literal must starts with a quote'); - - start = index; - ++index; - - while (index < length) { - ch = nextChar(); - - if (ch === quote) { - quote = ''; - break; - } else if (ch === '\\') { - ch = nextChar(); - if (!isLineTerminator(ch)) { - switch (ch) { - case 'n': - str += '\n'; - break; - case 'r': - str += '\r'; - break; - case 't': - str += '\t'; - break; - case 'u': - case 'x': - restore = index; - unescaped = scanHexEscape(ch); - if (unescaped) { - str += unescaped; - } else { - index = restore; - str += ch; - } - break; - case 'b': - str += '\b'; - break; - case 'f': - str += '\f'; - break; - case 'v': - str += '\v'; - break; - - default: - if (isOctalDigit(ch)) { - code = '01234567'.indexOf(ch); - - // \0 is not octal escape sequence - if (code !== 0) { - octal = true; - } - - if (index < length && isOctalDigit(source[index])) { - octal = true; - code = code * 8 + '01234567'.indexOf(nextChar()); - - // 3 digits are only allowed when string starts - // with 0, 1, 2, 3 - if ('0123'.indexOf(ch) >= 0 && - index < length && - isOctalDigit(source[index])) { - code = code * 8 + '01234567'.indexOf(nextChar()); - } - } - str += String.fromCharCode(code); - } else { - str += ch; - } - break; - } - } else { - ++lineNumber; - if (ch === '\r' && source[index] === '\n') { - ++index; - } - } - } else if (isLineTerminator(ch)) { - break; - } else { - str += ch; - } - } - - if (quote !== '') { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - - return { - type: Token.StringLiteral, - value: str, - octal: octal, - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; - } - - function scanRegExp() { - var str = '', ch, start, pattern, flags, value, classMarker = false, restore; - - buffer = null; - skipComment(); - - start = index; - ch = source[index]; - assert(ch === '/', 'Regular expression literal must start with a slash'); - str = nextChar(); - - while (index < length) { - ch = nextChar(); - str += ch; - if (classMarker) { - if (ch === ']') { - classMarker = false; - } - } else { - if (ch === '\\') { - ch = nextChar(); - // ECMA-262 7.8.5 - if (isLineTerminator(ch)) { - throwError({}, Messages.UnterminatedRegExp); - } - str += ch; - } - else if (ch === '/') { - break; - } - else if (ch === '[') { - classMarker = true; - } - else if (isLineTerminator(ch)) { - throwError({}, Messages.UnterminatedRegExp); - } - } - } - - if (str.length === 1) { - throwError({}, Messages.UnterminatedRegExp); - } - - // Exclude leading and trailing slash. - pattern = str.substr(1, str.length - 2); - - flags = ''; - while (index < length) { - ch = source[index]; - if (!isIdentifierPart(ch)) { - break; - } - - ++index; - if (ch === '\\' && index < length) { - ch = source[index]; - if (ch === 'u') { - ++index; - restore = index; - ch = scanHexEscape('u'); - if (ch) { - flags += ch; - str += '\\u'; - for (; restore < index; ++restore) { - str += source[restore]; - } - } else { - index = restore; - flags += 'u'; - str += '\\u'; - } - } else { - str += '\\'; - } - } else { - flags += ch; - str += ch; - } - } - - try { - value = new RegExp(pattern, flags); - } catch (e) { - throwError({}, Messages.InvalidRegExp); - } - - return { - literal: str, - value: value, - range: [start, index] - }; - } - - function isIdentifierName(token) { - return token.type === Token.Identifier || - token.type === Token.Keyword || - token.type === Token.BooleanLiteral || - token.type === Token.NullLiteral; - } - - function advance() { - var ch, token; - - skipComment(); - - if (index >= length) { - return { - type: Token.EOF, - lineNumber: lineNumber, - lineStart: lineStart, - range: [index, index] - }; - } - - token = scanPunctuator(); - if (typeof token !== 'undefined') { - return token; - } - - ch = source[index]; - - if (ch === '\'' || ch === '"') { - return scanStringLiteral(); - } - - if (ch === '.' || isDecimalDigit(ch)) { - return scanNumericLiteral(); - } - - token = scanIdentifier(); - if (typeof token !== 'undefined') { - return token; - } - - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - - function lex() { - var token; - - if (buffer) { - index = buffer.range[1]; - lineNumber = buffer.lineNumber; - lineStart = buffer.lineStart; - token = buffer; - buffer = null; - return token; - } - - buffer = null; - return advance(); - } - - function lookahead() { - var pos, line, start; - - if (buffer !== null) { - return buffer; - } - - pos = index; - line = lineNumber; - start = lineStart; - buffer = advance(); - index = pos; - lineNumber = line; - lineStart = start; - - return buffer; - } - - // Return true if there is a line terminator before the next token. - - function peekLineTerminator() { - var pos, line, start, found; - - pos = index; - line = lineNumber; - start = lineStart; - skipComment(); - found = lineNumber !== line; - index = pos; - lineNumber = line; - lineStart = start; - - return found; - } - - // Throw an exception - - function throwError(token, messageFormat) { - var error, - args = Array.prototype.slice.call(arguments, 2), - msg = messageFormat.replace( - /%(\d)/g, - function (whole, index) { - return args[index] || ''; - } - ); - - if (typeof token.lineNumber === 'number') { - error = new Error('Line ' + token.lineNumber + ': ' + msg); - error.index = token.range[0]; - error.lineNumber = token.lineNumber; - error.column = token.range[0] - lineStart + 1; - } else { - error = new Error('Line ' + lineNumber + ': ' + msg); - error.index = index; - error.lineNumber = lineNumber; - error.column = index - lineStart + 1; - } - - throw error; - } - - function throwErrorTolerant() { - var error; - try { - throwError.apply(null, arguments); - } catch (e) { - if (extra.errors) { - extra.errors.push(e); - } else { - throw e; - } - } - } - - - // Throw an exception because of the token. - - function throwUnexpected(token) { - var s; - - if (token.type === Token.EOF) { - throwError(token, Messages.UnexpectedEOS); - } - - if (token.type === Token.NumericLiteral) { - throwError(token, Messages.UnexpectedNumber); - } - - if (token.type === Token.StringLiteral) { - throwError(token, Messages.UnexpectedString); - } - - if (token.type === Token.Identifier) { - throwError(token, Messages.UnexpectedIdentifier); - } - - if (token.type === Token.Keyword) { - if (isFutureReservedWord(token.value)) { - throwError(token, Messages.UnexpectedReserved); - } else if (strict && isStrictModeReservedWord(token.value)) { - throwError(token, Messages.StrictReservedWord); - } - throwError(token, Messages.UnexpectedToken, token.value); - } - - // BooleanLiteral, NullLiteral, or Punctuator. - throwError(token, Messages.UnexpectedToken, token.value); - } - - // Expect the next token to match the specified punctuator. - // If not, an exception will be thrown. - - function expect(value) { - var token = lex(); - if (token.type !== Token.Punctuator || token.value !== value) { - throwUnexpected(token); - } - } - - // Expect the next token to match the specified keyword. - // If not, an exception will be thrown. - - function expectKeyword(keyword) { - var token = lex(); - if (token.type !== Token.Keyword || token.value !== keyword) { - throwUnexpected(token); - } - } - - // Return true if the next token matches the specified punctuator. - - function match(value) { - var token = lookahead(); - return token.type === Token.Punctuator && token.value === value; - } - - // Return true if the next token matches the specified keyword - - function matchKeyword(keyword) { - var token = lookahead(); - return token.type === Token.Keyword && token.value === keyword; - } - - // Return true if the next token is an assignment operator - - function matchAssign() { - var token = lookahead(), - op = token.value; - - if (token.type !== Token.Punctuator) { - return false; - } - return op === '=' || - op === '*=' || - op === '/=' || - op === '%=' || - op === '+=' || - op === '-=' || - op === '<<=' || - op === '>>=' || - op === '>>>=' || - op === '&=' || - op === '^=' || - op === '|='; - } - - function consumeSemicolon() { - var token, line; - - // Catch the very common case first. - if (source[index] === ';') { - lex(); - return; - } - - line = lineNumber; - skipComment(); - if (lineNumber !== line) { - return; - } - - if (match(';')) { - lex(); - return; - } - - token = lookahead(); - if (token.type !== Token.EOF && !match('}')) { - throwUnexpected(token); - } - return; - } - - // Return true if provided expression is LeftHandSideExpression - - function isLeftHandSide(expr) { - switch (expr.type) { - case 'AssignmentExpression': - case 'BinaryExpression': - case 'ConditionalExpression': - case 'LogicalExpression': - case 'SequenceExpression': - case 'UnaryExpression': - case 'UpdateExpression': - return false; - } - return true; - } - - // 11.1.4 Array Initialiser - - function parseArrayInitialiser() { - var elements = [], - undef; - - expect('['); - - while (!match(']')) { - if (match(',')) { - lex(); - elements.push(undef); - } else { - elements.push(parseAssignmentExpression()); - - if (!match(']')) { - expect(','); - } - } - } - - expect(']'); - - return { - type: Syntax.ArrayExpression, - elements: elements - }; - } - - // 11.1.5 Object Initialiser - - function parsePropertyFunction(param, first) { - var previousStrict, body; - - previousStrict = strict; - body = parseFunctionSourceElements(); - if (first && strict && isRestrictedWord(param[0].name)) { - throwError(first, Messages.StrictParamName); - } - strict = previousStrict; - - return { - type: Syntax.FunctionExpression, - id: null, - params: param, - body: body - }; - } - - function parseObjectPropertyKey() { - var token = lex(); - - // Note: This function is called only from parseObjectProperty(), where - // EOF and Punctuator tokens are already filtered out. - - if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) { - if (strict && token.octal) { - throwError(token, Messages.StrictOctalLiteral); - } - return createLiteral(token); - } - - return { - type: Syntax.Identifier, - name: token.value - }; - } - - function parseObjectProperty() { - var token, key, id, param; - - token = lookahead(); - - if (token.type === Token.Identifier) { - - id = parseObjectPropertyKey(); - - // Property Assignment: Getter and Setter. - - if (token.value === 'get' && !match(':')) { - key = parseObjectPropertyKey(); - expect('('); - expect(')'); - return { - type: Syntax.Property, - key: key, - value: parsePropertyFunction([]), - kind: 'get' - }; - } else if (token.value === 'set' && !match(':')) { - key = parseObjectPropertyKey(); - expect('('); - token = lookahead(); - if (token.type !== Token.Identifier) { - throwUnexpected(lex()); - } - param = [ parseVariableIdentifier() ]; - expect(')'); - return { - type: Syntax.Property, - key: key, - value: parsePropertyFunction(param, token), - kind: 'set' - }; - } else { - expect(':'); - return { - type: Syntax.Property, - key: id, - value: parseAssignmentExpression(), - kind: 'init' - }; - } - } else if (token.type === Token.EOF || token.type === Token.Punctuator) { - throwUnexpected(token); - } else { - key = parseObjectPropertyKey(); - expect(':'); - return { - type: Syntax.Property, - key: key, - value: parseAssignmentExpression(), - kind: 'init' - }; - } - } - - function parseObjectInitialiser() { - var token, properties = [], property, name, kind, map = {}, toString = String; - - expect('{'); - - while (!match('}')) { - property = parseObjectProperty(); - - if (property.key.type === Syntax.Identifier) { - name = property.key.name; - } else { - name = toString(property.key.value); - } - kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set; - if (Object.prototype.hasOwnProperty.call(map, name)) { - if (map[name] === PropertyKind.Data) { - if (strict && kind === PropertyKind.Data) { - throwErrorTolerant({}, Messages.StrictDuplicateProperty); - } else if (kind !== PropertyKind.Data) { - throwError({}, Messages.AccessorDataProperty); - } - } else { - if (kind === PropertyKind.Data) { - throwError({}, Messages.AccessorDataProperty); - } else if (map[name] & kind) { - throwError({}, Messages.AccessorGetSet); - } - } - map[name] |= kind; - } else { - map[name] = kind; - } - - properties.push(property); - - if (!match('}')) { - expect(','); - } - } - - expect('}'); - - return { - type: Syntax.ObjectExpression, - properties: properties - }; - } - - // 11.1 Primary Expressions - - function parsePrimaryExpression() { - var expr, - token = lookahead(), - type = token.type; - - if (type === Token.Identifier) { - return { - type: Syntax.Identifier, - name: lex().value - }; - } - - if (type === Token.StringLiteral || type === Token.NumericLiteral) { - if (strict && token.octal) { - throwErrorTolerant(token, Messages.StrictOctalLiteral); - } - return createLiteral(lex()); - } - - if (type === Token.Keyword) { - if (matchKeyword('this')) { - lex(); - return { - type: Syntax.ThisExpression - }; - } - - if (matchKeyword('function')) { - return parseFunctionExpression(); - } - } - - if (type === Token.BooleanLiteral) { - lex(); - token.value = (token.value === 'true'); - return createLiteral(token); - } - - if (type === Token.NullLiteral) { - lex(); - token.value = null; - return createLiteral(token); - } - - if (match('[')) { - return parseArrayInitialiser(); - } - - if (match('{')) { - return parseObjectInitialiser(); - } - - if (match('(')) { - lex(); - state.lastParenthesized = expr = parseExpression(); - expect(')'); - return expr; - } - - if (match('/') || match('/=')) { - return createLiteral(scanRegExp()); - } - - return throwUnexpected(lex()); - } - - // 11.2 Left-Hand-Side Expressions - - function parseArguments() { - var args = []; - - expect('('); - - if (!match(')')) { - while (index < length) { - args.push(parseAssignmentExpression()); - if (match(')')) { - break; - } - expect(','); - } - } - - expect(')'); - - return args; - } - - function parseNonComputedProperty() { - var token = lex(); - - if (!isIdentifierName(token)) { - throwUnexpected(token); - } - - return { - type: Syntax.Identifier, - name: token.value - }; - } - - function parseNonComputedMember(object) { - return { - type: Syntax.MemberExpression, - computed: false, - object: object, - property: parseNonComputedProperty() - }; - } - - function parseComputedMember(object) { - var property, expr; - - expect('['); - property = parseExpression(); - expr = { - type: Syntax.MemberExpression, - computed: true, - object: object, - property: property - }; - expect(']'); - return expr; - } - - function parseCallMember(object) { - return { - type: Syntax.CallExpression, - callee: object, - 'arguments': parseArguments() - }; - } - - function parseNewExpression() { - var expr; - - expectKeyword('new'); - - expr = { - type: Syntax.NewExpression, - callee: parseLeftHandSideExpression(), - 'arguments': [] - }; - - if (match('(')) { - expr['arguments'] = parseArguments(); - } - - return expr; - } - - function parseLeftHandSideExpressionAllowCall() { - var useNew, expr; - - useNew = matchKeyword('new'); - expr = useNew ? parseNewExpression() : parsePrimaryExpression(); - - while (index < length) { - if (match('.')) { - lex(); - expr = parseNonComputedMember(expr); - } else if (match('[')) { - expr = parseComputedMember(expr); - } else if (match('(')) { - expr = parseCallMember(expr); - } else { - break; - } - } - - return expr; - } - - function parseLeftHandSideExpression() { - var useNew, expr; - - useNew = matchKeyword('new'); - expr = useNew ? parseNewExpression() : parsePrimaryExpression(); - - while (index < length) { - if (match('.')) { - lex(); - expr = parseNonComputedMember(expr); - } else if (match('[')) { - expr = parseComputedMember(expr); - } else { - break; - } - } - - return expr; - } - - // 11.3 Postfix Expressions - - function parsePostfixExpression() { - var expr = parseLeftHandSideExpressionAllowCall(); - - if ((match('++') || match('--')) && !peekLineTerminator()) { - // 11.3.1, 11.3.2 - if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { - throwError({}, Messages.StrictLHSPostfix); - } - expr = { - type: Syntax.UpdateExpression, - operator: lex().value, - argument: expr, - prefix: false - }; - } - - return expr; - } - - // 11.4 Unary Operators - - function parseUnaryExpression() { - var token, expr; - - if (match('++') || match('--')) { - token = lex(); - expr = parseUnaryExpression(); - // 11.4.4, 11.4.5 - if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { - throwError({}, Messages.StrictLHSPrefix); - } - expr = { - type: Syntax.UpdateExpression, - operator: token.value, - argument: expr, - prefix: true - }; - return expr; - } - - if (match('+') || match('-') || match('~') || match('!')) { - expr = { - type: Syntax.UnaryExpression, - operator: lex().value, - argument: parseUnaryExpression() - }; - return expr; - } - - if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) { - expr = { - type: Syntax.UnaryExpression, - operator: lex().value, - argument: parseUnaryExpression() - }; - if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) { - throwErrorTolerant({}, Messages.StrictDelete); - } - return expr; - } - - return parsePostfixExpression(); - } - - // 11.5 Multiplicative Operators - - function parseMultiplicativeExpression() { - var expr = parseUnaryExpression(); - - while (match('*') || match('/') || match('%')) { - expr = { - type: Syntax.BinaryExpression, - operator: lex().value, - left: expr, - right: parseUnaryExpression() - }; - } - - return expr; - } - - // 11.6 Additive Operators - - function parseAdditiveExpression() { - var expr = parseMultiplicativeExpression(); - - while (match('+') || match('-')) { - expr = { - type: Syntax.BinaryExpression, - operator: lex().value, - left: expr, - right: parseMultiplicativeExpression() - }; - } - - return expr; - } - - // 11.7 Bitwise Shift Operators - - function parseShiftExpression() { - var expr = parseAdditiveExpression(); - - while (match('<<') || match('>>') || match('>>>')) { - expr = { - type: Syntax.BinaryExpression, - operator: lex().value, - left: expr, - right: parseAdditiveExpression() - }; - } - - return expr; - } - // 11.8 Relational Operators - - function parseRelationalExpression() { - var expr, previousAllowIn; - - previousAllowIn = state.allowIn; - state.allowIn = true; - expr = parseShiftExpression(); - state.allowIn = previousAllowIn; - - if (match('<') || match('>') || match('<=') || match('>=')) { - expr = { - type: Syntax.BinaryExpression, - operator: lex().value, - left: expr, - right: parseRelationalExpression() - }; - } else if (state.allowIn && matchKeyword('in')) { - lex(); - expr = { - type: Syntax.BinaryExpression, - operator: 'in', - left: expr, - right: parseRelationalExpression() - }; - } else if (matchKeyword('instanceof')) { - lex(); - expr = { - type: Syntax.BinaryExpression, - operator: 'instanceof', - left: expr, - right: parseRelationalExpression() - }; - } - - return expr; - } - - // 11.9 Equality Operators - - function parseEqualityExpression() { - var expr = parseRelationalExpression(); - - while (match('==') || match('!=') || match('===') || match('!==')) { - expr = { - type: Syntax.BinaryExpression, - operator: lex().value, - left: expr, - right: parseRelationalExpression() - }; - } - - return expr; - } - - // 11.10 Binary Bitwise Operators - - function parseBitwiseANDExpression() { - var expr = parseEqualityExpression(); - - while (match('&')) { - lex(); - expr = { - type: Syntax.BinaryExpression, - operator: '&', - left: expr, - right: parseEqualityExpression() - }; - } - - return expr; - } - - function parseBitwiseORExpression() { - var expr = parseBitwiseANDExpression(); - - while (match('|')) { - lex(); - expr = { - type: Syntax.BinaryExpression, - operator: '|', - left: expr, - right: parseBitwiseANDExpression() - }; - } - - return expr; - } - - function parseBitwiseXORExpression() { - var expr = parseBitwiseORExpression(); - - while (match('^')) { - lex(); - expr = { - type: Syntax.BinaryExpression, - operator: '^', - left: expr, - right: parseBitwiseORExpression() - }; - } - - return expr; - } - - // 11.11 Binary Logical Operators - - function parseLogicalANDExpression() { - var expr = parseBitwiseXORExpression(); - - while (match('&&')) { - lex(); - expr = { - type: Syntax.LogicalExpression, - operator: '&&', - left: expr, - right: parseBitwiseXORExpression() - }; - } - - return expr; - } - - function parseLogicalORExpression() { - var expr = parseLogicalANDExpression(); - - while (match('||')) { - lex(); - expr = { - type: Syntax.LogicalExpression, - operator: '||', - left: expr, - right: parseLogicalANDExpression() - }; - } - - return expr; - } - - // 11.12 Conditional Operator - - function parseConditionalExpression() { - var expr, previousAllowIn, consequent; - - expr = parseLogicalORExpression(); - - if (match('?')) { - lex(); - previousAllowIn = state.allowIn; - state.allowIn = true; - consequent = parseAssignmentExpression(); - state.allowIn = previousAllowIn; - expect(':'); - - expr = { - type: Syntax.ConditionalExpression, - test: expr, - consequent: consequent, - alternate: parseAssignmentExpression() - }; - } - - return expr; - } - - // 11.13 Assignment Operators - - function parseAssignmentExpression() { - var expr; - - expr = parseConditionalExpression(); - - if (matchAssign()) { - // LeftHandSideExpression - if (state.lastParenthesized !== expr && !isLeftHandSide(expr)) { - throwError({}, Messages.InvalidLHSInAssignment); - } - - // 11.13.1 - if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { - throwError({}, Messages.StrictLHSAssignment); - } - - expr = { - type: Syntax.AssignmentExpression, - operator: lex().value, - left: expr, - right: parseAssignmentExpression() - }; - } - - return expr; - } - - // 11.14 Comma Operator - - function parseExpression() { - var expr = parseAssignmentExpression(); - - if (match(',')) { - expr = { - type: Syntax.SequenceExpression, - expressions: [ expr ] - }; - - while (index < length) { - if (!match(',')) { - break; - } - lex(); - expr.expressions.push(parseAssignmentExpression()); - } - - } - return expr; - } - - // 12.1 Block - - function parseStatementList() { - var list = [], - statement; - - while (index < length) { - if (match('}')) { - break; - } - statement = parseSourceElement(); - if (typeof statement === 'undefined') { - break; - } - list.push(statement); - } - - return list; - } - - function parseBlock() { - var block; - - expect('{'); - - block = parseStatementList(); - - expect('}'); - - return { - type: Syntax.BlockStatement, - body: block - }; - } - - // 12.2 Variable Statement - - function parseVariableIdentifier() { - var token = lex(); - - if (token.type !== Token.Identifier) { - throwUnexpected(token); - } - - return { - type: Syntax.Identifier, - name: token.value - }; - } - - function parseVariableDeclaration(kind) { - var id = parseVariableIdentifier(), - init = null; - - // 12.2.1 - if (strict && isRestrictedWord(id.name)) { - throwErrorTolerant({}, Messages.StrictVarName); - } - - if (kind === 'const') { - expect('='); - init = parseAssignmentExpression(); - } else if (match('=')) { - lex(); - init = parseAssignmentExpression(); - } - - return { - type: Syntax.VariableDeclarator, - id: id, - init: init - }; - } - - function parseVariableDeclarationList(kind) { - var list = []; - - while (index < length) { - list.push(parseVariableDeclaration(kind)); - if (!match(',')) { - break; - } - lex(); - } - - return list; - } - - function parseVariableStatement() { - var declarations; - - expectKeyword('var'); - - declarations = parseVariableDeclarationList(); - - consumeSemicolon(); - - return { - type: Syntax.VariableDeclaration, - declarations: declarations, - kind: 'var' - }; - } - - // kind may be `const` or `let` - // Both are experimental and not in the specification yet. - // see http://wiki.ecmascript.org/doku.php?id=harmony:const - // and http://wiki.ecmascript.org/doku.php?id=harmony:let - function parseConstLetDeclaration(kind) { - var declarations; - - expectKeyword(kind); - - declarations = parseVariableDeclarationList(kind); - - consumeSemicolon(); - - return { - type: Syntax.VariableDeclaration, - declarations: declarations, - kind: kind - }; - } - - // 12.3 Empty Statement - - function parseEmptyStatement() { - expect(';'); - - return { - type: Syntax.EmptyStatement - }; - } - - // 12.4 Expression Statement - - function parseExpressionStatement() { - var expr = parseExpression(); - - consumeSemicolon(); - - return { - type: Syntax.ExpressionStatement, - expression: expr - }; - } - - // 12.5 If statement - - function parseIfStatement() { - var test, consequent, alternate; - - expectKeyword('if'); - - expect('('); - - test = parseExpression(); - - expect(')'); - - consequent = parseStatement(); - - if (matchKeyword('else')) { - lex(); - alternate = parseStatement(); - } else { - alternate = null; - } - - return { - type: Syntax.IfStatement, - test: test, - consequent: consequent, - alternate: alternate - }; - } - - // 12.6 Iteration Statements - - function parseDoWhileStatement() { - var body, test, oldInIteration; - - expectKeyword('do'); - - oldInIteration = state.inIteration; - state.inIteration = true; - - body = parseStatement(); - - state.inIteration = oldInIteration; - - expectKeyword('while'); - - expect('('); - - test = parseExpression(); - - expect(')'); - - if (match(';')) { - lex(); - } - - return { - type: Syntax.DoWhileStatement, - body: body, - test: test - }; - } - - function parseWhileStatement() { - var test, body, oldInIteration; - - expectKeyword('while'); - - expect('('); - - test = parseExpression(); - - expect(')'); - - oldInIteration = state.inIteration; - state.inIteration = true; - - body = parseStatement(); - - state.inIteration = oldInIteration; - - return { - type: Syntax.WhileStatement, - test: test, - body: body - }; - } - - function parseForVariableDeclaration() { - var token = lex(); - - return { - type: Syntax.VariableDeclaration, - declarations: parseVariableDeclarationList(), - kind: token.value - }; - } - - function parseForStatement() { - var init, test, update, left, right, body, oldInIteration; - - init = test = update = null; - - expectKeyword('for'); - - expect('('); - - if (match(';')) { - lex(); - } else { - if (matchKeyword('var') || matchKeyword('let')) { - state.allowIn = false; - init = parseForVariableDeclaration(); - state.allowIn = true; - - if (init.declarations.length === 1 && matchKeyword('in')) { - lex(); - left = init; - right = parseExpression(); - init = null; - } - } else { - state.allowIn = false; - init = parseExpression(); - state.allowIn = true; - - if (matchKeyword('in')) { - // LeftHandSideExpression - if (matchKeyword('in') && (state.lastParenthesized !== init && !isLeftHandSide(init))) { - throwError({}, Messages.InvalidLHSInForIn); - } - lex(); - left = init; - right = parseExpression(); - init = null; - } - } - - if (typeof left === 'undefined') { - expect(';'); - } - } - - if (typeof left === 'undefined') { - - if (!match(';')) { - test = parseExpression(); - } - expect(';'); - - if (!match(')')) { - update = parseExpression(); - } - } - - expect(')'); - - oldInIteration = state.inIteration; - state.inIteration = true; - - body = parseStatement(); - - state.inIteration = oldInIteration; - - if (typeof left === 'undefined') { - return { - type: Syntax.ForStatement, - init: init, - test: test, - update: update, - body: body - }; - } - - return { - type: Syntax.ForInStatement, - left: left, - right: right, - body: body, - each: false - }; - } - - // 12.7 The continue statement - - function parseContinueStatement() { - var token, label = null; - - expectKeyword('continue'); - - // Optimize the most common form: 'continue;'. - if (source[index] === ';') { - lex(); - - if (!state.inIteration) { - throwError({}, Messages.IllegalContinue); - } - - return { - type: Syntax.ContinueStatement, - label: null - }; - } - - if (peekLineTerminator()) { - if (!state.inIteration) { - throwError({}, Messages.IllegalContinue); - } - - return { - type: Syntax.ContinueStatement, - label: null - }; - } - - token = lookahead(); - if (token.type === Token.Identifier) { - label = parseVariableIdentifier(); - - if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) { - throwError({}, Messages.UnknownLabel, label.name); - } - } - - consumeSemicolon(); - - if (label === null && !state.inIteration) { - throwError({}, Messages.IllegalContinue); - } - - return { - type: Syntax.ContinueStatement, - label: label - }; - } - - // 12.8 The break statement - - function parseBreakStatement() { - var token, label = null; - - expectKeyword('break'); - - // Optimize the most common form: 'break;'. - if (source[index] === ';') { - lex(); - - if (!(state.inIteration || state.inSwitch)) { - throwError({}, Messages.IllegalBreak); - } - - return { - type: Syntax.BreakStatement, - label: null - }; - } - - if (peekLineTerminator()) { - if (!(state.inIteration || state.inSwitch)) { - throwError({}, Messages.IllegalBreak); - } - - return { - type: Syntax.BreakStatement, - label: null - }; - } - - token = lookahead(); - if (token.type === Token.Identifier) { - label = parseVariableIdentifier(); - - if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) { - throwError({}, Messages.UnknownLabel, label.name); - } - } - - consumeSemicolon(); - - if (label === null && !(state.inIteration || state.inSwitch)) { - throwError({}, Messages.IllegalBreak); - } - - return { - type: Syntax.BreakStatement, - label: label - }; - } - - // 12.9 The return statement - - function parseReturnStatement() { - var token, argument = null; - - expectKeyword('return'); - - if (!state.inFunctionBody) { - throwErrorTolerant({}, Messages.IllegalReturn); - } - - // 'return' followed by a space and an identifier is very common. - if (source[index] === ' ') { - if (isIdentifierStart(source[index + 1])) { - argument = parseExpression(); - consumeSemicolon(); - return { - type: Syntax.ReturnStatement, - argument: argument - }; - } - } - - if (peekLineTerminator()) { - return { - type: Syntax.ReturnStatement, - argument: null - }; - } - - if (!match(';')) { - token = lookahead(); - if (!match('}') && token.type !== Token.EOF) { - argument = parseExpression(); - } - } - - consumeSemicolon(); - - return { - type: Syntax.ReturnStatement, - argument: argument - }; - } - - // 12.10 The with statement - - function parseWithStatement() { - var object, body; - - if (strict) { - throwErrorTolerant({}, Messages.StrictModeWith); - } - - expectKeyword('with'); - - expect('('); - - object = parseExpression(); - - expect(')'); - - body = parseStatement(); - - return { - type: Syntax.WithStatement, - object: object, - body: body - }; - } - - // 12.10 The swith statement - - function parseSwitchCase() { - var test, - consequent = [], - statement; - - if (matchKeyword('default')) { - lex(); - test = null; - } else { - expectKeyword('case'); - test = parseExpression(); - } - expect(':'); - - while (index < length) { - if (match('}') || matchKeyword('default') || matchKeyword('case')) { - break; - } - statement = parseStatement(); - if (typeof statement === 'undefined') { - break; - } - consequent.push(statement); - } - - return { - type: Syntax.SwitchCase, - test: test, - consequent: consequent - }; - } - - function parseSwitchStatement() { - var discriminant, cases, oldInSwitch; - - expectKeyword('switch'); - - expect('('); - - discriminant = parseExpression(); - - expect(')'); - - expect('{'); - - if (match('}')) { - lex(); - return { - type: Syntax.SwitchStatement, - discriminant: discriminant - }; - } - - cases = []; - - oldInSwitch = state.inSwitch; - state.inSwitch = true; - - while (index < length) { - if (match('}')) { - break; - } - cases.push(parseSwitchCase()); - } - - state.inSwitch = oldInSwitch; - - expect('}'); - - return { - type: Syntax.SwitchStatement, - discriminant: discriminant, - cases: cases - }; - } - - // 12.13 The throw statement - - function parseThrowStatement() { - var argument; - - expectKeyword('throw'); - - if (peekLineTerminator()) { - throwError({}, Messages.NewlineAfterThrow); - } - - argument = parseExpression(); - - consumeSemicolon(); - - return { - type: Syntax.ThrowStatement, - argument: argument - }; - } - - // 12.14 The try statement - - function parseCatchClause() { - var param; - - expectKeyword('catch'); - - expect('('); - if (!match(')')) { - param = parseExpression(); - // 12.14.1 - if (strict && param.type === Syntax.Identifier && isRestrictedWord(param.name)) { - throwErrorTolerant({}, Messages.StrictCatchVariable); - } - } - expect(')'); - - return { - type: Syntax.CatchClause, - param: param, - guard: null, - body: parseBlock() - }; - } - - function parseTryStatement() { - var block, handlers = [], finalizer = null; - - expectKeyword('try'); - - block = parseBlock(); - - if (matchKeyword('catch')) { - handlers.push(parseCatchClause()); - } - - if (matchKeyword('finally')) { - lex(); - finalizer = parseBlock(); - } - - if (handlers.length === 0 && !finalizer) { - throwError({}, Messages.NoCatchOrFinally); - } - - return { - type: Syntax.TryStatement, - block: block, - handlers: handlers, - finalizer: finalizer - }; - } - - // 12.15 The debugger statement - - function parseDebuggerStatement() { - expectKeyword('debugger'); - - consumeSemicolon(); - - return { - type: Syntax.DebuggerStatement - }; - } - - // 12 Statements - - function parseStatement() { - var token = lookahead(), - expr, - labeledBody; - - if (token.type === Token.EOF) { - throwUnexpected(token); - } - - if (token.type === Token.Punctuator) { - switch (token.value) { - case ';': - return parseEmptyStatement(); - case '{': - return parseBlock(); - case '(': - return parseExpressionStatement(); - default: - break; - } - } - - if (token.type === Token.Keyword) { - switch (token.value) { - case 'break': - return parseBreakStatement(); - case 'continue': - return parseContinueStatement(); - case 'debugger': - return parseDebuggerStatement(); - case 'do': - return parseDoWhileStatement(); - case 'for': - return parseForStatement(); - case 'function': - return parseFunctionDeclaration(); - case 'if': - return parseIfStatement(); - case 'return': - return parseReturnStatement(); - case 'switch': - return parseSwitchStatement(); - case 'throw': - return parseThrowStatement(); - case 'try': - return parseTryStatement(); - case 'var': - return parseVariableStatement(); - case 'while': - return parseWhileStatement(); - case 'with': - return parseWithStatement(); - default: - break; - } - } - - expr = parseExpression(); - - // 12.12 Labelled Statements - if ((expr.type === Syntax.Identifier) && match(':')) { - lex(); - - if (Object.prototype.hasOwnProperty.call(state.labelSet, expr.name)) { - throwError({}, Messages.Redeclaration, 'Label', expr.name); - } - - state.labelSet[expr.name] = true; - labeledBody = parseStatement(); - delete state.labelSet[expr.name]; - - return { - type: Syntax.LabeledStatement, - label: expr, - body: labeledBody - }; - } - - consumeSemicolon(); - - return { - type: Syntax.ExpressionStatement, - expression: expr - }; - } - - // 13 Function Definition - - function parseFunctionSourceElements() { - var sourceElement, sourceElements = [], token, directive, firstRestricted, - oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody; - - expect('{'); - - while (index < length) { - token = lookahead(); - if (token.type !== Token.StringLiteral) { - break; - } - - sourceElement = parseSourceElement(); - sourceElements.push(sourceElement); - if (sourceElement.expression.type !== Syntax.Literal) { - // this is not directive - break; - } - directive = sliceSource(token.range[0] + 1, token.range[1] - 1); - if (directive === 'use strict') { - strict = true; - if (firstRestricted) { - throwError(firstRestricted, Messages.StrictOctalLiteral); - } - } else { - if (!firstRestricted && token.octal) { - firstRestricted = token; - } - } - } - - oldLabelSet = state.labelSet; - oldInIteration = state.inIteration; - oldInSwitch = state.inSwitch; - oldInFunctionBody = state.inFunctionBody; - - state.labelSet = {}; - state.inIteration = false; - state.inSwitch = false; - state.inFunctionBody = true; - - while (index < length) { - if (match('}')) { - break; - } - sourceElement = parseSourceElement(); - if (typeof sourceElement === 'undefined') { - break; - } - sourceElements.push(sourceElement); - } - - expect('}'); - - state.labelSet = oldLabelSet; - state.inIteration = oldInIteration; - state.inSwitch = oldInSwitch; - state.inFunctionBody = oldInFunctionBody; - - return { - type: Syntax.BlockStatement, - body: sourceElements - }; - } - - function parseFunctionDeclaration() { - var id, param, params = [], body, token, firstRestricted, message, previousStrict, paramSet; - - expectKeyword('function'); - token = lookahead(); - id = parseVariableIdentifier(); - if (strict) { - if (isRestrictedWord(token.value)) { - throwError(token, Messages.StrictFunctionName); - } - } else { - if (isRestrictedWord(token.value)) { - firstRestricted = token; - message = Messages.StrictFunctionName; - } else if (isStrictModeReservedWord(token.value)) { - firstRestricted = token; - message = Messages.StrictReservedWord; - } - } - - expect('('); - - if (!match(')')) { - paramSet = {}; - while (index < length) { - token = lookahead(); - param = parseVariableIdentifier(); - if (strict) { - if (isRestrictedWord(token.value)) { - throwError(token, Messages.StrictParamName); - } - if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) { - throwError(token, Messages.StrictParamDupe); - } - } else if (!firstRestricted) { - if (isRestrictedWord(token.value)) { - firstRestricted = token; - message = Messages.StrictParamName; - } else if (isStrictModeReservedWord(token.value)) { - firstRestricted = token; - message = Messages.StrictReservedWord; - } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) { - firstRestricted = token; - message = Messages.StrictParamDupe; - } - } - params.push(param); - paramSet[param.name] = true; - if (match(')')) { - break; - } - expect(','); - } - } - - expect(')'); - - previousStrict = strict; - body = parseFunctionSourceElements(); - if (strict && firstRestricted) { - throwError(firstRestricted, message); - } - strict = previousStrict; - - return { - type: Syntax.FunctionDeclaration, - id: id, - params: params, - body: body - }; - } - - function parseFunctionExpression() { - var token, id = null, firstRestricted, message, param, params = [], body, previousStrict, paramSet; - - expectKeyword('function'); - - if (!match('(')) { - token = lookahead(); - id = parseVariableIdentifier(); - if (strict) { - if (isRestrictedWord(token.value)) { - throwError(token, Messages.StrictFunctionName); - } - } else { - if (isRestrictedWord(token.value)) { - firstRestricted = token; - message = Messages.StrictFunctionName; - } else if (isStrictModeReservedWord(token.value)) { - firstRestricted = token; - message = Messages.StrictReservedWord; - } - } - } - - expect('('); - - if (!match(')')) { - paramSet = {}; - while (index < length) { - token = lookahead(); - param = parseVariableIdentifier(); - if (strict) { - if (isRestrictedWord(token.value)) { - throwError(token, Messages.StrictParamName); - } - if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) { - throwError(token, Messages.StrictParamDupe); - } - } else if (!firstRestricted) { - if (isRestrictedWord(token.value)) { - firstRestricted = token; - message = Messages.StrictParamName; - } else if (isStrictModeReservedWord(token.value)) { - firstRestricted = token; - message = Messages.StrictReservedWord; - } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) { - firstRestricted = token; - message = Messages.StrictParamDupe; - } - } - params.push(param); - paramSet[param.name] = true; - if (match(')')) { - break; - } - expect(','); - } - } - - expect(')'); - - previousStrict = strict; - body = parseFunctionSourceElements(); - if (strict && firstRestricted) { - throwError(firstRestricted, message); - } - strict = previousStrict; - - return { - type: Syntax.FunctionExpression, - id: id, - params: params, - body: body - }; - } - - // 14 Program - - function parseSourceElement() { - var token = lookahead(); - - if (token.type === Token.Keyword) { - switch (token.value) { - case 'const': - case 'let': - return parseConstLetDeclaration(token.value); - case 'function': - return parseFunctionDeclaration(); - default: - return parseStatement(); - } - } - - if (token.type !== Token.EOF) { - return parseStatement(); - } - } - - function parseSourceElements() { - var sourceElement, sourceElements = [], token, directive, firstRestricted; - - while (index < length) { - token = lookahead(); - if (token.type !== Token.StringLiteral) { - break; - } - - sourceElement = parseSourceElement(); - sourceElements.push(sourceElement); - if (sourceElement.expression.type !== Syntax.Literal) { - // this is not directive - break; - } - directive = sliceSource(token.range[0] + 1, token.range[1] - 1); - if (directive === 'use strict') { - strict = true; - if (firstRestricted) { - throwError(firstRestricted, Messages.StrictOctalLiteral); - } - } else { - if (!firstRestricted && token.octal) { - firstRestricted = token; - } - } - } - - while (index < length) { - sourceElement = parseSourceElement(); - if (typeof sourceElement === 'undefined') { - break; - } - sourceElements.push(sourceElement); - } - return sourceElements; - } - - function parseProgram() { - var program; - strict = false; - program = { - type: Syntax.Program, - body: parseSourceElements() - }; - return program; - } - - // The following functions are needed only when the option to preserve - // the comments is active. - - function addComment(start, end, type, value) { - assert(typeof start === 'number', 'Comment must have valid position'); - - // Because the way the actual token is scanned, often the comments - // (if any) are skipped twice during the lexical analysis. - // Thus, we need to skip adding a comment if the comment array already - // handled it. - if (extra.comments.length > 0) { - if (extra.comments[extra.comments.length - 1].range[1] > start) { - return; - } - } - - extra.comments.push({ - range: [start, end], - type: type, - value: value - }); - } - - function scanComment() { - var comment, ch, start, blockComment, lineComment; - - comment = ''; - blockComment = false; - lineComment = false; - - while (index < length) { - ch = source[index]; - - if (lineComment) { - ch = nextChar(); - if (index >= length) { - lineComment = false; - comment += ch; - addComment(start, index, 'Line', comment); - } else if (isLineTerminator(ch)) { - lineComment = false; - addComment(start, index, 'Line', comment); - if (ch === '\r' && source[index] === '\n') { - ++index; - } - ++lineNumber; - lineStart = index; - comment = ''; - } else { - comment += ch; - } - } else if (blockComment) { - if (isLineTerminator(ch)) { - if (ch === '\r' && source[index + 1] === '\n') { - ++index; - comment += '\r\n'; - } else { - comment += ch; - } - ++lineNumber; - ++index; - lineStart = index; - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } else { - ch = nextChar(); - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - comment += ch; - if (ch === '*') { - ch = source[index]; - if (ch === '/') { - comment = comment.substr(0, comment.length - 1); - blockComment = false; - ++index; - addComment(start, index, 'Block', comment); - comment = ''; - } - } - } - } else if (ch === '/') { - ch = source[index + 1]; - if (ch === '/') { - start = index; - index += 2; - lineComment = true; - } else if (ch === '*') { - start = index; - index += 2; - blockComment = true; - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } else { - break; - } - } else if (isWhiteSpace(ch)) { - ++index; - } else if (isLineTerminator(ch)) { - ++index; - if (ch === '\r' && source[index] === '\n') { - ++index; - } - ++lineNumber; - lineStart = index; - } else { - break; - } - } - } - - function collectToken() { - var token = extra.advance(), - range, - value; - - if (token.type !== Token.EOF) { - range = [token.range[0], token.range[1]]; - value = sliceSource(token.range[0], token.range[1]); - extra.tokens.push({ - type: TokenName[token.type], - value: value, - range: range - }); - } - - return token; - } - - function collectRegex() { - var pos, regex, token; - - skipComment(); - - pos = index; - regex = extra.scanRegExp(); - - // Pop the previous token, which is likely '/' or '/=' - if (extra.tokens.length > 0) { - token = extra.tokens[extra.tokens.length - 1]; - if (token.range[0] === pos && token.type === 'Punctuator') { - if (token.value === '/' || token.value === '/=') { - extra.tokens.pop(); - } - } - } - - extra.tokens.push({ - type: 'RegularExpression', - value: regex.literal, - range: [pos, index] - }); - - return regex; - } - - function createLiteral(token) { - return { - type: Syntax.Literal, - value: token.value - }; - } - - function createRawLiteral(token) { - return { - type: Syntax.Literal, - value: token.value, - raw: sliceSource(token.range[0], token.range[1]) - }; - } - - function wrapTrackingFunction(range, loc) { - - return function (parseFunction) { - - function isBinary(node) { - return node.type === Syntax.LogicalExpression || - node.type === Syntax.BinaryExpression; - } - - function visit(node) { - if (isBinary(node.left)) { - visit(node.left); - } - if (isBinary(node.right)) { - visit(node.right); - } - - if (range && typeof node.range === 'undefined') { - node.range = [node.left.range[0], node.right.range[1]]; - } - if (loc && typeof node.loc === 'undefined') { - node.loc = { - start: node.left.loc.start, - end: node.right.loc.end - }; - } - } - - return function () { - var node, rangeInfo, locInfo; - - skipComment(); - rangeInfo = [index, 0]; - locInfo = { - start: { - line: lineNumber, - column: index - lineStart - } - }; - - node = parseFunction.apply(null, arguments); - if (typeof node !== 'undefined') { - - if (range) { - rangeInfo[1] = index; - node.range = rangeInfo; - } - - if (loc) { - locInfo.end = { - line: lineNumber, - column: index - lineStart - }; - node.loc = locInfo; - } - - if (isBinary(node)) { - visit(node); - } - - if (node.type === Syntax.MemberExpression) { - if (typeof node.object.range !== 'undefined') { - node.range[0] = node.object.range[0]; - } - if (typeof node.object.loc !== 'undefined') { - node.loc.start = node.object.loc.start; - } - } - return node; - } - }; - - }; - } - - function patch() { - - var wrapTracking; - - if (extra.comments) { - extra.skipComment = skipComment; - skipComment = scanComment; - } - - if (extra.raw) { - extra.createLiteral = createLiteral; - createLiteral = createRawLiteral; - } - - if (extra.range || extra.loc) { - - wrapTracking = wrapTrackingFunction(extra.range, extra.loc); - - extra.parseAdditiveExpression = parseAdditiveExpression; - extra.parseAssignmentExpression = parseAssignmentExpression; - extra.parseBitwiseANDExpression = parseBitwiseANDExpression; - extra.parseBitwiseORExpression = parseBitwiseORExpression; - extra.parseBitwiseXORExpression = parseBitwiseXORExpression; - extra.parseBlock = parseBlock; - extra.parseFunctionSourceElements = parseFunctionSourceElements; - extra.parseCallMember = parseCallMember; - extra.parseCatchClause = parseCatchClause; - extra.parseComputedMember = parseComputedMember; - extra.parseConditionalExpression = parseConditionalExpression; - extra.parseConstLetDeclaration = parseConstLetDeclaration; - extra.parseEqualityExpression = parseEqualityExpression; - extra.parseExpression = parseExpression; - extra.parseForVariableDeclaration = parseForVariableDeclaration; - extra.parseFunctionDeclaration = parseFunctionDeclaration; - extra.parseFunctionExpression = parseFunctionExpression; - extra.parseLogicalANDExpression = parseLogicalANDExpression; - extra.parseLogicalORExpression = parseLogicalORExpression; - extra.parseMultiplicativeExpression = parseMultiplicativeExpression; - extra.parseNewExpression = parseNewExpression; - extra.parseNonComputedMember = parseNonComputedMember; - extra.parseNonComputedProperty = parseNonComputedProperty; - extra.parseObjectProperty = parseObjectProperty; - extra.parseObjectPropertyKey = parseObjectPropertyKey; - extra.parsePostfixExpression = parsePostfixExpression; - extra.parsePrimaryExpression = parsePrimaryExpression; - extra.parseProgram = parseProgram; - extra.parsePropertyFunction = parsePropertyFunction; - extra.parseRelationalExpression = parseRelationalExpression; - extra.parseStatement = parseStatement; - extra.parseShiftExpression = parseShiftExpression; - extra.parseSwitchCase = parseSwitchCase; - extra.parseUnaryExpression = parseUnaryExpression; - extra.parseVariableDeclaration = parseVariableDeclaration; - extra.parseVariableIdentifier = parseVariableIdentifier; - - parseAdditiveExpression = wrapTracking(extra.parseAdditiveExpression); - parseAssignmentExpression = wrapTracking(extra.parseAssignmentExpression); - parseBitwiseANDExpression = wrapTracking(extra.parseBitwiseANDExpression); - parseBitwiseORExpression = wrapTracking(extra.parseBitwiseORExpression); - parseBitwiseXORExpression = wrapTracking(extra.parseBitwiseXORExpression); - parseBlock = wrapTracking(extra.parseBlock); - parseFunctionSourceElements = wrapTracking(extra.parseFunctionSourceElements); - parseCallMember = wrapTracking(extra.parseCallMember); - parseCatchClause = wrapTracking(extra.parseCatchClause); - parseComputedMember = wrapTracking(extra.parseComputedMember); - parseConditionalExpression = wrapTracking(extra.parseConditionalExpression); - parseConstLetDeclaration = wrapTracking(extra.parseConstLetDeclaration); - parseEqualityExpression = wrapTracking(extra.parseEqualityExpression); - parseExpression = wrapTracking(extra.parseExpression); - parseForVariableDeclaration = wrapTracking(extra.parseForVariableDeclaration); - parseFunctionDeclaration = wrapTracking(extra.parseFunctionDeclaration); - parseFunctionExpression = wrapTracking(extra.parseFunctionExpression); - parseLogicalANDExpression = wrapTracking(extra.parseLogicalANDExpression); - parseLogicalORExpression = wrapTracking(extra.parseLogicalORExpression); - parseMultiplicativeExpression = wrapTracking(extra.parseMultiplicativeExpression); - parseNewExpression = wrapTracking(extra.parseNewExpression); - parseNonComputedMember = wrapTracking(extra.parseNonComputedMember); - parseNonComputedProperty = wrapTracking(extra.parseNonComputedProperty); - parseObjectProperty = wrapTracking(extra.parseObjectProperty); - parseObjectPropertyKey = wrapTracking(extra.parseObjectPropertyKey); - parsePostfixExpression = wrapTracking(extra.parsePostfixExpression); - parsePrimaryExpression = wrapTracking(extra.parsePrimaryExpression); - parseProgram = wrapTracking(extra.parseProgram); - parsePropertyFunction = wrapTracking(extra.parsePropertyFunction); - parseRelationalExpression = wrapTracking(extra.parseRelationalExpression); - parseStatement = wrapTracking(extra.parseStatement); - parseShiftExpression = wrapTracking(extra.parseShiftExpression); - parseSwitchCase = wrapTracking(extra.parseSwitchCase); - parseUnaryExpression = wrapTracking(extra.parseUnaryExpression); - parseVariableDeclaration = wrapTracking(extra.parseVariableDeclaration); - parseVariableIdentifier = wrapTracking(extra.parseVariableIdentifier); - } - - if (typeof extra.tokens !== 'undefined') { - extra.advance = advance; - extra.scanRegExp = scanRegExp; - - advance = collectToken; - scanRegExp = collectRegex; - } - } - - function unpatch() { - if (typeof extra.skipComment === 'function') { - skipComment = extra.skipComment; - } - - if (extra.raw) { - createLiteral = extra.createLiteral; - } - - if (extra.range || extra.loc) { - parseAdditiveExpression = extra.parseAdditiveExpression; - parseAssignmentExpression = extra.parseAssignmentExpression; - parseBitwiseANDExpression = extra.parseBitwiseANDExpression; - parseBitwiseORExpression = extra.parseBitwiseORExpression; - parseBitwiseXORExpression = extra.parseBitwiseXORExpression; - parseBlock = extra.parseBlock; - parseFunctionSourceElements = extra.parseFunctionSourceElements; - parseCallMember = extra.parseCallMember; - parseCatchClause = extra.parseCatchClause; - parseComputedMember = extra.parseComputedMember; - parseConditionalExpression = extra.parseConditionalExpression; - parseConstLetDeclaration = extra.parseConstLetDeclaration; - parseEqualityExpression = extra.parseEqualityExpression; - parseExpression = extra.parseExpression; - parseForVariableDeclaration = extra.parseForVariableDeclaration; - parseFunctionDeclaration = extra.parseFunctionDeclaration; - parseFunctionExpression = extra.parseFunctionExpression; - parseLogicalANDExpression = extra.parseLogicalANDExpression; - parseLogicalORExpression = extra.parseLogicalORExpression; - parseMultiplicativeExpression = extra.parseMultiplicativeExpression; - parseNewExpression = extra.parseNewExpression; - parseNonComputedMember = extra.parseNonComputedMember; - parseNonComputedProperty = extra.parseNonComputedProperty; - parseObjectProperty = extra.parseObjectProperty; - parseObjectPropertyKey = extra.parseObjectPropertyKey; - parsePrimaryExpression = extra.parsePrimaryExpression; - parsePostfixExpression = extra.parsePostfixExpression; - parseProgram = extra.parseProgram; - parsePropertyFunction = extra.parsePropertyFunction; - parseRelationalExpression = extra.parseRelationalExpression; - parseStatement = extra.parseStatement; - parseShiftExpression = extra.parseShiftExpression; - parseSwitchCase = extra.parseSwitchCase; - parseUnaryExpression = extra.parseUnaryExpression; - parseVariableDeclaration = extra.parseVariableDeclaration; - parseVariableIdentifier = extra.parseVariableIdentifier; - } - - if (typeof extra.scanRegExp === 'function') { - advance = extra.advance; - scanRegExp = extra.scanRegExp; - } - } - - function stringToArray(str) { - var length = str.length, - result = [], - i; - for (i = 0; i < length; ++i) { - result[i] = str.charAt(i); - } - return result; - } - - function parse(code, options) { - var program, toString; - - toString = String; - if (typeof code !== 'string' && !(code instanceof String)) { - code = toString(code); - } - - source = code; - index = 0; - lineNumber = (source.length > 0) ? 1 : 0; - lineStart = 0; - length = source.length; - buffer = null; - state = { - allowIn: true, - labelSet: {}, - lastParenthesized: null, - inFunctionBody: false, - inIteration: false, - inSwitch: false - }; - - extra = {}; - if (typeof options !== 'undefined') { - extra.range = (typeof options.range === 'boolean') && options.range; - extra.loc = (typeof options.loc === 'boolean') && options.loc; - extra.raw = (typeof options.raw === 'boolean') && options.raw; - if (typeof options.tokens === 'boolean' && options.tokens) { - extra.tokens = []; - } - if (typeof options.comment === 'boolean' && options.comment) { - extra.comments = []; - } - if (typeof options.tolerant === 'boolean' && options.tolerant) { - extra.errors = []; - } - } - - if (length > 0) { - if (typeof source[0] === 'undefined') { - // Try first to convert to a string. This is good as fast path - // for old IE which understands string indexing for string - // literals only and not for string object. - if (code instanceof String) { - source = code.valueOf(); - } - - // Force accessing the characters via an array. - if (typeof source[0] === 'undefined') { - source = stringToArray(code); - } - } - } - - patch(); - try { - program = parseProgram(); - if (typeof extra.comments !== 'undefined') { - program.comments = extra.comments; - } - if (typeof extra.tokens !== 'undefined') { - program.tokens = extra.tokens; - } - if (typeof extra.errors !== 'undefined') { - program.errors = extra.errors; - } - } catch (e) { - throw e; - } finally { - unpatch(); - extra = {}; - } - - return program; - } - - // Sync with package.json. - exports.version = '1.0.0-dev'; - - exports.parse = parse; - - // Deep copy. - exports.Syntax = (function () { - var name, types = {}; - - if (typeof Object.create === 'function') { - types = Object.create(null); - } - - for (name in Syntax) { - if (Syntax.hasOwnProperty(name)) { - types[name] = Syntax[name]; - } - } - - if (typeof Object.freeze === 'function') { - Object.freeze(types); - } - - return types; - }()); - -}(typeof exports === 'undefined' ? (esprima = {}) : exports)); -/* vim: set sw=4 ts=4 et tw=80 : */ -}); -define('uglifyjs/consolidator', ["require", "exports", "module", "./parse-js", "./process"], function(require, exports, module) { -/** - * @preserve Copyright 2012 Robert Gust-Bardon . - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/** - * @fileoverview Enhances UglifyJS with consolidation of null, Boolean, and String values. - *

Also known as aliasing, this feature has been deprecated in the Closure Compiler since its - * initial release, where it is unavailable from the CLI. The Closure Compiler allows one to log and - * influence this process. In contrast, this implementation does not introduce - * any variable declarations in global code and derives String values from - * identifier names used as property accessors.

- *

Consolidating literals may worsen the data compression ratio when an encoding - * transformation is applied. For instance, jQuery 1.7.1 takes 248235 bytes. - * Building it with - * UglifyJS v1.2.5 results in 93647 bytes (37.73% of the original) which are - * then compressed to 33154 bytes (13.36% of the original) using gzip(1). Building it with the same - * version of UglifyJS 1.2.5 patched with the implementation of consolidation - * results in 80784 bytes (a decrease of 12863 bytes, i.e. 13.74%, in comparison - * to the aforementioned 93647 bytes) which are then compressed to 34013 bytes - * (an increase of 859 bytes, i.e. 2.59%, in comparison to the aforementioned - * 33154 bytes).

- *

Written in the strict variant - * of ECMA-262 5.1 Edition. Encoded in UTF-8. Follows Revision 2.28 of the Google JavaScript Style Guide (except for the - * discouraged use of the {@code function} tag and the {@code namespace} tag). - * 100% typed for the Closure Compiler Version 1741.

- *

Should you find this software useful, please consider a donation.

- * @author follow.me@RGustBardon (Robert Gust-Bardon) - * @supported Tested with: - * - */ - -/*global console:false, exports:true, module:false, require:false */ -/*jshint sub:true */ -/** - * Consolidates null, Boolean, and String values found inside an AST. - * @param {!TSyntacticCodeUnit} oAbstractSyntaxTree An array-like object - * representing an AST. - * @return {!TSyntacticCodeUnit} An array-like object representing an AST with its null, Boolean, and - * String values consolidated. - */ -// TODO(user) Consolidation of mathematical values found in numeric literals. -// TODO(user) Unconsolidation. -// TODO(user) Consolidation of ECMA-262 6th Edition programs. -// TODO(user) Rewrite in ECMA-262 6th Edition. -exports['ast_consolidate'] = function(oAbstractSyntaxTree) { - 'use strict'; - /*jshint bitwise:true, curly:true, eqeqeq:true, forin:true, immed:true, - latedef:true, newcap:true, noarge:true, noempty:true, nonew:true, - onevar:true, plusplus:true, regexp:true, undef:true, strict:true, - sub:false, trailing:true */ - - var _, - /** - * A record consisting of data about one or more source elements. - * @constructor - * @nosideeffects - */ - TSourceElementsData = function() { - /** - * The category of the elements. - * @type {number} - * @see ESourceElementCategories - */ - this.nCategory = ESourceElementCategories.N_OTHER; - /** - * The number of occurrences (within the elements) of each primitive - * value that could be consolidated. - * @type {!Array.>} - */ - this.aCount = []; - this.aCount[EPrimaryExpressionCategories.N_IDENTIFIER_NAMES] = {}; - this.aCount[EPrimaryExpressionCategories.N_STRING_LITERALS] = {}; - this.aCount[EPrimaryExpressionCategories.N_NULL_AND_BOOLEAN_LITERALS] = - {}; - /** - * Identifier names found within the elements. - * @type {!Array.} - */ - this.aIdentifiers = []; - /** - * Prefixed representation Strings of each primitive value that could be - * consolidated within the elements. - * @type {!Array.} - */ - this.aPrimitiveValues = []; - }, - /** - * A record consisting of data about a primitive value that could be - * consolidated. - * @constructor - * @nosideeffects - */ - TPrimitiveValue = function() { - /** - * The difference in the number of terminal symbols between the original - * source text and the one with the primitive value consolidated. If the - * difference is positive, the primitive value is considered worthwhile. - * @type {number} - */ - this.nSaving = 0; - /** - * An identifier name of the variable that will be declared and assigned - * the primitive value if the primitive value is consolidated. - * @type {string} - */ - this.sName = ''; - }, - /** - * A record consisting of data on what to consolidate within the range of - * source elements that is currently being considered. - * @constructor - * @nosideeffects - */ - TSolution = function() { - /** - * An object whose keys are prefixed representation Strings of each - * primitive value that could be consolidated within the elements and - * whose values are corresponding data about those primitive values. - * @type {!Object.} - * @see TPrimitiveValue - */ - this.oPrimitiveValues = {}; - /** - * The difference in the number of terminal symbols between the original - * source text and the one with all the worthwhile primitive values - * consolidated. - * @type {number} - * @see TPrimitiveValue#nSaving - */ - this.nSavings = 0; - }, - /** - * The processor of ASTs found - * in UglifyJS. - * @namespace - * @type {!TProcessor} - */ - oProcessor = (/** @type {!TProcessor} */ require('./process')), - /** - * A record consisting of a number of constants that represent the - * difference in the number of terminal symbols between a source text with - * a modified syntactic code unit and the original one. - * @namespace - * @type {!Object.} - */ - oWeights = { - /** - * The difference in the number of punctuators required by the bracket - * notation and the dot notation. - *

'[]'.length - '.'.length

- * @const - * @type {number} - */ - N_PROPERTY_ACCESSOR: 1, - /** - * The number of punctuators required by a variable declaration with an - * initialiser. - *

':'.length + ';'.length

- * @const - * @type {number} - */ - N_VARIABLE_DECLARATION: 2, - /** - * The number of terminal symbols required to introduce a variable - * statement (excluding its variable declaration list). - *

'var '.length

- * @const - * @type {number} - */ - N_VARIABLE_STATEMENT_AFFIXATION: 4, - /** - * The number of terminal symbols needed to enclose source elements - * within a function call with no argument values to a function with an - * empty parameter list. - *

'(function(){}());'.length

- * @const - * @type {number} - */ - N_CLOSURE: 17 - }, - /** - * Categories of primary expressions from which primitive values that - * could be consolidated are derivable. - * @namespace - * @enum {number} - */ - EPrimaryExpressionCategories = { - /** - * Identifier names used as property accessors. - * @type {number} - */ - N_IDENTIFIER_NAMES: 0, - /** - * String literals. - * @type {number} - */ - N_STRING_LITERALS: 1, - /** - * Null and Boolean literals. - * @type {number} - */ - N_NULL_AND_BOOLEAN_LITERALS: 2 - }, - /** - * Prefixes of primitive values that could be consolidated. - * The String values of the prefixes must have same number of characters. - * The prefixes must not be used in any properties defined in any version - * of ECMA-262. - * @namespace - * @enum {string} - */ - EValuePrefixes = { - /** - * Identifies String values. - * @type {string} - */ - S_STRING: '#S', - /** - * Identifies null and Boolean values. - * @type {string} - */ - S_SYMBOLIC: '#O' - }, - /** - * Categories of source elements in terms of their appropriateness of - * having their primitive values consolidated. - * @namespace - * @enum {number} - */ - ESourceElementCategories = { - /** - * Identifies a source element that includes the {@code with} statement. - * @type {number} - */ - N_WITH: 0, - /** - * Identifies a source element that includes the {@code eval} identifier name. - * @type {number} - */ - N_EVAL: 1, - /** - * Identifies a source element that must be excluded from the process - * unless its whole scope is examined. - * @type {number} - */ - N_EXCLUDABLE: 2, - /** - * Identifies source elements not posing any problems. - * @type {number} - */ - N_OTHER: 3 - }, - /** - * The list of literals (other than the String ones) whose primitive - * values can be consolidated. - * @const - * @type {!Array.} - */ - A_OTHER_SUBSTITUTABLE_LITERALS = [ - 'null', // The null literal. - 'false', // The Boolean literal {@code false}. - 'true' // The Boolean literal {@code true}. - ]; - - (/** - * Consolidates all worthwhile primitive values in a syntactic code unit. - * @param {!TSyntacticCodeUnit} oSyntacticCodeUnit An array-like object - * representing the branch of the abstract syntax tree representing the - * syntactic code unit along with its scope. - * @see TPrimitiveValue#nSaving - */ - function fExamineSyntacticCodeUnit(oSyntacticCodeUnit) { - var _, - /** - * Indicates whether the syntactic code unit represents global code. - * @type {boolean} - */ - bIsGlobal = 'toplevel' === oSyntacticCodeUnit[0], - /** - * Indicates whether the whole scope is being examined. - * @type {boolean} - */ - bIsWhollyExaminable = !bIsGlobal, - /** - * An array-like object representing source elements that constitute a - * syntactic code unit. - * @type {!TSyntacticCodeUnit} - */ - oSourceElements, - /** - * A record consisting of data about the source element that is - * currently being examined. - * @type {!TSourceElementsData} - */ - oSourceElementData, - /** - * The scope of the syntactic code unit. - * @type {!TScope} - */ - oScope, - /** - * An instance of an object that allows the traversal of an AST. - * @type {!TWalker} - */ - oWalker, - /** - * An object encompassing collections of functions used during the - * traversal of an AST. - * @namespace - * @type {!Object.>} - */ - oWalkers = { - /** - * A collection of functions used during the surveyance of source - * elements. - * @namespace - * @type {!Object.} - */ - oSurveySourceElement: { - /**#nocode+*/ // JsDoc Toolkit 2.4.0 hides some of the keys. - /** - * Classifies the source element as excludable if it does not - * contain a {@code with} statement or the {@code eval} identifier - * name. Adds the identifier of the function and its formal - * parameters to the list of identifier names found. - * @param {string} sIdentifier The identifier of the function. - * @param {!Array.} aFormalParameterList Formal parameters. - * @param {!TSyntacticCodeUnit} oFunctionBody Function code. - */ - 'defun': function( - sIdentifier, - aFormalParameterList, - oFunctionBody) { - fClassifyAsExcludable(); - fAddIdentifier(sIdentifier); - aFormalParameterList.forEach(fAddIdentifier); - }, - /** - * Increments the count of the number of occurrences of the String - * value that is equivalent to the sequence of terminal symbols - * that constitute the encountered identifier name. - * @param {!TSyntacticCodeUnit} oExpression The nonterminal - * MemberExpression. - * @param {string} sIdentifierName The identifier name used as the - * property accessor. - * @return {!Array} The encountered branch of an AST with its nonterminal - * MemberExpression traversed. - */ - 'dot': function(oExpression, sIdentifierName) { - fCountPrimaryExpression( - EPrimaryExpressionCategories.N_IDENTIFIER_NAMES, - EValuePrefixes.S_STRING + sIdentifierName); - return ['dot', oWalker.walk(oExpression), sIdentifierName]; - }, - /** - * Adds the optional identifier of the function and its formal - * parameters to the list of identifier names found. - * @param {?string} sIdentifier The optional identifier of the - * function. - * @param {!Array.} aFormalParameterList Formal parameters. - * @param {!TSyntacticCodeUnit} oFunctionBody Function code. - */ - 'function': function( - sIdentifier, - aFormalParameterList, - oFunctionBody) { - if ('string' === typeof sIdentifier) { - fAddIdentifier(sIdentifier); - } - aFormalParameterList.forEach(fAddIdentifier); - }, - /** - * Either increments the count of the number of occurrences of the - * encountered null or Boolean value or classifies a source element - * as containing the {@code eval} identifier name. - * @param {string} sIdentifier The identifier encountered. - */ - 'name': function(sIdentifier) { - if (-1 !== A_OTHER_SUBSTITUTABLE_LITERALS.indexOf(sIdentifier)) { - fCountPrimaryExpression( - EPrimaryExpressionCategories.N_NULL_AND_BOOLEAN_LITERALS, - EValuePrefixes.S_SYMBOLIC + sIdentifier); - } else { - if ('eval' === sIdentifier) { - oSourceElementData.nCategory = - ESourceElementCategories.N_EVAL; - } - fAddIdentifier(sIdentifier); - } - }, - /** - * Classifies the source element as excludable if it does not - * contain a {@code with} statement or the {@code eval} identifier - * name. - * @param {TSyntacticCodeUnit} oExpression The expression whose - * value is to be returned. - */ - 'return': function(oExpression) { - fClassifyAsExcludable(); - }, - /** - * Increments the count of the number of occurrences of the - * encountered String value. - * @param {string} sStringValue The String value of the string - * literal encountered. - */ - 'string': function(sStringValue) { - if (sStringValue.length > 0) { - fCountPrimaryExpression( - EPrimaryExpressionCategories.N_STRING_LITERALS, - EValuePrefixes.S_STRING + sStringValue); - } - }, - /** - * Adds the identifier reserved for an exception to the list of - * identifier names found. - * @param {!TSyntacticCodeUnit} oTry A block of code in which an - * exception can occur. - * @param {Array} aCatch The identifier reserved for an exception - * and a block of code to handle the exception. - * @param {TSyntacticCodeUnit} oFinally An optional block of code - * to be evaluated regardless of whether an exception occurs. - */ - 'try': function(oTry, aCatch, oFinally) { - if (Array.isArray(aCatch)) { - fAddIdentifier(aCatch[0]); - } - }, - /** - * Classifies the source element as excludable if it does not - * contain a {@code with} statement or the {@code eval} identifier - * name. Adds the identifier of each declared variable to the list - * of identifier names found. - * @param {!Array.} aVariableDeclarationList Variable - * declarations. - */ - 'var': function(aVariableDeclarationList) { - fClassifyAsExcludable(); - aVariableDeclarationList.forEach(fAddVariable); - }, - /** - * Classifies a source element as containing the {@code with} - * statement. - * @param {!TSyntacticCodeUnit} oExpression An expression whose - * value is to be converted to a value of type Object and - * become the binding object of a new object environment - * record of a new lexical environment in which the statement - * is to be executed. - * @param {!TSyntacticCodeUnit} oStatement The statement to be - * executed in the augmented lexical environment. - * @return {!Array} An empty array to stop the traversal. - */ - 'with': function(oExpression, oStatement) { - oSourceElementData.nCategory = ESourceElementCategories.N_WITH; - return []; - } - /**#nocode-*/ // JsDoc Toolkit 2.4.0 hides some of the keys. - }, - /** - * A collection of functions used while looking for nested functions. - * @namespace - * @type {!Object.} - */ - oExamineFunctions: { - /**#nocode+*/ // JsDoc Toolkit 2.4.0 hides some of the keys. - /** - * Orders an examination of a nested function declaration. - * @this {!TSyntacticCodeUnit} An array-like object representing - * the branch of an AST representing the syntactic code unit along with - * its scope. - * @return {!Array} An empty array to stop the traversal. - */ - 'defun': function() { - fExamineSyntacticCodeUnit(this); - return []; - }, - /** - * Orders an examination of a nested function expression. - * @this {!TSyntacticCodeUnit} An array-like object representing - * the branch of an AST representing the syntactic code unit along with - * its scope. - * @return {!Array} An empty array to stop the traversal. - */ - 'function': function() { - fExamineSyntacticCodeUnit(this); - return []; - } - /**#nocode-*/ // JsDoc Toolkit 2.4.0 hides some of the keys. - } - }, - /** - * Records containing data about source elements. - * @type {Array.} - */ - aSourceElementsData = [], - /** - * The index (in the source text order) of the source element - * immediately following a Directive Prologue. - * @type {number} - */ - nAfterDirectivePrologue = 0, - /** - * The index (in the source text order) of the source element that is - * currently being considered. - * @type {number} - */ - nPosition, - /** - * The index (in the source text order) of the source element that is - * the last element of the range of source elements that is currently - * being considered. - * @type {(undefined|number)} - */ - nTo, - /** - * Initiates the traversal of a source element. - * @param {!TWalker} oWalker An instance of an object that allows the - * traversal of an abstract syntax tree. - * @param {!TSyntacticCodeUnit} oSourceElement A source element from - * which the traversal should commence. - * @return {function(): !TSyntacticCodeUnit} A function that is able to - * initiate the traversal from a given source element. - */ - cContext = function(oWalker, oSourceElement) { - /** - * @return {!TSyntacticCodeUnit} A function that is able to - * initiate the traversal from a given source element. - */ - var fLambda = function() { - return oWalker.walk(oSourceElement); - }; - - return fLambda; - }, - /** - * Classifies the source element as excludable if it does not - * contain a {@code with} statement or the {@code eval} identifier - * name. - */ - fClassifyAsExcludable = function() { - if (oSourceElementData.nCategory === - ESourceElementCategories.N_OTHER) { - oSourceElementData.nCategory = - ESourceElementCategories.N_EXCLUDABLE; - } - }, - /** - * Adds an identifier to the list of identifier names found. - * @param {string} sIdentifier The identifier to be added. - */ - fAddIdentifier = function(sIdentifier) { - if (-1 === oSourceElementData.aIdentifiers.indexOf(sIdentifier)) { - oSourceElementData.aIdentifiers.push(sIdentifier); - } - }, - /** - * Adds the identifier of a variable to the list of identifier names - * found. - * @param {!Array} aVariableDeclaration A variable declaration. - */ - fAddVariable = function(aVariableDeclaration) { - fAddIdentifier(/** @type {string} */ aVariableDeclaration[0]); - }, - /** - * Increments the count of the number of occurrences of the prefixed - * String representation attributed to the primary expression. - * @param {number} nCategory The category of the primary expression. - * @param {string} sName The prefixed String representation attributed - * to the primary expression. - */ - fCountPrimaryExpression = function(nCategory, sName) { - if (!oSourceElementData.aCount[nCategory].hasOwnProperty(sName)) { - oSourceElementData.aCount[nCategory][sName] = 0; - if (-1 === oSourceElementData.aPrimitiveValues.indexOf(sName)) { - oSourceElementData.aPrimitiveValues.push(sName); - } - } - oSourceElementData.aCount[nCategory][sName] += 1; - }, - /** - * Consolidates all worthwhile primitive values in a range of source - * elements. - * @param {number} nFrom The index (in the source text order) of the - * source element that is the first element of the range. - * @param {number} nTo The index (in the source text order) of the - * source element that is the last element of the range. - * @param {boolean} bEnclose Indicates whether the range should be - * enclosed within a function call with no argument values to a - * function with an empty parameter list if any primitive values - * are consolidated. - * @see TPrimitiveValue#nSaving - */ - fExamineSourceElements = function(nFrom, nTo, bEnclose) { - var _, - /** - * The index of the last mangled name. - * @type {number} - */ - nIndex = oScope.cname, - /** - * The index of the source element that is currently being - * considered. - * @type {number} - */ - nPosition, - /** - * A collection of functions used during the consolidation of - * primitive values and identifier names used as property - * accessors. - * @namespace - * @type {!Object.} - */ - oWalkersTransformers = { - /** - * If the String value that is equivalent to the sequence of - * terminal symbols that constitute the encountered identifier - * name is worthwhile, a syntactic conversion from the dot - * notation to the bracket notation ensues with that sequence - * being substituted by an identifier name to which the value - * is assigned. - * Applies to property accessors that use the dot notation. - * @param {!TSyntacticCodeUnit} oExpression The nonterminal - * MemberExpression. - * @param {string} sIdentifierName The identifier name used as - * the property accessor. - * @return {!Array} A syntactic code unit that is equivalent to - * the one encountered. - * @see TPrimitiveValue#nSaving - */ - 'dot': function(oExpression, sIdentifierName) { - /** - * The prefixed String value that is equivalent to the - * sequence of terminal symbols that constitute the - * encountered identifier name. - * @type {string} - */ - var sPrefixed = EValuePrefixes.S_STRING + sIdentifierName; - - return oSolutionBest.oPrimitiveValues.hasOwnProperty( - sPrefixed) && - oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0 ? - ['sub', - oWalker.walk(oExpression), - ['name', - oSolutionBest.oPrimitiveValues[sPrefixed].sName]] : - ['dot', oWalker.walk(oExpression), sIdentifierName]; - }, - /** - * If the encountered identifier is a null or Boolean literal - * and its value is worthwhile, the identifier is substituted - * by an identifier name to which that value is assigned. - * Applies to identifier names. - * @param {string} sIdentifier The identifier encountered. - * @return {!Array} A syntactic code unit that is equivalent to - * the one encountered. - * @see TPrimitiveValue#nSaving - */ - 'name': function(sIdentifier) { - /** - * The prefixed representation String of the identifier. - * @type {string} - */ - var sPrefixed = EValuePrefixes.S_SYMBOLIC + sIdentifier; - - return [ - 'name', - oSolutionBest.oPrimitiveValues.hasOwnProperty(sPrefixed) && - oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0 ? - oSolutionBest.oPrimitiveValues[sPrefixed].sName : - sIdentifier - ]; - }, - /** - * If the encountered String value is worthwhile, it is - * substituted by an identifier name to which that value is - * assigned. - * Applies to String values. - * @param {string} sStringValue The String value of the string - * literal encountered. - * @return {!Array} A syntactic code unit that is equivalent to - * the one encountered. - * @see TPrimitiveValue#nSaving - */ - 'string': function(sStringValue) { - /** - * The prefixed representation String of the primitive value - * of the literal. - * @type {string} - */ - var sPrefixed = - EValuePrefixes.S_STRING + sStringValue; - - return oSolutionBest.oPrimitiveValues.hasOwnProperty( - sPrefixed) && - oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0 ? - ['name', - oSolutionBest.oPrimitiveValues[sPrefixed].sName] : - ['string', sStringValue]; - } - }, - /** - * Such data on what to consolidate within the range of source - * elements that is currently being considered that lead to the - * greatest known reduction of the number of the terminal symbols - * in comparison to the original source text. - * @type {!TSolution} - */ - oSolutionBest = new TSolution(), - /** - * Data representing an ongoing attempt to find a better - * reduction of the number of the terminal symbols in comparison - * to the original source text than the best one that is - * currently known. - * @type {!TSolution} - * @see oSolutionBest - */ - oSolutionCandidate = new TSolution(), - /** - * A record consisting of data about the range of source elements - * that is currently being examined. - * @type {!TSourceElementsData} - */ - oSourceElementsData = new TSourceElementsData(), - /** - * Variable declarations for each primitive value that is to be - * consolidated within the elements. - * @type {!Array.} - */ - aVariableDeclarations = [], - /** - * Augments a list with a prefixed representation String. - * @param {!Array.} aList A list that is to be augmented. - * @return {function(string)} A function that augments a list - * with a prefixed representation String. - */ - cAugmentList = function(aList) { - /** - * @param {string} sPrefixed Prefixed representation String of - * a primitive value that could be consolidated within the - * elements. - */ - var fLambda = function(sPrefixed) { - if (-1 === aList.indexOf(sPrefixed)) { - aList.push(sPrefixed); - } - }; - - return fLambda; - }, - /** - * Adds the number of occurrences of a primitive value of a given - * category that could be consolidated in the source element with - * a given index to the count of occurrences of that primitive - * value within the range of source elements that is currently - * being considered. - * @param {number} nPosition The index (in the source text order) - * of a source element. - * @param {number} nCategory The category of the primary - * expression from which the primitive value is derived. - * @return {function(string)} A function that performs the - * addition. - * @see cAddOccurrencesInCategory - */ - cAddOccurrences = function(nPosition, nCategory) { - /** - * @param {string} sPrefixed The prefixed representation String - * of a primitive value. - */ - var fLambda = function(sPrefixed) { - if (!oSourceElementsData.aCount[nCategory].hasOwnProperty( - sPrefixed)) { - oSourceElementsData.aCount[nCategory][sPrefixed] = 0; - } - oSourceElementsData.aCount[nCategory][sPrefixed] += - aSourceElementsData[nPosition].aCount[nCategory][ - sPrefixed]; - }; - - return fLambda; - }, - /** - * Adds the number of occurrences of each primitive value of a - * given category that could be consolidated in the source - * element with a given index to the count of occurrences of that - * primitive values within the range of source elements that is - * currently being considered. - * @param {number} nPosition The index (in the source text order) - * of a source element. - * @return {function(number)} A function that performs the - * addition. - * @see fAddOccurrences - */ - cAddOccurrencesInCategory = function(nPosition) { - /** - * @param {number} nCategory The category of the primary - * expression from which the primitive value is derived. - */ - var fLambda = function(nCategory) { - Object.keys( - aSourceElementsData[nPosition].aCount[nCategory] - ).forEach(cAddOccurrences(nPosition, nCategory)); - }; - - return fLambda; - }, - /** - * Adds the number of occurrences of each primitive value that - * could be consolidated in the source element with a given index - * to the count of occurrences of that primitive values within - * the range of source elements that is currently being - * considered. - * @param {number} nPosition The index (in the source text order) - * of a source element. - */ - fAddOccurrences = function(nPosition) { - Object.keys(aSourceElementsData[nPosition].aCount).forEach( - cAddOccurrencesInCategory(nPosition)); - }, - /** - * Creates a variable declaration for a primitive value if that - * primitive value is to be consolidated within the elements. - * @param {string} sPrefixed Prefixed representation String of a - * primitive value that could be consolidated within the - * elements. - * @see aVariableDeclarations - */ - cAugmentVariableDeclarations = function(sPrefixed) { - if (oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0) { - aVariableDeclarations.push([ - oSolutionBest.oPrimitiveValues[sPrefixed].sName, - [0 === sPrefixed.indexOf(EValuePrefixes.S_SYMBOLIC) ? - 'name' : 'string', - sPrefixed.substring(EValuePrefixes.S_SYMBOLIC.length)] - ]); - } - }, - /** - * Sorts primitive values with regard to the difference in the - * number of terminal symbols between the original source text - * and the one with those primitive values consolidated. - * @param {string} sPrefixed0 The prefixed representation String - * of the first of the two primitive values that are being - * compared. - * @param {string} sPrefixed1 The prefixed representation String - * of the second of the two primitive values that are being - * compared. - * @return {number} - *
- *
-1
- *
if the first primitive value must be placed before - * the other one,
- *
0
- *
if the first primitive value may be placed before - * the other one,
- *
1
- *
if the first primitive value must not be placed - * before the other one.
- *
- * @see TSolution.oPrimitiveValues - */ - cSortPrimitiveValues = function(sPrefixed0, sPrefixed1) { - /** - * The difference between: - *
    - *
  1. the difference in the number of terminal symbols - * between the original source text and the one with the - * first primitive value consolidated, and
  2. - *
  3. the difference in the number of terminal symbols - * between the original source text and the one with the - * second primitive value consolidated.
  4. - *
- * @type {number} - */ - var nDifference = - oSolutionCandidate.oPrimitiveValues[sPrefixed0].nSaving - - oSolutionCandidate.oPrimitiveValues[sPrefixed1].nSaving; - - return nDifference > 0 ? -1 : nDifference < 0 ? 1 : 0; - }, - /** - * Assigns an identifier name to a primitive value and calculates - * whether instances of that primitive value are worth - * consolidating. - * @param {string} sPrefixed The prefixed representation String - * of a primitive value that is being evaluated. - */ - fEvaluatePrimitiveValue = function(sPrefixed) { - var _, - /** - * The index of the last mangled name. - * @type {number} - */ - nIndex, - /** - * The representation String of the primitive value that is - * being evaluated. - * @type {string} - */ - sName = - sPrefixed.substring(EValuePrefixes.S_SYMBOLIC.length), - /** - * The number of source characters taken up by the - * representation String of the primitive value that is - * being evaluated. - * @type {number} - */ - nLengthOriginal = sName.length, - /** - * The number of source characters taken up by the - * identifier name that could substitute the primitive - * value that is being evaluated. - * substituted. - * @type {number} - */ - nLengthSubstitution, - /** - * The number of source characters taken up by by the - * representation String of the primitive value that is - * being evaluated when it is represented by a string - * literal. - * @type {number} - */ - nLengthString = oProcessor.make_string(sName).length; - - oSolutionCandidate.oPrimitiveValues[sPrefixed] = - new TPrimitiveValue(); - do { // Find an identifier unused in this or any nested scope. - nIndex = oScope.cname; - oSolutionCandidate.oPrimitiveValues[sPrefixed].sName = - oScope.next_mangled(); - } while (-1 !== oSourceElementsData.aIdentifiers.indexOf( - oSolutionCandidate.oPrimitiveValues[sPrefixed].sName)); - nLengthSubstitution = oSolutionCandidate.oPrimitiveValues[ - sPrefixed].sName.length; - if (0 === sPrefixed.indexOf(EValuePrefixes.S_SYMBOLIC)) { - // foo:null, or foo:null; - oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving -= - nLengthSubstitution + nLengthOriginal + - oWeights.N_VARIABLE_DECLARATION; - // null vs foo - oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving += - oSourceElementsData.aCount[ - EPrimaryExpressionCategories. - N_NULL_AND_BOOLEAN_LITERALS][sPrefixed] * - (nLengthOriginal - nLengthSubstitution); - } else { - // foo:'fromCharCode'; - oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving -= - nLengthSubstitution + nLengthString + - oWeights.N_VARIABLE_DECLARATION; - // .fromCharCode vs [foo] - if (oSourceElementsData.aCount[ - EPrimaryExpressionCategories.N_IDENTIFIER_NAMES - ].hasOwnProperty(sPrefixed)) { - oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving += - oSourceElementsData.aCount[ - EPrimaryExpressionCategories.N_IDENTIFIER_NAMES - ][sPrefixed] * - (nLengthOriginal - nLengthSubstitution - - oWeights.N_PROPERTY_ACCESSOR); - } - // 'fromCharCode' vs foo - if (oSourceElementsData.aCount[ - EPrimaryExpressionCategories.N_STRING_LITERALS - ].hasOwnProperty(sPrefixed)) { - oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving += - oSourceElementsData.aCount[ - EPrimaryExpressionCategories.N_STRING_LITERALS - ][sPrefixed] * - (nLengthString - nLengthSubstitution); - } - } - if (oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving > - 0) { - oSolutionCandidate.nSavings += - oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving; - } else { - oScope.cname = nIndex; // Free the identifier name. - } - }, - /** - * Adds a variable declaration to an existing variable statement. - * @param {!Array} aVariableDeclaration A variable declaration - * with an initialiser. - */ - cAddVariableDeclaration = function(aVariableDeclaration) { - (/** @type {!Array} */ oSourceElements[nFrom][1]).unshift( - aVariableDeclaration); - }; - - if (nFrom > nTo) { - return; - } - // If the range is a closure, reuse the closure. - if (nFrom === nTo && - 'stat' === oSourceElements[nFrom][0] && - 'call' === oSourceElements[nFrom][1][0] && - 'function' === oSourceElements[nFrom][1][1][0]) { - fExamineSyntacticCodeUnit(oSourceElements[nFrom][1][1]); - return; - } - // Create a list of all derived primitive values within the range. - for (nPosition = nFrom; nPosition <= nTo; nPosition += 1) { - aSourceElementsData[nPosition].aPrimitiveValues.forEach( - cAugmentList(oSourceElementsData.aPrimitiveValues)); - } - if (0 === oSourceElementsData.aPrimitiveValues.length) { - return; - } - for (nPosition = nFrom; nPosition <= nTo; nPosition += 1) { - // Add the number of occurrences to the total count. - fAddOccurrences(nPosition); - // Add identifiers of this or any nested scope to the list. - aSourceElementsData[nPosition].aIdentifiers.forEach( - cAugmentList(oSourceElementsData.aIdentifiers)); - } - // Distribute identifier names among derived primitive values. - do { // If there was any progress, find a better distribution. - oSolutionBest = oSolutionCandidate; - if (Object.keys(oSolutionCandidate.oPrimitiveValues).length > 0) { - // Sort primitive values descending by their worthwhileness. - oSourceElementsData.aPrimitiveValues.sort(cSortPrimitiveValues); - } - oSolutionCandidate = new TSolution(); - oSourceElementsData.aPrimitiveValues.forEach( - fEvaluatePrimitiveValue); - oScope.cname = nIndex; - } while (oSolutionCandidate.nSavings > oSolutionBest.nSavings); - // Take the necessity of adding a variable statement into account. - if ('var' !== oSourceElements[nFrom][0]) { - oSolutionBest.nSavings -= oWeights.N_VARIABLE_STATEMENT_AFFIXATION; - } - if (bEnclose) { - // Take the necessity of forming a closure into account. - oSolutionBest.nSavings -= oWeights.N_CLOSURE; - } - if (oSolutionBest.nSavings > 0) { - // Create variable declarations suitable for UglifyJS. - Object.keys(oSolutionBest.oPrimitiveValues).forEach( - cAugmentVariableDeclarations); - // Rewrite expressions that contain worthwhile primitive values. - for (nPosition = nFrom; nPosition <= nTo; nPosition += 1) { - oWalker = oProcessor.ast_walker(); - oSourceElements[nPosition] = - oWalker.with_walkers( - oWalkersTransformers, - cContext(oWalker, oSourceElements[nPosition])); - } - if ('var' === oSourceElements[nFrom][0]) { // Reuse the statement. - (/** @type {!Array.} */ aVariableDeclarations.reverse( - )).forEach(cAddVariableDeclaration); - } else { // Add a variable statement. - Array.prototype.splice.call( - oSourceElements, - nFrom, - 0, - ['var', aVariableDeclarations]); - nTo += 1; - } - if (bEnclose) { - // Add a closure. - Array.prototype.splice.call( - oSourceElements, - nFrom, - 0, - ['stat', ['call', ['function', null, [], []], []]]); - // Copy source elements into the closure. - for (nPosition = nTo + 1; nPosition > nFrom; nPosition -= 1) { - Array.prototype.unshift.call( - oSourceElements[nFrom][1][1][3], - oSourceElements[nPosition]); - } - // Remove source elements outside the closure. - Array.prototype.splice.call( - oSourceElements, - nFrom + 1, - nTo - nFrom + 1); - } - } - if (bEnclose) { - // Restore the availability of identifier names. - oScope.cname = nIndex; - } - }; - - oSourceElements = (/** @type {!TSyntacticCodeUnit} */ - oSyntacticCodeUnit[bIsGlobal ? 1 : 3]); - if (0 === oSourceElements.length) { - return; - } - oScope = bIsGlobal ? oSyntacticCodeUnit.scope : oSourceElements.scope; - // Skip a Directive Prologue. - while (nAfterDirectivePrologue < oSourceElements.length && - 'directive' === oSourceElements[nAfterDirectivePrologue][0]) { - nAfterDirectivePrologue += 1; - aSourceElementsData.push(null); - } - if (oSourceElements.length === nAfterDirectivePrologue) { - return; - } - for (nPosition = nAfterDirectivePrologue; - nPosition < oSourceElements.length; - nPosition += 1) { - oSourceElementData = new TSourceElementsData(); - oWalker = oProcessor.ast_walker(); - // Classify a source element. - // Find its derived primitive values and count their occurrences. - // Find all identifiers used (including nested scopes). - oWalker.with_walkers( - oWalkers.oSurveySourceElement, - cContext(oWalker, oSourceElements[nPosition])); - // Establish whether the scope is still wholly examinable. - bIsWhollyExaminable = bIsWhollyExaminable && - ESourceElementCategories.N_WITH !== oSourceElementData.nCategory && - ESourceElementCategories.N_EVAL !== oSourceElementData.nCategory; - aSourceElementsData.push(oSourceElementData); - } - if (bIsWhollyExaminable) { // Examine the whole scope. - fExamineSourceElements( - nAfterDirectivePrologue, - oSourceElements.length - 1, - false); - } else { // Examine unexcluded ranges of source elements. - for (nPosition = oSourceElements.length - 1; - nPosition >= nAfterDirectivePrologue; - nPosition -= 1) { - oSourceElementData = (/** @type {!TSourceElementsData} */ - aSourceElementsData[nPosition]); - if (ESourceElementCategories.N_OTHER === - oSourceElementData.nCategory) { - if ('undefined' === typeof nTo) { - nTo = nPosition; // Indicate the end of a range. - } - // Examine the range if it immediately follows a Directive Prologue. - if (nPosition === nAfterDirectivePrologue) { - fExamineSourceElements(nPosition, nTo, true); - } - } else { - if ('undefined' !== typeof nTo) { - // Examine the range that immediately follows this source element. - fExamineSourceElements(nPosition + 1, nTo, true); - nTo = void 0; // Obliterate the range. - } - // Examine nested functions. - oWalker = oProcessor.ast_walker(); - oWalker.with_walkers( - oWalkers.oExamineFunctions, - cContext(oWalker, oSourceElements[nPosition])); - } - } - } - }(oAbstractSyntaxTree = oProcessor.ast_add_scope(oAbstractSyntaxTree))); - return oAbstractSyntaxTree; -}; -/*jshint sub:false */ - -/* Local Variables: */ -/* mode: js */ -/* coding: utf-8 */ -/* indent-tabs-mode: nil */ -/* tab-width: 2 */ -/* End: */ -/* vim: set ft=javascript fenc=utf-8 et ts=2 sts=2 sw=2: */ -/* :mode=javascript:noTabs=true:tabSize=2:indentSize=2:deepIndent=true: */ -}); -define('uglifyjs/parse-js', ["exports"], function(exports) { -/*********************************************************************** - - A JavaScript tokenizer / parser / beautifier / compressor. - - This version is suitable for Node.js. With minimal changes (the - exports stuff) it should work on any JS platform. - - This file contains the tokenizer/parser. It is a port to JavaScript - of parse-js [1], a JavaScript parser library written in Common Lisp - by Marijn Haverbeke. Thank you Marijn! - - [1] http://marijn.haverbeke.nl/parse-js/ - - Exported functions: - - - tokenizer(code) -- returns a function. Call the returned - function to fetch the next token. - - - parse(code) -- returns an AST of the given JavaScript code. - - -------------------------------- (C) --------------------------------- - - Author: Mihai Bazon - - http://mihai.bazon.net/blog - - Distributed under the BSD license: - - Copyright 2010 (c) Mihai Bazon - Based on parse-js (http://marijn.haverbeke.nl/parse-js/). - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the following - disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - - ***********************************************************************/ - -/* -----[ Tokenizer (constants) ]----- */ - -var KEYWORDS = array_to_hash([ - "break", - "case", - "catch", - "const", - "continue", - "debugger", - "default", - "delete", - "do", - "else", - "finally", - "for", - "function", - "if", - "in", - "instanceof", - "new", - "return", - "switch", - "throw", - "try", - "typeof", - "var", - "void", - "while", - "with" -]); - -var RESERVED_WORDS = array_to_hash([ - "abstract", - "boolean", - "byte", - "char", - "class", - "double", - "enum", - "export", - "extends", - "final", - "float", - "goto", - "implements", - "import", - "int", - "interface", - "long", - "native", - "package", - "private", - "protected", - "public", - "short", - "static", - "super", - "synchronized", - "throws", - "transient", - "volatile" -]); - -var KEYWORDS_BEFORE_EXPRESSION = array_to_hash([ - "return", - "new", - "delete", - "throw", - "else", - "case" -]); - -var KEYWORDS_ATOM = array_to_hash([ - "false", - "null", - "true", - "undefined" -]); - -var OPERATOR_CHARS = array_to_hash(characters("+-*&%=<>!?|~^")); - -var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i; -var RE_OCT_NUMBER = /^0[0-7]+$/; -var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i; - -var OPERATORS = array_to_hash([ - "in", - "instanceof", - "typeof", - "new", - "void", - "delete", - "++", - "--", - "+", - "-", - "!", - "~", - "&", - "|", - "^", - "*", - "/", - "%", - ">>", - "<<", - ">>>", - "<", - ">", - "<=", - ">=", - "==", - "===", - "!=", - "!==", - "?", - "=", - "+=", - "-=", - "/=", - "*=", - "%=", - ">>=", - "<<=", - ">>>=", - "|=", - "^=", - "&=", - "&&", - "||" -]); - -var WHITESPACE_CHARS = array_to_hash(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000")); - -var PUNC_BEFORE_EXPRESSION = array_to_hash(characters("[{(,.;:")); - -var PUNC_CHARS = array_to_hash(characters("[]{}(),;:")); - -var REGEXP_MODIFIERS = array_to_hash(characters("gmsiy")); - -/* -----[ Tokenizer ]----- */ - -var UNICODE = { // Unicode 6.1 - letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0\\u08A2-\\u08AC\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0977\\u0979-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F0\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA697\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA793\\uA7A0-\\uA7AA\\uA7F8-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA80-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"), - combining_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065F\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0859-\\u085B\\u08E4-\\u08FE\\u0900-\\u0903\\u093A-\\u093C\\u093E-\\u094F\\u0951-\\u0957\\u0962\\u0963\\u0981-\\u0983\\u09BC\\u09BE-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CD\\u09D7\\u09E2\\u09E3\\u0A01-\\u0A03\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81-\\u0A83\\u0ABC\\u0ABE-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD\\u0AE2\\u0AE3\\u0B01-\\u0B03\\u0B3C\\u0B3E-\\u0B44\\u0B47\\u0B48\\u0B4B-\\u0B4D\\u0B56\\u0B57\\u0B62\\u0B63\\u0B82\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD7\\u0C01-\\u0C03\\u0C3E-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0C82\\u0C83\\u0CBC\\u0CBE-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6\\u0CE2\\u0CE3\\u0D02\\u0D03\\u0D3E-\\u0D44\\u0D46-\\u0D48\\u0D4A-\\u0D4D\\u0D57\\u0D62\\u0D63\\u0D82\\u0D83\\u0DCA\\u0DCF-\\u0DD4\\u0DD6\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F3E\\u0F3F\\u0F71-\\u0F84\\u0F86\\u0F87\\u0F8D-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102B-\\u103E\\u1056-\\u1059\\u105E-\\u1060\\u1062-\\u1064\\u1067-\\u106D\\u1071-\\u1074\\u1082-\\u108D\\u108F\\u109A-\\u109D\\u135D-\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B4-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u192B\\u1930-\\u193B\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A17-\\u1A1B\\u1A55-\\u1A5E\\u1A60-\\u1A7C\\u1A7F\\u1B00-\\u1B04\\u1B34-\\u1B44\\u1B6B-\\u1B73\\u1B80-\\u1B82\\u1BA1-\\u1BAD\\u1BE6-\\u1BF3\\u1C24-\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE8\\u1CED\\u1CF2-\\u1CF4\\u1DC0-\\u1DE6\\u1DFC-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2D7F\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA674-\\uA67D\\uA69F\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA823-\\uA827\\uA880\\uA881\\uA8B4-\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA953\\uA980-\\uA983\\uA9B3-\\uA9C0\\uAA29-\\uAA36\\uAA43\\uAA4C\\uAA4D\\uAA7B\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uAAEB-\\uAAEF\\uAAF5\\uAAF6\\uABE3-\\uABEA\\uABEC\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"), - connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]"), - digit: new RegExp("[\\u0030-\\u0039\\u0660-\\u0669\\u06F0-\\u06F9\\u07C0-\\u07C9\\u0966-\\u096F\\u09E6-\\u09EF\\u0A66-\\u0A6F\\u0AE6-\\u0AEF\\u0B66-\\u0B6F\\u0BE6-\\u0BEF\\u0C66-\\u0C6F\\u0CE6-\\u0CEF\\u0D66-\\u0D6F\\u0E50-\\u0E59\\u0ED0-\\u0ED9\\u0F20-\\u0F29\\u1040-\\u1049\\u1090-\\u1099\\u17E0-\\u17E9\\u1810-\\u1819\\u1946-\\u194F\\u19D0-\\u19D9\\u1A80-\\u1A89\\u1A90-\\u1A99\\u1B50-\\u1B59\\u1BB0-\\u1BB9\\u1C40-\\u1C49\\u1C50-\\u1C59\\uA620-\\uA629\\uA8D0-\\uA8D9\\uA900-\\uA909\\uA9D0-\\uA9D9\\uAA50-\\uAA59\\uABF0-\\uABF9\\uFF10-\\uFF19]") -}; - -function is_letter(ch) { - return UNICODE.letter.test(ch); -}; - -function is_digit(ch) { - ch = ch.charCodeAt(0); - return ch >= 48 && ch <= 57; -}; - -function is_unicode_digit(ch) { - return UNICODE.digit.test(ch); -} - -function is_alphanumeric_char(ch) { - return is_digit(ch) || is_letter(ch); -}; - -function is_unicode_combining_mark(ch) { - return UNICODE.combining_mark.test(ch); -}; - -function is_unicode_connector_punctuation(ch) { - return UNICODE.connector_punctuation.test(ch); -}; - -function is_identifier_start(ch) { - return ch == "$" || ch == "_" || is_letter(ch); -}; - -function is_identifier_char(ch) { - return is_identifier_start(ch) - || is_unicode_combining_mark(ch) - || is_unicode_digit(ch) - || is_unicode_connector_punctuation(ch) - || ch == "\u200c" // zero-width non-joiner - || ch == "\u200d" // zero-width joiner (in my ECMA-262 PDF, this is also 200c) - ; -}; - -function parse_js_number(num) { - if (RE_HEX_NUMBER.test(num)) { - return parseInt(num.substr(2), 16); - } else if (RE_OCT_NUMBER.test(num)) { - return parseInt(num.substr(1), 8); - } else if (RE_DEC_NUMBER.test(num)) { - return parseFloat(num); - } -}; - -function JS_Parse_Error(message, line, col, pos) { - this.message = message; - this.line = line + 1; - this.col = col + 1; - this.pos = pos + 1; - this.stack = new Error().stack; -}; - -JS_Parse_Error.prototype.toString = function() { - return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack; -}; - -function js_error(message, line, col, pos) { - throw new JS_Parse_Error(message, line, col, pos); -}; - -function is_token(token, type, val) { - return token.type == type && (val == null || token.value == val); -}; - -var EX_EOF = {}; - -function tokenizer($TEXT) { - - var S = { - text : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, ''), - pos : 0, - tokpos : 0, - line : 0, - tokline : 0, - col : 0, - tokcol : 0, - newline_before : false, - regex_allowed : false, - comments_before : [] - }; - - function peek() { return S.text.charAt(S.pos); }; - - function next(signal_eof, in_string) { - var ch = S.text.charAt(S.pos++); - if (signal_eof && !ch) - throw EX_EOF; - if (ch == "\n") { - S.newline_before = S.newline_before || !in_string; - ++S.line; - S.col = 0; - } else { - ++S.col; - } - return ch; - }; - - function eof() { - return !S.peek(); - }; - - function find(what, signal_eof) { - var pos = S.text.indexOf(what, S.pos); - if (signal_eof && pos == -1) throw EX_EOF; - return pos; - }; - - function start_token() { - S.tokline = S.line; - S.tokcol = S.col; - S.tokpos = S.pos; - }; - - function token(type, value, is_comment) { - S.regex_allowed = ((type == "operator" && !HOP(UNARY_POSTFIX, value)) || - (type == "keyword" && HOP(KEYWORDS_BEFORE_EXPRESSION, value)) || - (type == "punc" && HOP(PUNC_BEFORE_EXPRESSION, value))); - var ret = { - type : type, - value : value, - line : S.tokline, - col : S.tokcol, - pos : S.tokpos, - endpos : S.pos, - nlb : S.newline_before - }; - if (!is_comment) { - ret.comments_before = S.comments_before; - S.comments_before = []; - // make note of any newlines in the comments that came before - for (var i = 0, len = ret.comments_before.length; i < len; i++) { - ret.nlb = ret.nlb || ret.comments_before[i].nlb; - } - } - S.newline_before = false; - return ret; - }; - - function skip_whitespace() { - while (HOP(WHITESPACE_CHARS, peek())) - next(); - }; - - function read_while(pred) { - var ret = "", ch = peek(), i = 0; - while (ch && pred(ch, i++)) { - ret += next(); - ch = peek(); - } - return ret; - }; - - function parse_error(err) { - js_error(err, S.tokline, S.tokcol, S.tokpos); - }; - - function read_num(prefix) { - var has_e = false, after_e = false, has_x = false, has_dot = prefix == "."; - var num = read_while(function(ch, i){ - if (ch == "x" || ch == "X") { - if (has_x) return false; - return has_x = true; - } - if (!has_x && (ch == "E" || ch == "e")) { - if (has_e) return false; - return has_e = after_e = true; - } - if (ch == "-") { - if (after_e || (i == 0 && !prefix)) return true; - return false; - } - if (ch == "+") return after_e; - after_e = false; - if (ch == ".") { - if (!has_dot && !has_x && !has_e) - return has_dot = true; - return false; - } - return is_alphanumeric_char(ch); - }); - if (prefix) - num = prefix + num; - var valid = parse_js_number(num); - if (!isNaN(valid)) { - return token("num", valid); - } else { - parse_error("Invalid syntax: " + num); - } - }; - - function read_escaped_char(in_string) { - var ch = next(true, in_string); - switch (ch) { - case "n" : return "\n"; - case "r" : return "\r"; - case "t" : return "\t"; - case "b" : return "\b"; - case "v" : return "\u000b"; - case "f" : return "\f"; - case "0" : return "\0"; - case "x" : return String.fromCharCode(hex_bytes(2)); - case "u" : return String.fromCharCode(hex_bytes(4)); - case "\n": return ""; - default : return ch; - } - }; - - function hex_bytes(n) { - var num = 0; - for (; n > 0; --n) { - var digit = parseInt(next(true), 16); - if (isNaN(digit)) - parse_error("Invalid hex-character pattern in string"); - num = (num << 4) | digit; - } - return num; - }; - - function read_string() { - return with_eof_error("Unterminated string constant", function(){ - var quote = next(), ret = ""; - for (;;) { - var ch = next(true); - if (ch == "\\") { - // read OctalEscapeSequence (XXX: deprecated if "strict mode") - // https://github.com/mishoo/UglifyJS/issues/178 - var octal_len = 0, first = null; - ch = read_while(function(ch){ - if (ch >= "0" && ch <= "7") { - if (!first) { - first = ch; - return ++octal_len; - } - else if (first <= "3" && octal_len <= 2) return ++octal_len; - else if (first >= "4" && octal_len <= 1) return ++octal_len; - } - return false; - }); - if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8)); - else ch = read_escaped_char(true); - } - else if (ch == quote) break; - ret += ch; - } - return token("string", ret); - }); - }; - - function read_line_comment() { - next(); - var i = find("\n"), ret; - if (i == -1) { - ret = S.text.substr(S.pos); - S.pos = S.text.length; - } else { - ret = S.text.substring(S.pos, i); - S.pos = i; - } - return token("comment1", ret, true); - }; - - function read_multiline_comment() { - next(); - return with_eof_error("Unterminated multiline comment", function(){ - var i = find("*/", true), - text = S.text.substring(S.pos, i); - S.pos = i + 2; - S.line += text.split("\n").length - 1; - S.newline_before = S.newline_before || text.indexOf("\n") >= 0; - - // https://github.com/mishoo/UglifyJS/issues/#issue/100 - if (/^@cc_on/i.test(text)) { - warn("WARNING: at line " + S.line); - warn("*** Found \"conditional comment\": " + text); - warn("*** UglifyJS DISCARDS ALL COMMENTS. This means your code might no longer work properly in Internet Explorer."); - } - - return token("comment2", text, true); - }); - }; - - function read_name() { - var backslash = false, name = "", ch, escaped = false, hex; - while ((ch = peek()) != null) { - if (!backslash) { - if (ch == "\\") escaped = backslash = true, next(); - else if (is_identifier_char(ch)) name += next(); - else break; - } - else { - if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX"); - ch = read_escaped_char(); - if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier"); - name += ch; - backslash = false; - } - } - if (HOP(KEYWORDS, name) && escaped) { - hex = name.charCodeAt(0).toString(16).toUpperCase(); - name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1); - } - return name; - }; - - function read_regexp(regexp) { - return with_eof_error("Unterminated regular expression", function(){ - var prev_backslash = false, ch, in_class = false; - while ((ch = next(true))) if (prev_backslash) { - regexp += "\\" + ch; - prev_backslash = false; - } else if (ch == "[") { - in_class = true; - regexp += ch; - } else if (ch == "]" && in_class) { - in_class = false; - regexp += ch; - } else if (ch == "/" && !in_class) { - break; - } else if (ch == "\\") { - prev_backslash = true; - } else { - regexp += ch; - } - var mods = read_name(); - return token("regexp", [ regexp, mods ]); - }); - }; - - function read_operator(prefix) { - function grow(op) { - if (!peek()) return op; - var bigger = op + peek(); - if (HOP(OPERATORS, bigger)) { - next(); - return grow(bigger); - } else { - return op; - } - }; - return token("operator", grow(prefix || next())); - }; - - function handle_slash() { - next(); - var regex_allowed = S.regex_allowed; - switch (peek()) { - case "/": - S.comments_before.push(read_line_comment()); - S.regex_allowed = regex_allowed; - return next_token(); - case "*": - S.comments_before.push(read_multiline_comment()); - S.regex_allowed = regex_allowed; - return next_token(); - } - return S.regex_allowed ? read_regexp("") : read_operator("/"); - }; - - function handle_dot() { - next(); - return is_digit(peek()) - ? read_num(".") - : token("punc", "."); - }; - - function read_word() { - var word = read_name(); - return !HOP(KEYWORDS, word) - ? token("name", word) - : HOP(OPERATORS, word) - ? token("operator", word) - : HOP(KEYWORDS_ATOM, word) - ? token("atom", word) - : token("keyword", word); - }; - - function with_eof_error(eof_error, cont) { - try { - return cont(); - } catch(ex) { - if (ex === EX_EOF) parse_error(eof_error); - else throw ex; - } - }; - - function next_token(force_regexp) { - if (force_regexp != null) - return read_regexp(force_regexp); - skip_whitespace(); - start_token(); - var ch = peek(); - if (!ch) return token("eof"); - if (is_digit(ch)) return read_num(); - if (ch == '"' || ch == "'") return read_string(); - if (HOP(PUNC_CHARS, ch)) return token("punc", next()); - if (ch == ".") return handle_dot(); - if (ch == "/") return handle_slash(); - if (HOP(OPERATOR_CHARS, ch)) return read_operator(); - if (ch == "\\" || is_identifier_start(ch)) return read_word(); - parse_error("Unexpected character '" + ch + "'"); - }; - - next_token.context = function(nc) { - if (nc) S = nc; - return S; - }; - - return next_token; - -}; - -/* -----[ Parser (constants) ]----- */ - -var UNARY_PREFIX = array_to_hash([ - "typeof", - "void", - "delete", - "--", - "++", - "!", - "~", - "-", - "+" -]); - -var UNARY_POSTFIX = array_to_hash([ "--", "++" ]); - -var ASSIGNMENT = (function(a, ret, i){ - while (i < a.length) { - ret[a[i]] = a[i].substr(0, a[i].length - 1); - i++; - } - return ret; -})( - ["+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&="], - { "=": true }, - 0 -); - -var PRECEDENCE = (function(a, ret){ - for (var i = 0, n = 1; i < a.length; ++i, ++n) { - var b = a[i]; - for (var j = 0; j < b.length; ++j) { - ret[b[j]] = n; - } - } - return ret; -})( - [ - ["||"], - ["&&"], - ["|"], - ["^"], - ["&"], - ["==", "===", "!=", "!=="], - ["<", ">", "<=", ">=", "in", "instanceof"], - [">>", "<<", ">>>"], - ["+", "-"], - ["*", "/", "%"] - ], - {} -); - -var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]); - -var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]); - -/* -----[ Parser ]----- */ - -function NodeWithToken(str, start, end) { - this.name = str; - this.start = start; - this.end = end; -}; - -NodeWithToken.prototype.toString = function() { return this.name; }; - -function parse($TEXT, exigent_mode, embed_tokens) { - - var S = { - input : typeof $TEXT == "string" ? tokenizer($TEXT, true) : $TEXT, - token : null, - prev : null, - peeked : null, - in_function : 0, - in_directives : true, - in_loop : 0, - labels : [] - }; - - S.token = next(); - - function is(type, value) { - return is_token(S.token, type, value); - }; - - function peek() { return S.peeked || (S.peeked = S.input()); }; - - function next() { - S.prev = S.token; - if (S.peeked) { - S.token = S.peeked; - S.peeked = null; - } else { - S.token = S.input(); - } - S.in_directives = S.in_directives && ( - S.token.type == "string" || is("punc", ";") - ); - return S.token; - }; - - function prev() { - return S.prev; - }; - - function croak(msg, line, col, pos) { - var ctx = S.input.context(); - js_error(msg, - line != null ? line : ctx.tokline, - col != null ? col : ctx.tokcol, - pos != null ? pos : ctx.tokpos); - }; - - function token_error(token, msg) { - croak(msg, token.line, token.col); - }; - - function unexpected(token) { - if (token == null) - token = S.token; - token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")"); - }; - - function expect_token(type, val) { - if (is(type, val)) { - return next(); - } - token_error(S.token, "Unexpected token " + S.token.type + ", expected " + type); - }; - - function expect(punc) { return expect_token("punc", punc); }; - - function can_insert_semicolon() { - return !exigent_mode && ( - S.token.nlb || is("eof") || is("punc", "}") - ); - }; - - function semicolon() { - if (is("punc", ";")) next(); - else if (!can_insert_semicolon()) unexpected(); - }; - - function as() { - return slice(arguments); - }; - - function parenthesised() { - expect("("); - var ex = expression(); - expect(")"); - return ex; - }; - - function add_tokens(str, start, end) { - return str instanceof NodeWithToken ? str : new NodeWithToken(str, start, end); - }; - - function maybe_embed_tokens(parser) { - if (embed_tokens) return function() { - var start = S.token; - var ast = parser.apply(this, arguments); - ast[0] = add_tokens(ast[0], start, prev()); - return ast; - }; - else return parser; - }; - - var statement = maybe_embed_tokens(function() { - if (is("operator", "/") || is("operator", "/=")) { - S.peeked = null; - S.token = S.input(S.token.value.substr(1)); // force regexp - } - switch (S.token.type) { - case "string": - var dir = S.in_directives, stat = simple_statement(); - if (dir && stat[1][0] == "string" && !is("punc", ",")) - return as("directive", stat[1][1]); - return stat; - case "num": - case "regexp": - case "operator": - case "atom": - return simple_statement(); - - case "name": - return is_token(peek(), "punc", ":") - ? labeled_statement(prog1(S.token.value, next, next)) - : simple_statement(); - - case "punc": - switch (S.token.value) { - case "{": - return as("block", block_()); - case "[": - case "(": - return simple_statement(); - case ";": - next(); - return as("block"); - default: - unexpected(); - } - - case "keyword": - switch (prog1(S.token.value, next)) { - case "break": - return break_cont("break"); - - case "continue": - return break_cont("continue"); - - case "debugger": - semicolon(); - return as("debugger"); - - case "do": - return (function(body){ - expect_token("keyword", "while"); - return as("do", prog1(parenthesised, semicolon), body); - })(in_loop(statement)); - - case "for": - return for_(); - - case "function": - return function_(true); - - case "if": - return if_(); - - case "return": - if (S.in_function == 0) - croak("'return' outside of function"); - return as("return", - is("punc", ";") - ? (next(), null) - : can_insert_semicolon() - ? null - : prog1(expression, semicolon)); - - case "switch": - return as("switch", parenthesised(), switch_block_()); - - case "throw": - if (S.token.nlb) - croak("Illegal newline after 'throw'"); - return as("throw", prog1(expression, semicolon)); - - case "try": - return try_(); - - case "var": - return prog1(var_, semicolon); - - case "const": - return prog1(const_, semicolon); - - case "while": - return as("while", parenthesised(), in_loop(statement)); - - case "with": - return as("with", parenthesised(), statement()); - - default: - unexpected(); - } - } - }); - - function labeled_statement(label) { - S.labels.push(label); - var start = S.token, stat = statement(); - if (exigent_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0])) - unexpected(start); - S.labels.pop(); - return as("label", label, stat); - }; - - function simple_statement() { - return as("stat", prog1(expression, semicolon)); - }; - - function break_cont(type) { - var name; - if (!can_insert_semicolon()) { - name = is("name") ? S.token.value : null; - } - if (name != null) { - next(); - if (!member(name, S.labels)) - croak("Label " + name + " without matching loop or statement"); - } - else if (S.in_loop == 0) - croak(type + " not inside a loop or switch"); - semicolon(); - return as(type, name); - }; - - function for_() { - expect("("); - var init = null; - if (!is("punc", ";")) { - init = is("keyword", "var") - ? (next(), var_(true)) - : expression(true, true); - if (is("operator", "in")) { - if (init[0] == "var" && init[1].length > 1) - croak("Only one variable declaration allowed in for..in loop"); - return for_in(init); - } - } - return regular_for(init); - }; - - function regular_for(init) { - expect(";"); - var test = is("punc", ";") ? null : expression(); - expect(";"); - var step = is("punc", ")") ? null : expression(); - expect(")"); - return as("for", init, test, step, in_loop(statement)); - }; - - function for_in(init) { - var lhs = init[0] == "var" ? as("name", init[1][0]) : init; - next(); - var obj = expression(); - expect(")"); - return as("for-in", init, lhs, obj, in_loop(statement)); - }; - - var function_ = function(in_statement) { - var name = is("name") ? prog1(S.token.value, next) : null; - if (in_statement && !name) - unexpected(); - expect("("); - return as(in_statement ? "defun" : "function", - name, - // arguments - (function(first, a){ - while (!is("punc", ")")) { - if (first) first = false; else expect(","); - if (!is("name")) unexpected(); - a.push(S.token.value); - next(); - } - next(); - return a; - })(true, []), - // body - (function(){ - ++S.in_function; - var loop = S.in_loop; - S.in_directives = true; - S.in_loop = 0; - var a = block_(); - --S.in_function; - S.in_loop = loop; - return a; - })()); - }; - - function if_() { - var cond = parenthesised(), body = statement(), belse; - if (is("keyword", "else")) { - next(); - belse = statement(); - } - return as("if", cond, body, belse); - }; - - function block_() { - expect("{"); - var a = []; - while (!is("punc", "}")) { - if (is("eof")) unexpected(); - a.push(statement()); - } - next(); - return a; - }; - - var switch_block_ = curry(in_loop, function(){ - expect("{"); - var a = [], cur = null; - while (!is("punc", "}")) { - if (is("eof")) unexpected(); - if (is("keyword", "case")) { - next(); - cur = []; - a.push([ expression(), cur ]); - expect(":"); - } - else if (is("keyword", "default")) { - next(); - expect(":"); - cur = []; - a.push([ null, cur ]); - } - else { - if (!cur) unexpected(); - cur.push(statement()); - } - } - next(); - return a; - }); - - function try_() { - var body = block_(), bcatch, bfinally; - if (is("keyword", "catch")) { - next(); - expect("("); - if (!is("name")) - croak("Name expected"); - var name = S.token.value; - next(); - expect(")"); - bcatch = [ name, block_() ]; - } - if (is("keyword", "finally")) { - next(); - bfinally = block_(); - } - if (!bcatch && !bfinally) - croak("Missing catch/finally blocks"); - return as("try", body, bcatch, bfinally); - }; - - function vardefs(no_in) { - var a = []; - for (;;) { - if (!is("name")) - unexpected(); - var name = S.token.value; - next(); - if (is("operator", "=")) { - next(); - a.push([ name, expression(false, no_in) ]); - } else { - a.push([ name ]); - } - if (!is("punc", ",")) - break; - next(); - } - return a; - }; - - function var_(no_in) { - return as("var", vardefs(no_in)); - }; - - function const_() { - return as("const", vardefs()); - }; - - function new_() { - var newexp = expr_atom(false), args; - if (is("punc", "(")) { - next(); - args = expr_list(")"); - } else { - args = []; - } - return subscripts(as("new", newexp, args), true); - }; - - var expr_atom = maybe_embed_tokens(function(allow_calls) { - if (is("operator", "new")) { - next(); - return new_(); - } - if (is("punc")) { - switch (S.token.value) { - case "(": - next(); - return subscripts(prog1(expression, curry(expect, ")")), allow_calls); - case "[": - next(); - return subscripts(array_(), allow_calls); - case "{": - next(); - return subscripts(object_(), allow_calls); - } - unexpected(); - } - if (is("keyword", "function")) { - next(); - return subscripts(function_(false), allow_calls); - } - if (HOP(ATOMIC_START_TOKEN, S.token.type)) { - var atom = S.token.type == "regexp" - ? as("regexp", S.token.value[0], S.token.value[1]) - : as(S.token.type, S.token.value); - return subscripts(prog1(atom, next), allow_calls); - } - unexpected(); - }); - - function expr_list(closing, allow_trailing_comma, allow_empty) { - var first = true, a = []; - while (!is("punc", closing)) { - if (first) first = false; else expect(","); - if (allow_trailing_comma && is("punc", closing)) break; - if (is("punc", ",") && allow_empty) { - a.push([ "atom", "undefined" ]); - } else { - a.push(expression(false)); - } - } - next(); - return a; - }; - - function array_() { - return as("array", expr_list("]", !exigent_mode, true)); - }; - - function object_() { - var first = true, a = []; - while (!is("punc", "}")) { - if (first) first = false; else expect(","); - if (!exigent_mode && is("punc", "}")) - // allow trailing comma - break; - var type = S.token.type; - var name = as_property_name(); - if (type == "name" && (name == "get" || name == "set") && !is("punc", ":")) { - a.push([ as_name(), function_(false), name ]); - } else { - expect(":"); - a.push([ name, expression(false) ]); - } - } - next(); - return as("object", a); - }; - - function as_property_name() { - switch (S.token.type) { - case "num": - case "string": - return prog1(S.token.value, next); - } - return as_name(); - }; - - function as_name() { - switch (S.token.type) { - case "name": - case "operator": - case "keyword": - case "atom": - return prog1(S.token.value, next); - default: - unexpected(); - } - }; - - function subscripts(expr, allow_calls) { - if (is("punc", ".")) { - next(); - return subscripts(as("dot", expr, as_name()), allow_calls); - } - if (is("punc", "[")) { - next(); - return subscripts(as("sub", expr, prog1(expression, curry(expect, "]"))), allow_calls); - } - if (allow_calls && is("punc", "(")) { - next(); - return subscripts(as("call", expr, expr_list(")")), true); - } - return expr; - }; - - function maybe_unary(allow_calls) { - if (is("operator") && HOP(UNARY_PREFIX, S.token.value)) { - return make_unary("unary-prefix", - prog1(S.token.value, next), - maybe_unary(allow_calls)); - } - var val = expr_atom(allow_calls); - while (is("operator") && HOP(UNARY_POSTFIX, S.token.value) && !S.token.nlb) { - val = make_unary("unary-postfix", S.token.value, val); - next(); - } - return val; - }; - - function make_unary(tag, op, expr) { - if ((op == "++" || op == "--") && !is_assignable(expr)) - croak("Invalid use of " + op + " operator"); - return as(tag, op, expr); - }; - - function expr_op(left, min_prec, no_in) { - var op = is("operator") ? S.token.value : null; - if (op && op == "in" && no_in) op = null; - var prec = op != null ? PRECEDENCE[op] : null; - if (prec != null && prec > min_prec) { - next(); - var right = expr_op(maybe_unary(true), prec, no_in); - return expr_op(as("binary", op, left, right), min_prec, no_in); - } - return left; - }; - - function expr_ops(no_in) { - return expr_op(maybe_unary(true), 0, no_in); - }; - - function maybe_conditional(no_in) { - var expr = expr_ops(no_in); - if (is("operator", "?")) { - next(); - var yes = expression(false); - expect(":"); - return as("conditional", expr, yes, expression(false, no_in)); - } - return expr; - }; - - function is_assignable(expr) { - if (!exigent_mode) return true; - switch (expr[0]+"") { - case "dot": - case "sub": - case "new": - case "call": - return true; - case "name": - return expr[1] != "this"; - } - }; - - function maybe_assign(no_in) { - var left = maybe_conditional(no_in), val = S.token.value; - if (is("operator") && HOP(ASSIGNMENT, val)) { - if (is_assignable(left)) { - next(); - return as("assign", ASSIGNMENT[val], left, maybe_assign(no_in)); - } - croak("Invalid assignment"); - } - return left; - }; - - var expression = maybe_embed_tokens(function(commas, no_in) { - if (arguments.length == 0) - commas = true; - var expr = maybe_assign(no_in); - if (commas && is("punc", ",")) { - next(); - return as("seq", expr, expression(true, no_in)); - } - return expr; - }); - - function in_loop(cont) { - try { - ++S.in_loop; - return cont(); - } finally { - --S.in_loop; - } - }; - - return as("toplevel", (function(a){ - while (!is("eof")) - a.push(statement()); - return a; - })([])); - -}; - -/* -----[ Utilities ]----- */ - -function curry(f) { - var args = slice(arguments, 1); - return function() { return f.apply(this, args.concat(slice(arguments))); }; -}; - -function prog1(ret) { - if (ret instanceof Function) - ret = ret(); - for (var i = 1, n = arguments.length; --n > 0; ++i) - arguments[i](); - return ret; -}; - -function array_to_hash(a) { - var ret = {}; - for (var i = 0; i < a.length; ++i) - ret[a[i]] = true; - return ret; -}; - -function slice(a, start) { - return Array.prototype.slice.call(a, start || 0); -}; - -function characters(str) { - return str.split(""); -}; - -function member(name, array) { - for (var i = array.length; --i >= 0;) - if (array[i] == name) - return true; - return false; -}; - -function HOP(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); -}; - -var warn = function() {}; - -/* -----[ Exports ]----- */ - -exports.tokenizer = tokenizer; -exports.parse = parse; -exports.slice = slice; -exports.curry = curry; -exports.member = member; -exports.array_to_hash = array_to_hash; -exports.PRECEDENCE = PRECEDENCE; -exports.KEYWORDS_ATOM = KEYWORDS_ATOM; -exports.RESERVED_WORDS = RESERVED_WORDS; -exports.KEYWORDS = KEYWORDS; -exports.ATOMIC_START_TOKEN = ATOMIC_START_TOKEN; -exports.OPERATORS = OPERATORS; -exports.is_alphanumeric_char = is_alphanumeric_char; -exports.is_identifier_start = is_identifier_start; -exports.is_identifier_char = is_identifier_char; -exports.set_logger = function(logger) { - warn = logger; -}; -}); -define('uglifyjs/squeeze-more', ["require", "exports", "module", "./parse-js", "./process"], function(require, exports, module) { - var jsp = require("./parse-js"), - pro = require("./process"), - slice = jsp.slice, - member = jsp.member, - curry = jsp.curry, - MAP = pro.MAP, - PRECEDENCE = jsp.PRECEDENCE, - OPERATORS = jsp.OPERATORS; - -function ast_squeeze_more(ast) { - var w = pro.ast_walker(), walk = w.walk, scope; - function with_scope(s, cont) { - var save = scope, ret; - scope = s; - ret = cont(); - scope = save; - return ret; - }; - function _lambda(name, args, body) { - return [ this[0], name, args, with_scope(body.scope, curry(MAP, body, walk)) ]; - }; - return w.with_walkers({ - "toplevel": function(body) { - return [ this[0], with_scope(this.scope, curry(MAP, body, walk)) ]; - }, - "function": _lambda, - "defun": _lambda, - "new": function(ctor, args) { - if (ctor[0] == "name") { - if (ctor[1] == "Array" && !scope.has("Array")) { - if (args.length != 1) { - return [ "array", args ]; - } else { - return walk([ "call", [ "name", "Array" ], args ]); - } - } else if (ctor[1] == "Object" && !scope.has("Object")) { - if (!args.length) { - return [ "object", [] ]; - } else { - return walk([ "call", [ "name", "Object" ], args ]); - } - } else if ((ctor[1] == "RegExp" || ctor[1] == "Function" || ctor[1] == "Error") && !scope.has(ctor[1])) { - return walk([ "call", [ "name", ctor[1] ], args]); - } - } - }, - "call": function(expr, args) { - if (expr[0] == "dot" && expr[1][0] == "string" && args.length == 1 - && (args[0][1] > 0 && expr[2] == "substring" || expr[2] == "substr")) { - return [ "call", [ "dot", expr[1], "slice"], args]; - } - if (expr[0] == "dot" && expr[2] == "toString" && args.length == 0) { - // foo.toString() ==> foo+"" - if (expr[1][0] == "string") return expr[1]; - return [ "binary", "+", expr[1], [ "string", "" ]]; - } - if (expr[0] == "name") { - if (expr[1] == "Array" && args.length != 1 && !scope.has("Array")) { - return [ "array", args ]; - } - if (expr[1] == "Object" && !args.length && !scope.has("Object")) { - return [ "object", [] ]; - } - if (expr[1] == "String" && !scope.has("String")) { - return [ "binary", "+", args[0], [ "string", "" ]]; - } - } - } - }, function() { - return walk(pro.ast_add_scope(ast)); - }); -}; - -exports.ast_squeeze_more = ast_squeeze_more; -}); -define('uglifyjs/process', ["require", "exports", "module", "./parse-js", "./squeeze-more"], function(require, exports, module) { - -/*********************************************************************** - - A JavaScript tokenizer / parser / beautifier / compressor. - - This version is suitable for Node.js. With minimal changes (the - exports stuff) it should work on any JS platform. - - This file implements some AST processors. They work on data built - by parse-js. - - Exported functions: - - - ast_mangle(ast, options) -- mangles the variable/function names - in the AST. Returns an AST. - - - ast_squeeze(ast) -- employs various optimizations to make the - final generated code even smaller. Returns an AST. - - - gen_code(ast, options) -- generates JS code from the AST. Pass - true (or an object, see the code for some options) as second - argument to get "pretty" (indented) code. - - -------------------------------- (C) --------------------------------- - - Author: Mihai Bazon - - http://mihai.bazon.net/blog - - Distributed under the BSD license: - - Copyright 2010 (c) Mihai Bazon - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the following - disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - - ***********************************************************************/ - -var jsp = require("./parse-js"), - slice = jsp.slice, - member = jsp.member, - is_identifier_char = jsp.is_identifier_char, - PRECEDENCE = jsp.PRECEDENCE, - OPERATORS = jsp.OPERATORS; - -/* -----[ helper for AST traversal ]----- */ - -function ast_walker() { - function _vardefs(defs) { - return [ this[0], MAP(defs, function(def){ - var a = [ def[0] ]; - if (def.length > 1) - a[1] = walk(def[1]); - return a; - }) ]; - }; - function _block(statements) { - var out = [ this[0] ]; - if (statements != null) - out.push(MAP(statements, walk)); - return out; - }; - var walkers = { - "string": function(str) { - return [ this[0], str ]; - }, - "num": function(num) { - return [ this[0], num ]; - }, - "name": function(name) { - return [ this[0], name ]; - }, - "toplevel": function(statements) { - return [ this[0], MAP(statements, walk) ]; - }, - "block": _block, - "splice": _block, - "var": _vardefs, - "const": _vardefs, - "try": function(t, c, f) { - return [ - this[0], - MAP(t, walk), - c != null ? [ c[0], MAP(c[1], walk) ] : null, - f != null ? MAP(f, walk) : null - ]; - }, - "throw": function(expr) { - return [ this[0], walk(expr) ]; - }, - "new": function(ctor, args) { - return [ this[0], walk(ctor), MAP(args, walk) ]; - }, - "switch": function(expr, body) { - return [ this[0], walk(expr), MAP(body, function(branch){ - return [ branch[0] ? walk(branch[0]) : null, - MAP(branch[1], walk) ]; - }) ]; - }, - "break": function(label) { - return [ this[0], label ]; - }, - "continue": function(label) { - return [ this[0], label ]; - }, - "conditional": function(cond, t, e) { - return [ this[0], walk(cond), walk(t), walk(e) ]; - }, - "assign": function(op, lvalue, rvalue) { - return [ this[0], op, walk(lvalue), walk(rvalue) ]; - }, - "dot": function(expr) { - return [ this[0], walk(expr) ].concat(slice(arguments, 1)); - }, - "call": function(expr, args) { - return [ this[0], walk(expr), MAP(args, walk) ]; - }, - "function": function(name, args, body) { - return [ this[0], name, args.slice(), MAP(body, walk) ]; - }, - "debugger": function() { - return [ this[0] ]; - }, - "defun": function(name, args, body) { - return [ this[0], name, args.slice(), MAP(body, walk) ]; - }, - "if": function(conditional, t, e) { - return [ this[0], walk(conditional), walk(t), walk(e) ]; - }, - "for": function(init, cond, step, block) { - return [ this[0], walk(init), walk(cond), walk(step), walk(block) ]; - }, - "for-in": function(vvar, key, hash, block) { - return [ this[0], walk(vvar), walk(key), walk(hash), walk(block) ]; - }, - "while": function(cond, block) { - return [ this[0], walk(cond), walk(block) ]; - }, - "do": function(cond, block) { - return [ this[0], walk(cond), walk(block) ]; - }, - "return": function(expr) { - return [ this[0], walk(expr) ]; - }, - "binary": function(op, left, right) { - return [ this[0], op, walk(left), walk(right) ]; - }, - "unary-prefix": function(op, expr) { - return [ this[0], op, walk(expr) ]; - }, - "unary-postfix": function(op, expr) { - return [ this[0], op, walk(expr) ]; - }, - "sub": function(expr, subscript) { - return [ this[0], walk(expr), walk(subscript) ]; - }, - "object": function(props) { - return [ this[0], MAP(props, function(p){ - return p.length == 2 - ? [ p[0], walk(p[1]) ] - : [ p[0], walk(p[1]), p[2] ]; // get/set-ter - }) ]; - }, - "regexp": function(rx, mods) { - return [ this[0], rx, mods ]; - }, - "array": function(elements) { - return [ this[0], MAP(elements, walk) ]; - }, - "stat": function(stat) { - return [ this[0], walk(stat) ]; - }, - "seq": function() { - return [ this[0] ].concat(MAP(slice(arguments), walk)); - }, - "label": function(name, block) { - return [ this[0], name, walk(block) ]; - }, - "with": function(expr, block) { - return [ this[0], walk(expr), walk(block) ]; - }, - "atom": function(name) { - return [ this[0], name ]; - }, - "directive": function(dir) { - return [ this[0], dir ]; - } - }; - - var user = {}; - var stack = []; - function walk(ast) { - if (ast == null) - return null; - try { - stack.push(ast); - var type = ast[0]; - var gen = user[type]; - if (gen) { - var ret = gen.apply(ast, ast.slice(1)); - if (ret != null) - return ret; - } - gen = walkers[type]; - return gen.apply(ast, ast.slice(1)); - } finally { - stack.pop(); - } - }; - - function dive(ast) { - if (ast == null) - return null; - try { - stack.push(ast); - return walkers[ast[0]].apply(ast, ast.slice(1)); - } finally { - stack.pop(); - } - }; - - function with_walkers(walkers, cont){ - var save = {}, i; - for (i in walkers) if (HOP(walkers, i)) { - save[i] = user[i]; - user[i] = walkers[i]; - } - var ret = cont(); - for (i in save) if (HOP(save, i)) { - if (!save[i]) delete user[i]; - else user[i] = save[i]; - } - return ret; - }; - - return { - walk: walk, - dive: dive, - with_walkers: with_walkers, - parent: function() { - return stack[stack.length - 2]; // last one is current node - }, - stack: function() { - return stack; - } - }; -}; - -/* -----[ Scope and mangling ]----- */ - -function Scope(parent) { - this.names = {}; // names defined in this scope - this.mangled = {}; // mangled names (orig.name => mangled) - this.rev_mangled = {}; // reverse lookup (mangled => orig.name) - this.cname = -1; // current mangled name - this.refs = {}; // names referenced from this scope - this.uses_with = false; // will become TRUE if with() is detected in this or any subscopes - this.uses_eval = false; // will become TRUE if eval() is detected in this or any subscopes - this.directives = []; // directives activated from this scope - this.parent = parent; // parent scope - this.children = []; // sub-scopes - if (parent) { - this.level = parent.level + 1; - parent.children.push(this); - } else { - this.level = 0; - } -}; - -function base54_digits() { - if (typeof DIGITS_OVERRIDE_FOR_TESTING != "undefined") - return DIGITS_OVERRIDE_FOR_TESTING; - else - return "etnrisouaflchpdvmgybwESxTNCkLAOM_DPHBjFIqRUzWXV$JKQGYZ0516372984"; -} - -var base54 = (function(){ - var DIGITS = base54_digits(); - return function(num) { - var ret = "", base = 54; - do { - ret += DIGITS.charAt(num % base); - num = Math.floor(num / base); - base = 64; - } while (num > 0); - return ret; - }; -})(); - -Scope.prototype = { - has: function(name) { - for (var s = this; s; s = s.parent) - if (HOP(s.names, name)) - return s; - }, - has_mangled: function(mname) { - for (var s = this; s; s = s.parent) - if (HOP(s.rev_mangled, mname)) - return s; - }, - toJSON: function() { - return { - names: this.names, - uses_eval: this.uses_eval, - uses_with: this.uses_with - }; - }, - - next_mangled: function() { - // we must be careful that the new mangled name: - // - // 1. doesn't shadow a mangled name from a parent - // scope, unless we don't reference the original - // name from this scope OR from any sub-scopes! - // This will get slow. - // - // 2. doesn't shadow an original name from a parent - // scope, in the event that the name is not mangled - // in the parent scope and we reference that name - // here OR IN ANY SUBSCOPES! - // - // 3. doesn't shadow a name that is referenced but not - // defined (possibly global defined elsewhere). - for (;;) { - var m = base54(++this.cname), prior; - - // case 1. - prior = this.has_mangled(m); - if (prior && this.refs[prior.rev_mangled[m]] === prior) - continue; - - // case 2. - prior = this.has(m); - if (prior && prior !== this && this.refs[m] === prior && !prior.has_mangled(m)) - continue; - - // case 3. - if (HOP(this.refs, m) && this.refs[m] == null) - continue; - - // I got "do" once. :-/ - if (!is_identifier(m)) - continue; - - return m; - } - }, - set_mangle: function(name, m) { - this.rev_mangled[m] = name; - return this.mangled[name] = m; - }, - get_mangled: function(name, newMangle) { - if (this.uses_eval || this.uses_with) return name; // no mangle if eval or with is in use - var s = this.has(name); - if (!s) return name; // not in visible scope, no mangle - if (HOP(s.mangled, name)) return s.mangled[name]; // already mangled in this scope - if (!newMangle) return name; // not found and no mangling requested - return s.set_mangle(name, s.next_mangled()); - }, - references: function(name) { - return name && !this.parent || this.uses_with || this.uses_eval || this.refs[name]; - }, - define: function(name, type) { - if (name != null) { - if (type == "var" || !HOP(this.names, name)) - this.names[name] = type || "var"; - return name; - } - }, - active: function(dir) { - return member(dir, this.directives) || this.parent && this.parent.active(dir); - } -}; - -function ast_add_scope(ast) { - - var current_scope = null; - var w = ast_walker(), walk = w.walk; - var having_eval = []; - - function with_new_scope(cont) { - current_scope = new Scope(current_scope); - current_scope.labels = new Scope(); - var ret = current_scope.body = cont(); - ret.scope = current_scope; - current_scope = current_scope.parent; - return ret; - }; - - function define(name, type) { - return current_scope.define(name, type); - }; - - function reference(name) { - current_scope.refs[name] = true; - }; - - function _lambda(name, args, body) { - var is_defun = this[0] == "defun"; - return [ this[0], is_defun ? define(name, "defun") : name, args, with_new_scope(function(){ - if (!is_defun) define(name, "lambda"); - MAP(args, function(name){ define(name, "arg") }); - return MAP(body, walk); - })]; - }; - - function _vardefs(type) { - return function(defs) { - MAP(defs, function(d){ - define(d[0], type); - if (d[1]) reference(d[0]); - }); - }; - }; - - function _breacont(label) { - if (label) - current_scope.labels.refs[label] = true; - }; - - return with_new_scope(function(){ - // process AST - var ret = w.with_walkers({ - "function": _lambda, - "defun": _lambda, - "label": function(name, stat) { current_scope.labels.define(name) }, - "break": _breacont, - "continue": _breacont, - "with": function(expr, block) { - for (var s = current_scope; s; s = s.parent) - s.uses_with = true; - }, - "var": _vardefs("var"), - "const": _vardefs("const"), - "try": function(t, c, f) { - if (c != null) return [ - this[0], - MAP(t, walk), - [ define(c[0], "catch"), MAP(c[1], walk) ], - f != null ? MAP(f, walk) : null - ]; - }, - "name": function(name) { - if (name == "eval") - having_eval.push(current_scope); - reference(name); - } - }, function(){ - return walk(ast); - }); - - // the reason why we need an additional pass here is - // that names can be used prior to their definition. - - // scopes where eval was detected and their parents - // are marked with uses_eval, unless they define the - // "eval" name. - MAP(having_eval, function(scope){ - if (!scope.has("eval")) while (scope) { - scope.uses_eval = true; - scope = scope.parent; - } - }); - - // for referenced names it might be useful to know - // their origin scope. current_scope here is the - // toplevel one. - function fixrefs(scope, i) { - // do children first; order shouldn't matter - for (i = scope.children.length; --i >= 0;) - fixrefs(scope.children[i]); - for (i in scope.refs) if (HOP(scope.refs, i)) { - // find origin scope and propagate the reference to origin - for (var origin = scope.has(i), s = scope; s; s = s.parent) { - s.refs[i] = origin; - if (s === origin) break; - } - } - }; - fixrefs(current_scope); - - return ret; - }); - -}; - -/* -----[ mangle names ]----- */ - -function ast_mangle(ast, options) { - var w = ast_walker(), walk = w.walk, scope; - options = defaults(options, { - mangle : true, - toplevel : false, - defines : null, - except : null, - no_functions : false - }); - - function get_mangled(name, newMangle) { - if (!options.mangle) return name; - if (!options.toplevel && !scope.parent) return name; // don't mangle toplevel - if (options.except && member(name, options.except)) - return name; - if (options.no_functions && HOP(scope.names, name) && - (scope.names[name] == 'defun' || scope.names[name] == 'lambda')) - return name; - return scope.get_mangled(name, newMangle); - }; - - function get_define(name) { - if (options.defines) { - // we always lookup a defined symbol for the current scope FIRST, so declared - // vars trump a DEFINE symbol, but if no such var is found, then match a DEFINE value - if (!scope.has(name)) { - if (HOP(options.defines, name)) { - return options.defines[name]; - } - } - return null; - } - }; - - function _lambda(name, args, body) { - if (!options.no_functions && options.mangle) { - var is_defun = this[0] == "defun", extra; - if (name) { - if (is_defun) name = get_mangled(name); - else if (body.scope.references(name)) { - extra = {}; - if (!(scope.uses_eval || scope.uses_with)) - name = extra[name] = scope.next_mangled(); - else - extra[name] = name; - } - else name = null; - } - } - body = with_scope(body.scope, function(){ - args = MAP(args, function(name){ return get_mangled(name) }); - return MAP(body, walk); - }, extra); - return [ this[0], name, args, body ]; - }; - - function with_scope(s, cont, extra) { - var _scope = scope; - scope = s; - if (extra) for (var i in extra) if (HOP(extra, i)) { - s.set_mangle(i, extra[i]); - } - for (var i in s.names) if (HOP(s.names, i)) { - get_mangled(i, true); - } - var ret = cont(); - ret.scope = s; - scope = _scope; - return ret; - }; - - function _vardefs(defs) { - return [ this[0], MAP(defs, function(d){ - return [ get_mangled(d[0]), walk(d[1]) ]; - }) ]; - }; - - function _breacont(label) { - if (label) return [ this[0], scope.labels.get_mangled(label) ]; - }; - - return w.with_walkers({ - "function": _lambda, - "defun": function() { - // move function declarations to the top when - // they are not in some block. - var ast = _lambda.apply(this, arguments); - switch (w.parent()[0]) { - case "toplevel": - case "function": - case "defun": - return MAP.at_top(ast); - } - return ast; - }, - "label": function(label, stat) { - if (scope.labels.refs[label]) return [ - this[0], - scope.labels.get_mangled(label, true), - walk(stat) - ]; - return walk(stat); - }, - "break": _breacont, - "continue": _breacont, - "var": _vardefs, - "const": _vardefs, - "name": function(name) { - return get_define(name) || [ this[0], get_mangled(name) ]; - }, - "try": function(t, c, f) { - return [ this[0], - MAP(t, walk), - c != null ? [ get_mangled(c[0]), MAP(c[1], walk) ] : null, - f != null ? MAP(f, walk) : null ]; - }, - "toplevel": function(body) { - var self = this; - return with_scope(self.scope, function(){ - return [ self[0], MAP(body, walk) ]; - }); - }, - "directive": function() { - return MAP.at_top(this); - } - }, function() { - return walk(ast_add_scope(ast)); - }); -}; - -/* -----[ - - compress foo["bar"] into foo.bar, - - remove block brackets {} where possible - - join consecutive var declarations - - various optimizations for IFs: - - if (cond) foo(); else bar(); ==> cond?foo():bar(); - - if (cond) foo(); ==> cond&&foo(); - - if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); // also for throw - - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} - ]----- */ - -var warn = function(){}; - -function best_of(ast1, ast2) { - return gen_code(ast1).length > gen_code(ast2[0] == "stat" ? ast2[1] : ast2).length ? ast2 : ast1; -}; - -function last_stat(b) { - if (b[0] == "block" && b[1] && b[1].length > 0) - return b[1][b[1].length - 1]; - return b; -} - -function aborts(t) { - if (t) switch (last_stat(t)[0]) { - case "return": - case "break": - case "continue": - case "throw": - return true; - } -}; - -function boolean_expr(expr) { - return ( (expr[0] == "unary-prefix" - && member(expr[1], [ "!", "delete" ])) || - - (expr[0] == "binary" - && member(expr[1], [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ])) || - - (expr[0] == "binary" - && member(expr[1], [ "&&", "||" ]) - && boolean_expr(expr[2]) - && boolean_expr(expr[3])) || - - (expr[0] == "conditional" - && boolean_expr(expr[2]) - && boolean_expr(expr[3])) || - - (expr[0] == "assign" - && expr[1] === true - && boolean_expr(expr[3])) || - - (expr[0] == "seq" - && boolean_expr(expr[expr.length - 1])) - ); -}; - -function empty(b) { - return !b || (b[0] == "block" && (!b[1] || b[1].length == 0)); -}; - -function is_string(node) { - return (node[0] == "string" || - node[0] == "unary-prefix" && node[1] == "typeof" || - node[0] == "binary" && node[1] == "+" && - (is_string(node[2]) || is_string(node[3]))); -}; - -var when_constant = (function(){ - - var $NOT_CONSTANT = {}; - - // this can only evaluate constant expressions. If it finds anything - // not constant, it throws $NOT_CONSTANT. - function evaluate(expr) { - switch (expr[0]) { - case "string": - case "num": - return expr[1]; - case "name": - case "atom": - switch (expr[1]) { - case "true": return true; - case "false": return false; - case "null": return null; - } - break; - case "unary-prefix": - switch (expr[1]) { - case "!": return !evaluate(expr[2]); - case "typeof": return typeof evaluate(expr[2]); - case "~": return ~evaluate(expr[2]); - case "-": return -evaluate(expr[2]); - case "+": return +evaluate(expr[2]); - } - break; - case "binary": - var left = expr[2], right = expr[3]; - switch (expr[1]) { - case "&&" : return evaluate(left) && evaluate(right); - case "||" : return evaluate(left) || evaluate(right); - case "|" : return evaluate(left) | evaluate(right); - case "&" : return evaluate(left) & evaluate(right); - case "^" : return evaluate(left) ^ evaluate(right); - case "+" : return evaluate(left) + evaluate(right); - case "*" : return evaluate(left) * evaluate(right); - case "/" : return evaluate(left) / evaluate(right); - case "%" : return evaluate(left) % evaluate(right); - case "-" : return evaluate(left) - evaluate(right); - case "<<" : return evaluate(left) << evaluate(right); - case ">>" : return evaluate(left) >> evaluate(right); - case ">>>" : return evaluate(left) >>> evaluate(right); - case "==" : return evaluate(left) == evaluate(right); - case "===" : return evaluate(left) === evaluate(right); - case "!=" : return evaluate(left) != evaluate(right); - case "!==" : return evaluate(left) !== evaluate(right); - case "<" : return evaluate(left) < evaluate(right); - case "<=" : return evaluate(left) <= evaluate(right); - case ">" : return evaluate(left) > evaluate(right); - case ">=" : return evaluate(left) >= evaluate(right); - case "in" : return evaluate(left) in evaluate(right); - case "instanceof" : return evaluate(left) instanceof evaluate(right); - } - } - throw $NOT_CONSTANT; - }; - - return function(expr, yes, no) { - try { - var val = evaluate(expr), ast; - switch (typeof val) { - case "string": ast = [ "string", val ]; break; - case "number": ast = [ "num", val ]; break; - case "boolean": ast = [ "name", String(val) ]; break; - default: - if (val === null) { ast = [ "atom", "null" ]; break; } - throw new Error("Can't handle constant of type: " + (typeof val)); - } - return yes.call(expr, ast, val); - } catch(ex) { - if (ex === $NOT_CONSTANT) { - if (expr[0] == "binary" - && (expr[1] == "===" || expr[1] == "!==") - && ((is_string(expr[2]) && is_string(expr[3])) - || (boolean_expr(expr[2]) && boolean_expr(expr[3])))) { - expr[1] = expr[1].substr(0, 2); - } - else if (no && expr[0] == "binary" - && (expr[1] == "||" || expr[1] == "&&")) { - // the whole expression is not constant but the lval may be... - try { - var lval = evaluate(expr[2]); - expr = ((expr[1] == "&&" && (lval ? expr[3] : lval)) || - (expr[1] == "||" && (lval ? lval : expr[3])) || - expr); - } catch(ex2) { - // IGNORE... lval is not constant - } - } - return no ? no.call(expr, expr) : null; - } - else throw ex; - } - }; - -})(); - -function warn_unreachable(ast) { - if (!empty(ast)) - warn("Dropping unreachable code: " + gen_code(ast, true)); -}; - -function prepare_ifs(ast) { - var w = ast_walker(), walk = w.walk; - // In this first pass, we rewrite ifs which abort with no else with an - // if-else. For example: - // - // if (x) { - // blah(); - // return y; - // } - // foobar(); - // - // is rewritten into: - // - // if (x) { - // blah(); - // return y; - // } else { - // foobar(); - // } - function redo_if(statements) { - statements = MAP(statements, walk); - - for (var i = 0; i < statements.length; ++i) { - var fi = statements[i]; - if (fi[0] != "if") continue; - - if (fi[3] && walk(fi[3])) continue; - - var t = walk(fi[2]); - if (!aborts(t)) continue; - - var conditional = walk(fi[1]); - - var e_body = redo_if(statements.slice(i + 1)); - var e = e_body.length == 1 ? e_body[0] : [ "block", e_body ]; - - return statements.slice(0, i).concat([ [ - fi[0], // "if" - conditional, // conditional - t, // then - e // else - ] ]); - } - - return statements; - }; - - function redo_if_lambda(name, args, body) { - body = redo_if(body); - return [ this[0], name, args, body ]; - }; - - function redo_if_block(statements) { - return [ this[0], statements != null ? redo_if(statements) : null ]; - }; - - return w.with_walkers({ - "defun": redo_if_lambda, - "function": redo_if_lambda, - "block": redo_if_block, - "splice": redo_if_block, - "toplevel": function(statements) { - return [ this[0], redo_if(statements) ]; - }, - "try": function(t, c, f) { - return [ - this[0], - redo_if(t), - c != null ? [ c[0], redo_if(c[1]) ] : null, - f != null ? redo_if(f) : null - ]; - } - }, function() { - return walk(ast); - }); -}; - -function for_side_effects(ast, handler) { - var w = ast_walker(), walk = w.walk; - var $stop = {}, $restart = {}; - function stop() { throw $stop }; - function restart() { throw $restart }; - function found(){ return handler.call(this, this, w, stop, restart) }; - function unary(op) { - if (op == "++" || op == "--") - return found.apply(this, arguments); - }; - return w.with_walkers({ - "try": found, - "throw": found, - "return": found, - "new": found, - "switch": found, - "break": found, - "continue": found, - "assign": found, - "call": found, - "if": found, - "for": found, - "for-in": found, - "while": found, - "do": found, - "return": found, - "unary-prefix": unary, - "unary-postfix": unary, - "defun": found - }, function(){ - while (true) try { - walk(ast); - break; - } catch(ex) { - if (ex === $stop) break; - if (ex === $restart) continue; - throw ex; - } - }); -}; - -function ast_lift_variables(ast) { - var w = ast_walker(), walk = w.walk, scope; - function do_body(body, env) { - var _scope = scope; - scope = env; - body = MAP(body, walk); - var hash = {}, names = MAP(env.names, function(type, name){ - if (type != "var") return MAP.skip; - if (!env.references(name)) return MAP.skip; - hash[name] = true; - return [ name ]; - }); - if (names.length > 0) { - // looking for assignments to any of these variables. - // we can save considerable space by moving the definitions - // in the var declaration. - for_side_effects([ "block", body ], function(ast, walker, stop, restart) { - if (ast[0] == "assign" - && ast[1] === true - && ast[2][0] == "name" - && HOP(hash, ast[2][1])) { - // insert the definition into the var declaration - for (var i = names.length; --i >= 0;) { - if (names[i][0] == ast[2][1]) { - if (names[i][1]) // this name already defined, we must stop - stop(); - names[i][1] = ast[3]; // definition - names.push(names.splice(i, 1)[0]); - break; - } - } - // remove this assignment from the AST. - var p = walker.parent(); - if (p[0] == "seq") { - var a = p[2]; - a.unshift(0, p.length); - p.splice.apply(p, a); - } - else if (p[0] == "stat") { - p.splice(0, p.length, "block"); // empty statement - } - else { - stop(); - } - restart(); - } - stop(); - }); - body.unshift([ "var", names ]); - } - scope = _scope; - return body; - }; - function _vardefs(defs) { - var ret = null; - for (var i = defs.length; --i >= 0;) { - var d = defs[i]; - if (!d[1]) continue; - d = [ "assign", true, [ "name", d[0] ], d[1] ]; - if (ret == null) ret = d; - else ret = [ "seq", d, ret ]; - } - if (ret == null) { - if (w.parent()[0] == "for-in") - return [ "name", defs[0][0] ]; - return MAP.skip; - } - return [ "stat", ret ]; - }; - function _toplevel(body) { - return [ this[0], do_body(body, this.scope) ]; - }; - return w.with_walkers({ - "function": function(name, args, body){ - for (var i = args.length; --i >= 0 && !body.scope.references(args[i]);) - args.pop(); - if (!body.scope.references(name)) name = null; - return [ this[0], name, args, do_body(body, body.scope) ]; - }, - "defun": function(name, args, body){ - if (!scope.references(name)) return MAP.skip; - for (var i = args.length; --i >= 0 && !body.scope.references(args[i]);) - args.pop(); - return [ this[0], name, args, do_body(body, body.scope) ]; - }, - "var": _vardefs, - "toplevel": _toplevel - }, function(){ - return walk(ast_add_scope(ast)); - }); -}; - -function ast_squeeze(ast, options) { - options = defaults(options, { - make_seqs : true, - dead_code : true, - no_warnings : false, - keep_comps : true, - unsafe : false - }); - - var w = ast_walker(), walk = w.walk, scope; - - function negate(c) { - var not_c = [ "unary-prefix", "!", c ]; - switch (c[0]) { - case "unary-prefix": - return c[1] == "!" && boolean_expr(c[2]) ? c[2] : not_c; - case "seq": - c = slice(c); - c[c.length - 1] = negate(c[c.length - 1]); - return c; - case "conditional": - return best_of(not_c, [ "conditional", c[1], negate(c[2]), negate(c[3]) ]); - case "binary": - var op = c[1], left = c[2], right = c[3]; - if (!options.keep_comps) switch (op) { - case "<=" : return [ "binary", ">", left, right ]; - case "<" : return [ "binary", ">=", left, right ]; - case ">=" : return [ "binary", "<", left, right ]; - case ">" : return [ "binary", "<=", left, right ]; - } - switch (op) { - case "==" : return [ "binary", "!=", left, right ]; - case "!=" : return [ "binary", "==", left, right ]; - case "===" : return [ "binary", "!==", left, right ]; - case "!==" : return [ "binary", "===", left, right ]; - case "&&" : return best_of(not_c, [ "binary", "||", negate(left), negate(right) ]); - case "||" : return best_of(not_c, [ "binary", "&&", negate(left), negate(right) ]); - } - break; - } - return not_c; - }; - - function make_conditional(c, t, e) { - var make_real_conditional = function() { - if (c[0] == "unary-prefix" && c[1] == "!") { - return e ? [ "conditional", c[2], e, t ] : [ "binary", "||", c[2], t ]; - } else { - return e ? best_of( - [ "conditional", c, t, e ], - [ "conditional", negate(c), e, t ] - ) : [ "binary", "&&", c, t ]; - } - }; - // shortcut the conditional if the expression has a constant value - return when_constant(c, function(ast, val){ - warn_unreachable(val ? e : t); - return (val ? t : e); - }, make_real_conditional); - }; - - function rmblock(block) { - if (block != null && block[0] == "block" && block[1]) { - if (block[1].length == 1) - block = block[1][0]; - else if (block[1].length == 0) - block = [ "block" ]; - } - return block; - }; - - function _lambda(name, args, body) { - return [ this[0], name, args, with_scope(body.scope, function() { - return tighten(body, "lambda"); - }) ]; - }; - - function with_scope(s, cont) { - var _scope = scope; - scope = s; - var ret = cont(); - scope = _scope; - return ret; - }; - - // this function does a few things: - // 1. discard useless blocks - // 2. join consecutive var declarations - // 3. remove obviously dead code - // 4. transform consecutive statements using the comma operator - // 5. if block_type == "lambda" and it detects constructs like if(foo) return ... - rewrite like if (!foo) { ... } - function tighten(statements, block_type) { - statements = MAP(statements, walk); - - statements = statements.reduce(function(a, stat){ - if (stat[0] == "block") { - if (stat[1]) { - a.push.apply(a, stat[1]); - } - } else { - a.push(stat); - } - return a; - }, []); - - statements = (function(a, prev){ - statements.forEach(function(cur){ - if (prev && ((cur[0] == "var" && prev[0] == "var") || - (cur[0] == "const" && prev[0] == "const"))) { - prev[1] = prev[1].concat(cur[1]); - } else { - a.push(cur); - prev = cur; - } - }); - return a; - })([]); - - if (options.dead_code) statements = (function(a, has_quit){ - statements.forEach(function(st){ - if (has_quit) { - if (st[0] == "function" || st[0] == "defun") { - a.push(st); - } - else if (st[0] == "var" || st[0] == "const") { - if (!options.no_warnings) - warn("Variables declared in unreachable code"); - st[1] = MAP(st[1], function(def){ - if (def[1] && !options.no_warnings) - warn_unreachable([ "assign", true, [ "name", def[0] ], def[1] ]); - return [ def[0] ]; - }); - a.push(st); - } - else if (!options.no_warnings) - warn_unreachable(st); - } - else { - a.push(st); - if (member(st[0], [ "return", "throw", "break", "continue" ])) - has_quit = true; - } - }); - return a; - })([]); - - if (options.make_seqs) statements = (function(a, prev) { - statements.forEach(function(cur){ - if (prev && prev[0] == "stat" && cur[0] == "stat") { - prev[1] = [ "seq", prev[1], cur[1] ]; - } else { - a.push(cur); - prev = cur; - } - }); - if (a.length >= 2 - && a[a.length-2][0] == "stat" - && (a[a.length-1][0] == "return" || a[a.length-1][0] == "throw") - && a[a.length-1][1]) - { - a.splice(a.length - 2, 2, - [ a[a.length-1][0], - [ "seq", a[a.length-2][1], a[a.length-1][1] ]]); - } - return a; - })([]); - - // this increases jQuery by 1K. Probably not such a good idea after all.. - // part of this is done in prepare_ifs anyway. - // if (block_type == "lambda") statements = (function(i, a, stat){ - // while (i < statements.length) { - // stat = statements[i++]; - // if (stat[0] == "if" && !stat[3]) { - // if (stat[2][0] == "return" && stat[2][1] == null) { - // a.push(make_if(negate(stat[1]), [ "block", statements.slice(i) ])); - // break; - // } - // var last = last_stat(stat[2]); - // if (last[0] == "return" && last[1] == null) { - // a.push(make_if(stat[1], [ "block", stat[2][1].slice(0, -1) ], [ "block", statements.slice(i) ])); - // break; - // } - // } - // a.push(stat); - // } - // return a; - // })(0, []); - - return statements; - }; - - function make_if(c, t, e) { - return when_constant(c, function(ast, val){ - if (val) { - t = walk(t); - warn_unreachable(e); - return t || [ "block" ]; - } else { - e = walk(e); - warn_unreachable(t); - return e || [ "block" ]; - } - }, function() { - return make_real_if(c, t, e); - }); - }; - - function abort_else(c, t, e) { - var ret = [ [ "if", negate(c), e ] ]; - if (t[0] == "block") { - if (t[1]) ret = ret.concat(t[1]); - } else { - ret.push(t); - } - return walk([ "block", ret ]); - }; - - function make_real_if(c, t, e) { - c = walk(c); - t = walk(t); - e = walk(e); - - if (empty(e) && empty(t)) - return [ "stat", c ]; - - if (empty(t)) { - c = negate(c); - t = e; - e = null; - } else if (empty(e)) { - e = null; - } else { - // if we have both else and then, maybe it makes sense to switch them? - (function(){ - var a = gen_code(c); - var n = negate(c); - var b = gen_code(n); - if (b.length < a.length) { - var tmp = t; - t = e; - e = tmp; - c = n; - } - })(); - } - var ret = [ "if", c, t, e ]; - if (t[0] == "if" && empty(t[3]) && empty(e)) { - ret = best_of(ret, walk([ "if", [ "binary", "&&", c, t[1] ], t[2] ])); - } - else if (t[0] == "stat") { - if (e) { - if (e[0] == "stat") - ret = best_of(ret, [ "stat", make_conditional(c, t[1], e[1]) ]); - else if (aborts(e)) - ret = abort_else(c, t, e); - } - else { - ret = best_of(ret, [ "stat", make_conditional(c, t[1]) ]); - } - } - else if (e && t[0] == e[0] && (t[0] == "return" || t[0] == "throw") && t[1] && e[1]) { - ret = best_of(ret, [ t[0], make_conditional(c, t[1], e[1] ) ]); - } - else if (e && aborts(t)) { - ret = [ [ "if", c, t ] ]; - if (e[0] == "block") { - if (e[1]) ret = ret.concat(e[1]); - } - else { - ret.push(e); - } - ret = walk([ "block", ret ]); - } - else if (t && aborts(e)) { - ret = abort_else(c, t, e); - } - return ret; - }; - - function _do_while(cond, body) { - return when_constant(cond, function(cond, val){ - if (!val) { - warn_unreachable(body); - return [ "block" ]; - } else { - return [ "for", null, null, null, walk(body) ]; - } - }); - }; - - return w.with_walkers({ - "sub": function(expr, subscript) { - if (subscript[0] == "string") { - var name = subscript[1]; - if (is_identifier(name)) - return [ "dot", walk(expr), name ]; - else if (/^[1-9][0-9]*$/.test(name) || name === "0") - return [ "sub", walk(expr), [ "num", parseInt(name, 10) ] ]; - } - }, - "if": make_if, - "toplevel": function(body) { - return with_scope(this.scope, function() { - return [ "toplevel", tighten(body) ]; - }); - }, - "switch": function(expr, body) { - var last = body.length - 1; - return [ "switch", walk(expr), MAP(body, function(branch, i){ - var block = tighten(branch[1]); - if (i == last && block.length > 0) { - var node = block[block.length - 1]; - if (node[0] == "break" && !node[1]) - block.pop(); - } - return [ branch[0] ? walk(branch[0]) : null, block ]; - }) ]; - }, - "function": _lambda, - "defun": _lambda, - "block": function(body) { - if (body) return rmblock([ "block", tighten(body) ]); - }, - "binary": function(op, left, right) { - return when_constant([ "binary", op, walk(left), walk(right) ], function yes(c){ - return best_of(walk(c), this); - }, function no() { - return function(){ - if(op != "==" && op != "!=") return; - var l = walk(left), r = walk(right); - if(l && l[0] == "unary-prefix" && l[1] == "!" && l[2][0] == "num") - left = ['num', +!l[2][1]]; - else if (r && r[0] == "unary-prefix" && r[1] == "!" && r[2][0] == "num") - right = ['num', +!r[2][1]]; - return ["binary", op, left, right]; - }() || this; - }); - }, - "conditional": function(c, t, e) { - return make_conditional(walk(c), walk(t), walk(e)); - }, - "try": function(t, c, f) { - return [ - "try", - tighten(t), - c != null ? [ c[0], tighten(c[1]) ] : null, - f != null ? tighten(f) : null - ]; - }, - "unary-prefix": function(op, expr) { - expr = walk(expr); - var ret = [ "unary-prefix", op, expr ]; - if (op == "!") - ret = best_of(ret, negate(expr)); - return when_constant(ret, function(ast, val){ - return walk(ast); // it's either true or false, so minifies to !0 or !1 - }, function() { return ret }); - }, - "name": function(name) { - switch (name) { - case "true": return [ "unary-prefix", "!", [ "num", 0 ]]; - case "false": return [ "unary-prefix", "!", [ "num", 1 ]]; - } - }, - "while": _do_while, - "assign": function(op, lvalue, rvalue) { - lvalue = walk(lvalue); - rvalue = walk(rvalue); - var okOps = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ]; - if (op === true && lvalue[0] === "name" && rvalue[0] === "binary" && - ~okOps.indexOf(rvalue[1]) && rvalue[2][0] === "name" && - rvalue[2][1] === lvalue[1]) { - return [ this[0], rvalue[1], lvalue, rvalue[3] ] - } - return [ this[0], op, lvalue, rvalue ]; - }, - "directive": function(dir) { - if (scope.active(dir)) - return [ "block" ]; - scope.directives.push(dir); - return [ this[0], dir ]; - }, - "call": function(expr, args) { - expr = walk(expr); - if (options.unsafe && expr[0] == "dot" && expr[1][0] == "string" && expr[2] == "toString") { - return expr[1]; - } - return [ this[0], expr, MAP(args, walk) ]; - }, - "num": function (num) { - if (!isFinite(num)) - return [ "binary", "/", num === 1 / 0 - ? [ "num", 1 ] : num === -1 / 0 - ? [ "unary-prefix", "-", [ "num", 1 ] ] - : [ "num", 0 ], [ "num", 0 ] ]; - - return [ this[0], num ]; - } - }, function() { - for (var i = 0; i < 2; ++i) { - ast = prepare_ifs(ast); - ast = walk(ast_add_scope(ast)); - } - return ast; - }); -}; - -/* -----[ re-generate code from the AST ]----- */ - -var DOT_CALL_NO_PARENS = jsp.array_to_hash([ - "name", - "array", - "object", - "string", - "dot", - "sub", - "call", - "regexp", - "defun" -]); - -function make_string(str, ascii_only) { - var dq = 0, sq = 0; - str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s){ - switch (s) { - case "\\": return "\\\\"; - case "\b": return "\\b"; - case "\f": return "\\f"; - case "\n": return "\\n"; - case "\r": return "\\r"; - case "\u2028": return "\\u2028"; - case "\u2029": return "\\u2029"; - case '"': ++dq; return '"'; - case "'": ++sq; return "'"; - case "\0": return "\\0"; - } - return s; - }); - if (ascii_only) str = to_ascii(str); - if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'"; - else return '"' + str.replace(/\x22/g, '\\"') + '"'; -}; - -function to_ascii(str) { - return str.replace(/[\u0080-\uffff]/g, function(ch) { - var code = ch.charCodeAt(0).toString(16); - while (code.length < 4) code = "0" + code; - return "\\u" + code; - }); -}; - -var SPLICE_NEEDS_BRACKETS = jsp.array_to_hash([ "if", "while", "do", "for", "for-in", "with" ]); - -function gen_code(ast, options) { - options = defaults(options, { - indent_start : 0, - indent_level : 4, - quote_keys : false, - space_colon : false, - beautify : false, - ascii_only : false, - inline_script: false - }); - var beautify = !!options.beautify; - var indentation = 0, - newline = beautify ? "\n" : "", - space = beautify ? " " : ""; - - function encode_string(str) { - var ret = make_string(str, options.ascii_only); - if (options.inline_script) - ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1"); - return ret; - }; - - function make_name(name) { - name = name.toString(); - if (options.ascii_only) - name = to_ascii(name); - return name; - }; - - function indent(line) { - if (line == null) - line = ""; - if (beautify) - line = repeat_string(" ", options.indent_start + indentation * options.indent_level) + line; - return line; - }; - - function with_indent(cont, incr) { - if (incr == null) incr = 1; - indentation += incr; - try { return cont.apply(null, slice(arguments, 1)); } - finally { indentation -= incr; } - }; - - function last_char(str) { - str = str.toString(); - return str.charAt(str.length - 1); - }; - - function first_char(str) { - return str.toString().charAt(0); - }; - - function add_spaces(a) { - if (beautify) - return a.join(" "); - var b = []; - for (var i = 0; i < a.length; ++i) { - var next = a[i + 1]; - b.push(a[i]); - if (next && - ((is_identifier_char(last_char(a[i])) && (is_identifier_char(first_char(next)) - || first_char(next) == "\\")) || - (/[\+\-]$/.test(a[i].toString()) && /^[\+\-]/.test(next.toString())))) { - b.push(" "); - } - } - return b.join(""); - }; - - function add_commas(a) { - return a.join("," + space); - }; - - function parenthesize(expr) { - var gen = make(expr); - for (var i = 1; i < arguments.length; ++i) { - var el = arguments[i]; - if ((el instanceof Function && el(expr)) || expr[0] == el) - return "(" + gen + ")"; - } - return gen; - }; - - function best_of(a) { - if (a.length == 1) { - return a[0]; - } - if (a.length == 2) { - var b = a[1]; - a = a[0]; - return a.length <= b.length ? a : b; - } - return best_of([ a[0], best_of(a.slice(1)) ]); - }; - - function needs_parens(expr) { - if (expr[0] == "function" || expr[0] == "object") { - // dot/call on a literal function requires the - // function literal itself to be parenthesized - // only if it's the first "thing" in a - // statement. This means that the parent is - // "stat", but it could also be a "seq" and - // we're the first in this "seq" and the - // parent is "stat", and so on. Messy stuff, - // but it worths the trouble. - var a = slice(w.stack()), self = a.pop(), p = a.pop(); - while (p) { - if (p[0] == "stat") return true; - if (((p[0] == "seq" || p[0] == "call" || p[0] == "dot" || p[0] == "sub" || p[0] == "conditional") && p[1] === self) || - ((p[0] == "binary" || p[0] == "assign" || p[0] == "unary-postfix") && p[2] === self)) { - self = p; - p = a.pop(); - } else { - return false; - } - } - } - return !HOP(DOT_CALL_NO_PARENS, expr[0]); - }; - - function make_num(num) { - var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m; - if (Math.floor(num) === num) { - if (num >= 0) { - a.push("0x" + num.toString(16).toLowerCase(), // probably pointless - "0" + num.toString(8)); // same. - } else { - a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless - "-0" + (-num).toString(8)); // same. - } - if ((m = /^(.*?)(0+)$/.exec(num))) { - a.push(m[1] + "e" + m[2].length); - } - } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) { - a.push(m[2] + "e-" + (m[1].length + m[2].length), - str.substr(str.indexOf("."))); - } - return best_of(a); - }; - - var w = ast_walker(); - var make = w.walk; - return w.with_walkers({ - "string": encode_string, - "num": make_num, - "name": make_name, - "debugger": function(){ return "debugger;" }, - "toplevel": function(statements) { - return make_block_statements(statements) - .join(newline + newline); - }, - "splice": function(statements) { - var parent = w.parent(); - if (HOP(SPLICE_NEEDS_BRACKETS, parent)) { - // we need block brackets in this case - return make_block.apply(this, arguments); - } else { - return MAP(make_block_statements(statements, true), - function(line, i) { - // the first line is already indented - return i > 0 ? indent(line) : line; - }).join(newline); - } - }, - "block": make_block, - "var": function(defs) { - return "var " + add_commas(MAP(defs, make_1vardef)) + ";"; - }, - "const": function(defs) { - return "const " + add_commas(MAP(defs, make_1vardef)) + ";"; - }, - "try": function(tr, ca, fi) { - var out = [ "try", make_block(tr) ]; - if (ca) out.push("catch", "(" + ca[0] + ")", make_block(ca[1])); - if (fi) out.push("finally", make_block(fi)); - return add_spaces(out); - }, - "throw": function(expr) { - return add_spaces([ "throw", make(expr) ]) + ";"; - }, - "new": function(ctor, args) { - args = args.length > 0 ? "(" + add_commas(MAP(args, function(expr){ - return parenthesize(expr, "seq"); - })) + ")" : ""; - return add_spaces([ "new", parenthesize(ctor, "seq", "binary", "conditional", "assign", function(expr){ - var w = ast_walker(), has_call = {}; - try { - w.with_walkers({ - "call": function() { throw has_call }, - "function": function() { return this } - }, function(){ - w.walk(expr); - }); - } catch(ex) { - if (ex === has_call) - return true; - throw ex; - } - }) + args ]); - }, - "switch": function(expr, body) { - return add_spaces([ "switch", "(" + make(expr) + ")", make_switch_block(body) ]); - }, - "break": function(label) { - var out = "break"; - if (label != null) - out += " " + make_name(label); - return out + ";"; - }, - "continue": function(label) { - var out = "continue"; - if (label != null) - out += " " + make_name(label); - return out + ";"; - }, - "conditional": function(co, th, el) { - return add_spaces([ parenthesize(co, "assign", "seq", "conditional"), "?", - parenthesize(th, "seq"), ":", - parenthesize(el, "seq") ]); - }, - "assign": function(op, lvalue, rvalue) { - if (op && op !== true) op += "="; - else op = "="; - return add_spaces([ make(lvalue), op, parenthesize(rvalue, "seq") ]); - }, - "dot": function(expr) { - var out = make(expr), i = 1; - if (expr[0] == "num") { - if (!/[a-f.]/i.test(out)) - out += "."; - } else if (expr[0] != "function" && needs_parens(expr)) - out = "(" + out + ")"; - while (i < arguments.length) - out += "." + make_name(arguments[i++]); - return out; - }, - "call": function(func, args) { - var f = make(func); - if (f.charAt(0) != "(" && needs_parens(func)) - f = "(" + f + ")"; - return f + "(" + add_commas(MAP(args, function(expr){ - return parenthesize(expr, "seq"); - })) + ")"; - }, - "function": make_function, - "defun": make_function, - "if": function(co, th, el) { - var out = [ "if", "(" + make(co) + ")", el ? make_then(th) : make(th) ]; - if (el) { - out.push("else", make(el)); - } - return add_spaces(out); - }, - "for": function(init, cond, step, block) { - var out = [ "for" ]; - init = (init != null ? make(init) : "").replace(/;*\s*$/, ";" + space); - cond = (cond != null ? make(cond) : "").replace(/;*\s*$/, ";" + space); - step = (step != null ? make(step) : "").replace(/;*\s*$/, ""); - var args = init + cond + step; - if (args == "; ; ") args = ";;"; - out.push("(" + args + ")", make(block)); - return add_spaces(out); - }, - "for-in": function(vvar, key, hash, block) { - return add_spaces([ "for", "(" + - (vvar ? make(vvar).replace(/;+$/, "") : make(key)), - "in", - make(hash) + ")", make(block) ]); - }, - "while": function(condition, block) { - return add_spaces([ "while", "(" + make(condition) + ")", make(block) ]); - }, - "do": function(condition, block) { - return add_spaces([ "do", make(block), "while", "(" + make(condition) + ")" ]) + ";"; - }, - "return": function(expr) { - var out = [ "return" ]; - if (expr != null) out.push(make(expr)); - return add_spaces(out) + ";"; - }, - "binary": function(operator, lvalue, rvalue) { - var left = make(lvalue), right = make(rvalue); - // XXX: I'm pretty sure other cases will bite here. - // we need to be smarter. - // adding parens all the time is the safest bet. - if (member(lvalue[0], [ "assign", "conditional", "seq" ]) || - lvalue[0] == "binary" && PRECEDENCE[operator] > PRECEDENCE[lvalue[1]] || - lvalue[0] == "function" && needs_parens(this)) { - left = "(" + left + ")"; - } - if (member(rvalue[0], [ "assign", "conditional", "seq" ]) || - rvalue[0] == "binary" && PRECEDENCE[operator] >= PRECEDENCE[rvalue[1]] && - !(rvalue[1] == operator && member(operator, [ "&&", "||", "*" ]))) { - right = "(" + right + ")"; - } - else if (!beautify && options.inline_script && (operator == "<" || operator == "<<") - && rvalue[0] == "regexp" && /^script/i.test(rvalue[1])) { - right = " " + right; - } - return add_spaces([ left, operator, right ]); - }, - "unary-prefix": function(operator, expr) { - var val = make(expr); - if (!(expr[0] == "num" || (expr[0] == "unary-prefix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr))) - val = "(" + val + ")"; - return operator + (jsp.is_alphanumeric_char(operator.charAt(0)) ? " " : "") + val; - }, - "unary-postfix": function(operator, expr) { - var val = make(expr); - if (!(expr[0] == "num" || (expr[0] == "unary-postfix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr))) - val = "(" + val + ")"; - return val + operator; - }, - "sub": function(expr, subscript) { - var hash = make(expr); - if (needs_parens(expr)) - hash = "(" + hash + ")"; - return hash + "[" + make(subscript) + "]"; - }, - "object": function(props) { - var obj_needs_parens = needs_parens(this); - if (props.length == 0) - return obj_needs_parens ? "({})" : "{}"; - var out = "{" + newline + with_indent(function(){ - return MAP(props, function(p){ - if (p.length == 3) { - // getter/setter. The name is in p[0], the arg.list in p[1][2], the - // body in p[1][3] and type ("get" / "set") in p[2]. - return indent(make_function(p[0], p[1][2], p[1][3], p[2], true)); - } - var key = p[0], val = parenthesize(p[1], "seq"); - if (options.quote_keys) { - key = encode_string(key); - } else if ((typeof key == "number" || !beautify && +key + "" == key) - && parseFloat(key) >= 0) { - key = make_num(+key); - } else if (!is_identifier(key)) { - key = encode_string(key); - } - return indent(add_spaces(beautify && options.space_colon - ? [ key, ":", val ] - : [ key + ":", val ])); - }).join("," + newline); - }) + newline + indent("}"); - return obj_needs_parens ? "(" + out + ")" : out; - }, - "regexp": function(rx, mods) { - if (options.ascii_only) rx = to_ascii(rx); - return "/" + rx + "/" + mods; - }, - "array": function(elements) { - if (elements.length == 0) return "[]"; - return add_spaces([ "[", add_commas(MAP(elements, function(el, i){ - if (!beautify && el[0] == "atom" && el[1] == "undefined") return i === elements.length - 1 ? "," : ""; - return parenthesize(el, "seq"); - })), "]" ]); - }, - "stat": function(stmt) { - return make(stmt).replace(/;*\s*$/, ";"); - }, - "seq": function() { - return add_commas(MAP(slice(arguments), make)); - }, - "label": function(name, block) { - return add_spaces([ make_name(name), ":", make(block) ]); - }, - "with": function(expr, block) { - return add_spaces([ "with", "(" + make(expr) + ")", make(block) ]); - }, - "atom": function(name) { - return make_name(name); - }, - "directive": function(dir) { - return make_string(dir) + ";"; - } - }, function(){ return make(ast) }); - - // The squeezer replaces "block"-s that contain only a single - // statement with the statement itself; technically, the AST - // is correct, but this can create problems when we output an - // IF having an ELSE clause where the THEN clause ends in an - // IF *without* an ELSE block (then the outer ELSE would refer - // to the inner IF). This function checks for this case and - // adds the block brackets if needed. - function make_then(th) { - if (th == null) return ";"; - if (th[0] == "do") { - // https://github.com/mishoo/UglifyJS/issues/#issue/57 - // IE croaks with "syntax error" on code like this: - // if (foo) do ... while(cond); else ... - // we need block brackets around do/while - return make_block([ th ]); - } - var b = th; - while (true) { - var type = b[0]; - if (type == "if") { - if (!b[3]) - // no else, we must add the block - return make([ "block", [ th ]]); - b = b[3]; - } - else if (type == "while" || type == "do") b = b[2]; - else if (type == "for" || type == "for-in") b = b[4]; - else break; - } - return make(th); - }; - - function make_function(name, args, body, keyword, no_parens) { - var out = keyword || "function"; - if (name) { - out += " " + make_name(name); - } - out += "(" + add_commas(MAP(args, make_name)) + ")"; - out = add_spaces([ out, make_block(body) ]); - return (!no_parens && needs_parens(this)) ? "(" + out + ")" : out; - }; - - function must_has_semicolon(node) { - switch (node[0]) { - case "with": - case "while": - return empty(node[2]) || must_has_semicolon(node[2]); - case "for": - case "for-in": - return empty(node[4]) || must_has_semicolon(node[4]); - case "if": - if (empty(node[2]) && !node[3]) return true; // `if' with empty `then' and no `else' - if (node[3]) { - if (empty(node[3])) return true; // `else' present but empty - return must_has_semicolon(node[3]); // dive into the `else' branch - } - return must_has_semicolon(node[2]); // dive into the `then' branch - case "directive": - return true; - } - }; - - function make_block_statements(statements, noindent) { - for (var a = [], last = statements.length - 1, i = 0; i <= last; ++i) { - var stat = statements[i]; - var code = make(stat); - if (code != ";") { - if (!beautify && i == last && !must_has_semicolon(stat)) { - code = code.replace(/;+\s*$/, ""); - } - a.push(code); - } - } - return noindent ? a : MAP(a, indent); - }; - - function make_switch_block(body) { - var n = body.length; - if (n == 0) return "{}"; - return "{" + newline + MAP(body, function(branch, i){ - var has_body = branch[1].length > 0, code = with_indent(function(){ - return indent(branch[0] - ? add_spaces([ "case", make(branch[0]) + ":" ]) - : "default:"); - }, 0.5) + (has_body ? newline + with_indent(function(){ - return make_block_statements(branch[1]).join(newline); - }) : ""); - if (!beautify && has_body && i < n - 1) - code += ";"; - return code; - }).join(newline) + newline + indent("}"); - }; - - function make_block(statements) { - if (!statements) return ";"; - if (statements.length == 0) return "{}"; - return "{" + newline + with_indent(function(){ - return make_block_statements(statements).join(newline); - }) + newline + indent("}"); - }; - - function make_1vardef(def) { - var name = def[0], val = def[1]; - if (val != null) - name = add_spaces([ make_name(name), "=", parenthesize(val, "seq") ]); - return name; - }; - -}; - -function split_lines(code, max_line_length) { - var splits = [ 0 ]; - jsp.parse(function(){ - var next_token = jsp.tokenizer(code); - var last_split = 0; - var prev_token; - function current_length(tok) { - return tok.pos - last_split; - }; - function split_here(tok) { - last_split = tok.pos; - splits.push(last_split); - }; - function custom(){ - var tok = next_token.apply(this, arguments); - out: { - if (prev_token) { - if (prev_token.type == "keyword") break out; - } - if (current_length(tok) > max_line_length) { - switch (tok.type) { - case "keyword": - case "atom": - case "name": - case "punc": - split_here(tok); - break out; - } - } - } - prev_token = tok; - return tok; - }; - custom.context = function() { - return next_token.context.apply(this, arguments); - }; - return custom; - }()); - return splits.map(function(pos, i){ - return code.substring(pos, splits[i + 1] || code.length); - }).join("\n"); -}; - -/* -----[ Utilities ]----- */ - -function repeat_string(str, i) { - if (i <= 0) return ""; - if (i == 1) return str; - var d = repeat_string(str, i >> 1); - d += d; - if (i & 1) d += str; - return d; -}; - -function defaults(args, defs) { - var ret = {}; - if (args === true) - args = {}; - for (var i in defs) if (HOP(defs, i)) { - ret[i] = (args && HOP(args, i)) ? args[i] : defs[i]; - } - return ret; -}; - -function is_identifier(name) { - return /^[a-z_$][a-z0-9_$]*$/i.test(name) - && name != "this" - && !HOP(jsp.KEYWORDS_ATOM, name) - && !HOP(jsp.RESERVED_WORDS, name) - && !HOP(jsp.KEYWORDS, name); -}; - -function HOP(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); -}; - -// some utilities - -var MAP; - -(function(){ - MAP = function(a, f, o) { - var ret = [], top = [], i; - function doit() { - var val = f.call(o, a[i], i); - if (val instanceof AtTop) { - val = val.v; - if (val instanceof Splice) { - top.push.apply(top, val.v); - } else { - top.push(val); - } - } - else if (val != skip) { - if (val instanceof Splice) { - ret.push.apply(ret, val.v); - } else { - ret.push(val); - } - } - }; - if (a instanceof Array) for (i = 0; i < a.length; ++i) doit(); - else for (i in a) if (HOP(a, i)) doit(); - return top.concat(ret); - }; - MAP.at_top = function(val) { return new AtTop(val) }; - MAP.splice = function(val) { return new Splice(val) }; - var skip = MAP.skip = {}; - function AtTop(val) { this.v = val }; - function Splice(val) { this.v = val }; -})(); - -/* -----[ Exports ]----- */ - -exports.ast_walker = ast_walker; -exports.ast_mangle = ast_mangle; -exports.ast_squeeze = ast_squeeze; -exports.ast_lift_variables = ast_lift_variables; -exports.gen_code = gen_code; -exports.ast_add_scope = ast_add_scope; -exports.set_logger = function(logger) { warn = logger }; -exports.make_string = make_string; -exports.split_lines = split_lines; -exports.MAP = MAP; - -// keep this last! -exports.ast_squeeze_more = require("./squeeze-more").ast_squeeze_more; -}); -define('uglifyjs/index', ["require", "exports", "module", "./parse-js", "./process", "./consolidator"], function(require, exports, module) { -//convienence function(src, [options]); -function uglify(orig_code, options){ - options || (options = {}); - var jsp = uglify.parser; - var pro = uglify.uglify; - - var ast = jsp.parse(orig_code, options.strict_semicolons); // parse code and get the initial AST - ast = pro.ast_mangle(ast, options.mangle_options); // get a new AST with mangled names - ast = pro.ast_squeeze(ast, options.squeeze_options); // get an AST with compression optimizations - var final_code = pro.gen_code(ast, options.gen_options); // compressed code here - return final_code; -}; - -uglify.parser = require("./parse-js"); -uglify.uglify = require("./process"); -uglify.consolidator = require("./consolidator"); - -module.exports = uglify -});/** - * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint plusplus: true */ -/*global define: false */ - -define('parse', ['./esprima', './uglifyjs/index'], function (esprima, uglify) { - 'use strict'; - - var parser = uglify.parser, - processor = uglify.uglify, - ostring = Object.prototype.toString, - isArray; - - if (Array.isArray) { - isArray = Array.isArray; - } else { - isArray = function (it) { - return ostring.call(it) === "[object Array]"; - }; - } - - /** - * Determines if the AST node is an array literal - */ - function isArrayLiteral(node) { - return node[0] === 'array'; - } - - /** - * Determines if the AST node is an object literal - */ - function isObjectLiteral(node) { - return node[0] === 'object'; - } - - /** - * Converts a regular JS array of strings to an AST node that - * represents that array. - * @param {Array} ary - * @param {Node} an AST node that represents an array of strings. - */ - function toAstArray(ary) { - var output = [ - 'array', - [] - ], - i, item; - - for (i = 0; i < ary.length; i++) { - item = ary[i]; - output[1].push([ - 'string', - item - ]); - } - - return output; - } - - /** - * Validates a node as being an object literal (like for i18n bundles) - * or an array literal with just string members. If an array literal, - * only return array members that are full strings. So the caller of - * this function should use the return value as the new value for the - * node. - * - * This function does not need to worry about comments, they are not - * present in this AST. - * - * @param {Node} node an AST node. - * - * @returns {Node} an AST node to use for the valid dependencies. - * If null is returned, then it means the input node was not a valid - * dependency. - */ - function validateDeps(node) { - var newDeps = ['array', []], - arrayArgs, i, dep; - - if (!node) { - return null; - } - - if (isObjectLiteral(node) || node[0] === 'function') { - return node; - } - - //Dependencies can be an object literal or an array. - if (!isArrayLiteral(node)) { - return null; - } - - arrayArgs = node[1]; - - for (i = 0; i < arrayArgs.length; i++) { - dep = arrayArgs[i]; - if (dep[0] === 'string') { - newDeps[1].push(dep); - } - } - return newDeps[1].length ? newDeps : null; - } - - /** - * Gets dependencies from a node, but only if it is an array literal, - * and only if the dependency is a string literal. - * - * This function does not need to worry about comments, they are not - * present in this AST. - * - * @param {Node} node an AST node. - * - * @returns {Array} of valid dependencies. - * If null is returned, then it means the input node was not a valid - * array literal, or did not have any string literals.. - */ - function getValidDeps(node) { - var newDeps = [], - arrayArgs, i, dep; - - if (!node) { - return null; - } - - if (isObjectLiteral(node) || node[0] === 'function') { - return null; - } - - //Dependencies can be an object literal or an array. - if (!isArrayLiteral(node)) { - return null; - } - - arrayArgs = node[1]; - - for (i = 0; i < arrayArgs.length; i++) { - dep = arrayArgs[i]; - if (dep[0] === 'string') { - newDeps.push(dep[1]); - } - } - return newDeps.length ? newDeps : null; - } - - /** - * Main parse function. Returns a string of any valid require or define/require.def - * calls as part of one JavaScript source string. - * @param {String} moduleName the module name that represents this file. - * It is used to create a default define if there is not one already for the file. - * This allows properly tracing dependencies for builds. Otherwise, if - * the file just has a require() call, the file dependencies will not be - * properly reflected: the file will come before its dependencies. - * @param {String} moduleName - * @param {String} fileName - * @param {String} fileContents - * @param {Object} options optional options. insertNeedsDefine: true will - * add calls to require.needsDefine() if appropriate. - * @returns {String} JS source string or null, if no require or define/require.def - * calls are found. - */ - function parse(moduleName, fileName, fileContents, options) { - options = options || {}; - - //Set up source input - var moduleDeps = [], - result = '', - moduleList = [], - needsDefine = true, - astRoot = parser.parse(fileContents), - i, moduleCall, depString; - - parse.recurse(astRoot, function (callName, config, name, deps) { - //If name is an array, it means it is an anonymous module, - //so adjust args appropriately. An anonymous module could - //have a FUNCTION as the name type, but just ignore those - //since we just want to find dependencies. - if (name && isArrayLiteral(name)) { - deps = name; - name = null; - } - - deps = getValidDeps(deps); - if (!deps) { - deps = []; - } - - //Get the name as a string literal, if it is available. - if (name && name[0] === 'string') { - name = name[1]; - } else { - name = null; - } - - if (callName === 'define' && (!name || name === moduleName)) { - needsDefine = false; - } - - if (!name) { - //If there is no module name, the dependencies are for - //this file/default module name. - moduleDeps = moduleDeps.concat(deps); - } else { - moduleList.push({ - name: name, - deps: deps - }); - } - - //If define was found, no need to dive deeper, unless - //the config explicitly wants to dig deeper. - return !options.findNestedDependencies; - }, options); - - if (options.insertNeedsDefine && needsDefine) { - result += 'require.needsDefine("' + moduleName + '");'; - } - - if (moduleDeps.length || moduleList.length) { - for (i = 0; i < moduleList.length; i++) { - moduleCall = moduleList[i]; - if (result) { - result += '\n'; - } - - //If this is the main module for this file, combine any - //"anonymous" dependencies (could come from a nested require - //call) with this module. - if (moduleCall.name === moduleName) { - moduleCall.deps = moduleCall.deps.concat(moduleDeps); - moduleDeps = []; - } - - depString = moduleCall.deps.length ? '["' + moduleCall.deps.join('","') + '"]' : '[]'; - result += 'define("' + moduleCall.name + '",' + depString + ');'; - } - if (moduleDeps.length) { - if (result) { - result += '\n'; - } - depString = moduleDeps.length ? '["' + moduleDeps.join('","') + '"]' : '[]'; - result += 'define("' + moduleName + '",' + depString + ');'; - } - } - - return result || null; - } - - //Add some private methods to object for use in derived objects. - parse.isArray = isArray; - parse.isObjectLiteral = isObjectLiteral; - parse.isArrayLiteral = isArrayLiteral; - - /** - * Handles parsing a file recursively for require calls. - * @param {Array} parentNode the AST node to start with. - * @param {Function} onMatch function to call on a parse match. - * @param {Object} [options] This is normally the build config options if - * it is passed. - * @param {Function} [recurseCallback] function to call on each valid - * node, defaults to parse.parseNode. - */ - parse.recurse = function (parentNode, onMatch, options, recurseCallback) { - var hasHas = options && options.has, - i, node; - - recurseCallback = recurseCallback || this.parseNode; - - if (isArray(parentNode)) { - for (i = 0; i < parentNode.length; i++) { - node = parentNode[i]; - if (isArray(node)) { - //If has config is in play, if calls have been converted - //by this point to be true/false values. So, if - //options has a 'has' value, skip if branches that have - //literal false values. - - //uglify returns if constructs in an array: - //[0]: 'if' - //[1]: the condition, ['name', true | false] for the has replaced case. - //[2]: the block to process if true - //[3]: the block to process if false - //For if/else if/else, the else if is in the [3], - //so only ever have to deal with this structure. - if (hasHas && node[0] === 'if' && node[1] && node[1][0] === 'name' && - (node[1][1] === 'true' || node[1][1] === 'false')) { - if (node[1][1] === 'true') { - this.recurse([node[2]], onMatch, options, recurseCallback); - } else { - this.recurse([node[3]], onMatch, options, recurseCallback); - } - } else { - //If the onMatch indicated parsing should - //stop for children of this node, stop, otherwise, - //keep going. - if (!recurseCallback(node, onMatch)) { - this.recurse(node, onMatch, options, recurseCallback); - } - } - } - } - } - }; - - /** - * Determines if the file defines require(). - * @param {String} fileName - * @param {String} fileContents - * @returns {Boolean} - */ - parse.definesRequire = function (fileName, fileContents) { - var astRoot = parser.parse(fileContents); - return this.nodeHasRequire(astRoot); - }; - - /** - * Finds require("") calls inside a CommonJS anonymous module wrapped in a - * define(function(require, exports, module){}) wrapper. These dependencies - * will be added to a modified define() call that lists the dependencies - * on the outside of the function. - * @param {String} fileName - * @param {String} fileContents - * @returns {Array} an array of module names that are dependencies. Always - * returns an array, but could be of length zero. - */ - parse.getAnonDeps = function (fileName, fileContents) { - var astRoot = parser.parse(fileContents), - defFunc = this.findAnonDefineFactory(astRoot); - - return parse.getAnonDepsFromNode(defFunc); - }; - - /** - * Finds require("") calls inside a CommonJS anonymous module wrapped - * in a define function, given an AST node for the definition function. - * @param {Node} node the AST node for the definition function. - * @returns {Array} and array of dependency names. Can be of zero length. - */ - parse.getAnonDepsFromNode = function (node) { - var deps = [], - funcArgLength; - - if (node) { - this.findRequireDepNames(node, deps); - - //If no deps, still add the standard CommonJS require, exports, module, - //in that order, to the deps, but only if specified as function args. - //In particular, if exports is used, it is favored over the return - //value of the function, so only add it if asked. - funcArgLength = node[2] && node[2].length; - if (funcArgLength) { - deps = (funcArgLength > 1 ? ["require", "exports", "module"] : - ["require"]).concat(deps); - } - } - return deps; - }; - - /** - * Finds the function in define(function (require, exports, module){}); - * @param {Array} node - * @returns {Boolean} - */ - parse.findAnonDefineFactory = function (node) { - var callback, i, n, call, args; - - if (isArray(node)) { - if (node[0] === 'call' && node.length > 2) { - call = node[1]; - args = node[2]; - if ((call[0] === 'name' && call[1] === 'define') || - (call[0] === 'dot' && call[1][1] === 'require' && call[2] === 'def')) { - - //There should only be one argument and it should be a function, - //or a named module with function as second arg - if (args.length === 1 && args[0][0] === 'function') { - return args[0]; - } else if (args.length === 2 && args[0][0] === 'string' && - args[1][0] === 'function') { - return args[1]; - } - } - } - - //Check child nodes - for (i = 0; i < node.length; i++) { - n = node[i]; - callback = this.findAnonDefineFactory(n); - if (callback) { - return callback; - } - } - } - - return null; - }; - - /** - * Finds any config that is passed to requirejs. - * @param {String} fileName - * @param {String} fileContents - * - * @returns {Object} a config object. Will be null if no config. - * Can throw an error if the config in the file cannot be evaluated in - * a build context to valid JavaScript. - */ - parse.findConfig = function (fileName, fileContents) { - /*jslint evil: true */ - //This is a litle bit inefficient, it ends up with two uglifyjs parser - //calls. Can revisit later, but trying to build out larger functional - //pieces first. - var foundConfig = null, - astRoot = parser.parse(fileContents); - - parse.recurse(astRoot, function (configNode) { - var jsConfig; - - if (!foundConfig && configNode) { - jsConfig = parse.nodeToString(configNode); - foundConfig = eval('(' + jsConfig + ')'); - return foundConfig; - } - return undefined; - }, null, parse.parseConfigNode); - - return foundConfig; - }; - - /** - * Finds all dependencies specified in dependency arrays and inside - * simplified commonjs wrappers. - * @param {String} fileName - * @param {String} fileContents - * - * @returns {Array} an array of dependency strings. The dependencies - * have not been normalized, they may be relative IDs. - */ - parse.findDependencies = function (fileName, fileContents, options) { - //This is a litle bit inefficient, it ends up with two uglifyjs parser - //calls. Can revisit later, but trying to build out larger functional - //pieces first. - var dependencies = [], - astRoot = parser.parse(fileContents); - - parse.recurse(astRoot, function (callName, config, name, deps) { - //Normalize the input args. - if (name && isArrayLiteral(name)) { - deps = name; - name = null; - } - - deps = getValidDeps(deps); - if (deps) { - dependencies = dependencies.concat(deps); - } - }, options); - - return dependencies; - }; - - /** - * Finds only CJS dependencies, ones that are the form require('stringLiteral') - */ - parse.findCjsDependencies = function (fileName, fileContents, options) { - //This is a litle bit inefficient, it ends up with two uglifyjs parser - //calls. Can revisit later, but trying to build out larger functional - //pieces first. - var dependencies = [], - astRoot = parser.parse(fileContents); - - parse.recurse(astRoot, function (dep) { - dependencies.push(dep); - }, options, function (node, onMatch) { - - var call, args; - - if (!isArray(node)) { - return false; - } - - if (node[0] === 'call') { - call = node[1]; - args = node[2]; - - if (call) { - //A require('') use. - if (call[0] === 'name' && call[1] === 'require' && - args[0][0] === 'string') { - return onMatch(args[0][1]); - } - } - } - - return false; - - }); - - return dependencies; - }; - - /** - * Determines if define(), require({}|[]) or requirejs was called in the - * file. Also finds out if define() is declared and if define.amd is called. - */ - parse.usesAmdOrRequireJs = function (fileName, fileContents, options) { - var astRoot = parser.parse(fileContents), - uses; - - parse.recurse(astRoot, function (prop) { - if (!uses) { - uses = {}; - } - uses[prop] = true; - }, options, parse.findAmdOrRequireJsNode); - - return uses; - }; - - /** - * Determines if require(''), exports.x =, module.exports =, - * __dirname, __filename are used. So, not strictly traditional CommonJS, - * also checks for Node variants. - */ - parse.usesCommonJs = function (fileName, fileContents, options) { - var uses = null, - assignsExports = false, - astRoot = parser.parse(fileContents); - - parse.recurse(astRoot, function (prop) { - if (prop === 'varExports') { - assignsExports = true; - } else if (prop !== 'exports' || !assignsExports) { - if (!uses) { - uses = {}; - } - uses[prop] = true; - } - }, options, function (node, onMatch) { - - var call, args; - - if (!isArray(node)) { - return false; - } - - if (node[0] === 'name' && (node[1] === '__dirname' || node[1] === '__filename')) { - return onMatch(node[1].substring(2)); - } else if (node[0] === 'var' && node[1] && node[1][0] && node[1][0][0] === 'exports') { - //Hmm, a variable assignment for exports, so does not use cjs exports. - return onMatch('varExports'); - } else if (node[0] === 'assign' && node[2] && node[2][0] === 'dot') { - args = node[2][1]; - - if (args) { - //An exports or module.exports assignment. - if (args[0] === 'name' && args[1] === 'module' && - node[2][2] === 'exports') { - return onMatch('moduleExports'); - } else if (args[0] === 'name' && args[1] === 'exports') { - return onMatch('exports'); - } - } - } else if (node[0] === 'call') { - call = node[1]; - args = node[2]; - - if (call) { - //A require('') use. - if (call[0] === 'name' && call[1] === 'require' && - args[0][0] === 'string') { - return onMatch('require'); - } - } - } - - return false; - - }); - - return uses; - }; - - - parse.findRequireDepNames = function (node, deps) { - var moduleName, i, n, call, args; - - if (isArray(node)) { - if (node[0] === 'call') { - call = node[1]; - args = node[2]; - - if (call && call[0] === 'name' && call[1] === 'require') { - moduleName = args[0]; - if (moduleName[0] === 'string') { - deps.push(moduleName[1]); - } - } - - - } - - //Check child nodes - for (i = 0; i < node.length; i++) { - n = node[i]; - this.findRequireDepNames(n, deps); - } - } - }; - - /** - * Determines if a given node contains a require() definition. - * @param {Array} node - * @returns {Boolean} - */ - parse.nodeHasRequire = function (node) { - var i, n; - - if (this.isDefineNode(node)) { - return true; - } - - if (isArray(node)) { - for (i = 0; i < node.length; i++) { - n = node[i]; - if (this.nodeHasRequire(n)) { - return true; - } - } - } - - return false; - }; - - /** - * Is the given node the actual definition of define(). Actually uses - * the definition of define.amd to find require. - * @param {Array} node - * @returns {Boolean} - */ - parse.isDefineNode = function (node) { - //Actually look for the define.amd = assignment, since - //that is more indicative of RequireJS vs a plain require definition. - var assign; - if (!node) { - return null; - } - - if (node[0] === 'assign' && node[1] === true) { - assign = node[2]; - if (assign[0] === 'dot' && assign[1][0] === 'name' && - assign[1][1] === 'define' && assign[2] === 'amd') { - return true; - } - } - return false; - }; - - /** - * Determines if a specific node is a valid require or define/require.def call. - * @param {Array} node - * @param {Function} onMatch a function to call when a match is found. - * It is passed the match name, and the config, name, deps possible args. - * The config, name and deps args are not normalized. - * - * @returns {String} a JS source string with the valid require/define call. - * Otherwise null. - */ - parse.parseNode = function (node, onMatch) { - var call, name, config, deps, args, cjsDeps; - - if (!isArray(node)) { - return false; - } - - if (node[0] === 'call') { - call = node[1]; - args = node[2]; - - if (call) { - if (call[0] === 'name' && - (call[1] === 'require' || call[1] === 'requirejs')) { - - //It is a plain require() call. - config = args[0]; - deps = args[1]; - if (isArrayLiteral(config)) { - deps = config; - config = null; - } - - deps = validateDeps(deps); - if (!deps) { - return null; - } - - return onMatch("require", null, null, deps); - - } else if (call[0] === 'name' && call[1] === 'define') { - - //A define call - name = args[0]; - deps = args[1]; - //Only allow define calls that match what is expected - //in an AMD call: - //* first arg should be string, array, function or object - //* second arg optional, or array, function or object. - //This helps weed out calls to a non-AMD define, but it is - //not completely robust. Someone could create a define - //function that still matches this shape, but this is the - //best that is possible, and at least allows UglifyJS, - //which does create its own internal define in one file, - //to be inlined. - if (((name[0] === 'string' || isArrayLiteral(name) || - name[0] === 'function' || isObjectLiteral(name))) && - (!deps || isArrayLiteral(deps) || - deps[0] === 'function' || isObjectLiteral(deps) || - // allow define(['dep'], factory) pattern - (isArrayLiteral(name) && deps[0] === 'name' && args.length === 2))) { - - //If first arg is a function, could be a commonjs wrapper, - //look inside for commonjs dependencies. - //Also, if deps is a function look for commonjs deps. - if (name && name[0] === 'function') { - cjsDeps = parse.getAnonDepsFromNode(name); - if (cjsDeps.length) { - name = toAstArray(cjsDeps); - } - } else if (deps && deps[0] === 'function') { - cjsDeps = parse.getAnonDepsFromNode(deps); - if (cjsDeps.length) { - deps = toAstArray(cjsDeps); - } - } - - return onMatch("define", null, name, deps); - } - } - } - } - - return false; - }; - - /** - * Looks for define(), require({} || []), requirejs({} || []) calls. - */ - parse.findAmdOrRequireJsNode = function (node, onMatch) { - var call, args, configNode, type; - - if (!isArray(node)) { - return false; - } - - if (node[0] === 'defun' && node[1] === 'define') { - type = 'declaresDefine'; - } else if (node[0] === 'assign' && node[2] && node[2][2] === 'amd' && - node[2][1] && node[2][1][0] === 'name' && - node[2][1][1] === 'define') { - type = 'defineAmd'; - } else if (node[0] === 'call') { - call = node[1]; - args = node[2]; - - if (call) { - if ((call[0] === 'dot' && - (call[1] && call[1][0] === 'name' && - (call[1][1] === 'require' || call[1][1] === 'requirejs')) && - call[2] === 'config')) { - //A require.config() or requirejs.config() call. - type = call[1][1] + 'Config'; - } else if (call[0] === 'name' && - (call[1] === 'require' || call[1] === 'requirejs')) { - //A require() or requirejs() config call. - //Only want ones that start with an object or an array. - configNode = args[0]; - if (configNode[0] === 'object' || configNode[0] === 'array') { - type = call[1]; - } - } else if (call[0] === 'name' && call[1] === 'define') { - //A define call. - type = 'define'; - } - } - } - - if (type) { - return onMatch(type); - } - - return false; - }; - - /** - * Determines if a specific node is a valid require/requirejs config - * call. That includes calls to require/requirejs.config(). - * @param {Array} node - * @param {Function} onMatch a function to call when a match is found. - * It is passed the match name, and the config, name, deps possible args. - * The config, name and deps args are not normalized. - * - * @returns {String} a JS source string with the valid require/define call. - * Otherwise null. - */ - parse.parseConfigNode = function (node, onMatch) { - var call, configNode, args; - - if (!isArray(node)) { - return false; - } - - if (node[0] === 'call') { - call = node[1]; - args = node[2]; - - if (call) { - //A require.config() or requirejs.config() call. - if ((call[0] === 'dot' && - (call[1] && call[1][0] === 'name' && - (call[1][1] === 'require' || call[1][1] === 'requirejs')) && - call[2] === 'config') || - //A require() or requirejs() config call. - - (call[0] === 'name' && - (call[1] === 'require' || call[1] === 'requirejs')) - ) { - //It is a plain require() call. - configNode = args[0]; - - if (configNode[0] !== 'object') { - return null; - } - - return onMatch(configNode); - - } - } - } - - return false; - }; - - /** - * Converts an AST node into a JS source string. Does not maintain formatting - * or even comments from original source, just returns valid JS source. - * @param {Array} node - * @returns {String} a JS source string. - */ - parse.nodeToString = function (node) { - return processor.gen_code(node, true); - }; - - /** - * Extracts license comments from JS text. - * @param {String} fileName - * @param {String} contents - * @returns {String} a string of license comments. - */ - parse.getLicenseComments = function (fileName, contents) { - var ast = esprima.parse(contents, { - comment: true - }), - result = '', - lineEnd = contents.indexOf('\r') === -1 ? '\n' : '\r\n', - commentNode, refNode, subNode, value, i, j; - - if (ast.comments) { - for (i = 0; i < ast.comments.length; i++) { - commentNode = ast.comments[i]; - - if (commentNode.type === 'Line') { - value = '//' + commentNode.value + lineEnd; - refNode = commentNode; - - if (i + 1 >= ast.comments.length) { - value += lineEnd; - } else { - //Look for immediately adjacent single line comments since - //it could from a multiple line comment made out of single - //line comments. Like this comment. - for (j = i + 1; j < ast.comments.length; j++) { - subNode = ast.comments[j]; - if (subNode.type === 'Line' && subNode.range[0] === refNode.range[1]) { - //Adjacent single line comment. Collect it. - value += '//' + subNode.value + lineEnd; - refNode = subNode; - } else { - //No more single line comment blocks. Break out - //and continue outer looping. - value += lineEnd; - i = j - 1; - break; - } - } - } - } else { - value = '/*' + commentNode.value + '*/' + lineEnd + lineEnd; - } - - if (value.indexOf('license') !== -1 || - (commentNode.type === 'Block' && value.indexOf('/*!') === 0) || - value.indexOf('opyright') !== -1 || - value.indexOf('(c)') !== -1) { - - result += value; - } - - } - } - - return result; - }; - - return parse; -}); -/** - * @license Copyright (c) 2012, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint */ - -define('transform', [ './esprima', './parse', 'logger', 'lang'], -function (esprima, parse, logger, lang) { - - 'use strict'; - var transform; - - return (transform = { - toTransport: function (namespace, moduleName, path, contents, onFound, options) { - options = options || {}; - - var defineRanges = [], - contentInsertion = '', - depString = '', - tokens, info, deps; - - try { - tokens = esprima.parse(contents, { - tokens: true, - range: true - }).tokens; - } catch(e) { - logger.trace('toTransport skipping ' + path + ': ' + - e.toString()); - return contents; - } - - //Find the define calls and their position in the files. - tokens.forEach(function (token, i) { - var namespaceExists = false, - prev, prev2, next, next2, next3, next4, - needsId, depAction, nameCommaRange, foundId, - sourceUrlData; - - if (token.type === 'Identifier' && token.value === 'define') { - //Possible match. Do not want something.define calls - //though, and only defines follow by a paren - prev = tokens[i - 1]; - next = tokens[i + 1]; - - if (prev && prev.type === 'Punctuator' && - prev.value === '.') { - //a define on a sub-object, not a top level - //define() call. If the sub object is the - //namespace, then it is ok. - prev2 = tokens[i - 2]; - if (!prev2) { - return; - } - - //If the prev2 does not match namespace, then bail. - if (!namespace || prev2.type !== 'Identifier' || - prev2.value !== namespace) { - return; - } else if (namespace) { - namespaceExists = true; - } - } - - if (!next || next.type !== 'Punctuator' || - next.value !== '(') { - //Not a define() function call. Bail. - return; - } - - next2 = tokens[i + 2]; - if (!next2) { - return; - } - - //Figure out if this needs a named define call. - if (next2.type === 'Punctuator' && - next2.value === '[') { - //Dependency array - needsId = true; - depAction = 'skip'; - } else if (next2.type === 'Punctuator' && - next2.value === '{') { - //Object literal - needsId = true; - depAction = 'skip'; - } else if (next2.type === 'Keyword' && - next2.value === 'function') { - //function - needsId = true; - depAction = 'scan'; - } else if (next2.type === 'String') { - //Named module - needsId = false; - - //The value includes the quotes around the string, - //so remove them. - foundId = next2.value.substring(1, - next2.value.length - 1); - - //assumed it does not need dependencies injected - - //If next argument is a function it means we need - //dependency scanning. - next3 = tokens[i + 3]; - next4 = tokens[i + 4]; - if (!next3 || !next4) { - return; - } - - if (next3.type === 'Punctuator' && - next3.value === ',' && - next4.type === 'Keyword' && - next4.value === 'function') { - depAction = 'scan'; - nameCommaRange = next3.range; - } else { - depAction = 'skip'; - } - } else if (next2.type === 'Identifier') { - //May be the define(factory); type. - next3 = tokens[i + 3]; - if (!next3) { - return; - } - if (next3.type === 'Punctuator' && - next3.value === ')') { - needsId = true; - depAction = 'empty'; - } else { - return; - } - } else if (next2.type === 'Numeric') { - //May be the define(12345); type. - next3 = tokens[i + 3]; - if (!next3) { - return; - } - if (next3.type === 'Punctuator' && - next3.value === ')') { - needsId = true; - depAction = 'skip'; - } else { - return; - } - } else if (next2.type === 'Punctuator' && - next2.value === '-') { - //May be the define(-12345); type. - next3 = tokens[i + 3]; - if (!next3) { - return; - } - if (next3.type === 'Numeric') { - next4 = tokens[i + 4]; - if (!next4) { - return; - } - if (next4.type === 'Punctuator' && - next4.value === ')') { - needsId = true; - depAction = 'skip'; - } else { - return; - } - } else { - return; - } - } else { - //Not a match, skip it. - return; - } - - defineRanges.push({ - foundId: foundId, - needsId: needsId, - depAction: depAction, - namespaceExists: namespaceExists, - defineRange: token.range, - parenRange: next.range, - nameCommaRange: nameCommaRange, - sourceUrlData: sourceUrlData - }); - } - }); - - //Only do naming and dependency injection if there is one define - //call in the file. - if (defineRanges.length > 1) { - return contents; - } - if (!defineRanges.length) { - return contents; - } - - info = defineRanges[0]; - - //Do the modifications "backwards", in other words, start with the - //one that is farthest down and work up, so that the ranges in the - //defineRanges still apply. So that means deps, id, then namespace. - - if (info.needsId && moduleName) { - contentInsertion += "'" + moduleName + "',"; - } - - if (info.depAction === 'scan') { - deps = parse.getAnonDeps(path, contents); - - if (deps.length) { - depString = '[' + deps.map(function (dep) { - return "'" + dep + "'"; - }) + ']'; - } else { - depString = '[]'; - } - depString += ','; - - if (info.nameCommaRange) { - //Already have a named module, need to insert the - //dependencies after the name. - contents = contents.substring(0, info.nameCommaRange[1]) + - depString + - contents.substring(info.nameCommaRange[1], - contents.length); - } else { - contentInsertion += depString; - } - } else if (info.depAction === 'empty') { - contentInsertion += '[],'; - } - - if (contentInsertion) { - contents = contents.substring(0, info.parenRange[1]) + - contentInsertion + - contents.substring(info.parenRange[1], - contents.length); - } - - //Do namespace last so that ui does not mess upthe parenRange - //used above. - if (namespace && !info.namespaceExists) { - contents = contents.substring(0, info.defineRange[0]) + - namespace + '.' + - contents.substring(info.defineRange[0], - contents.length); - } - - - //Notify any listener for the found info - if (onFound) { - onFound(info); - } - - if (options.useSourceUrl) { - contents = 'eval("' + lang.jsEscape(contents) + - '\\n//@ sourceURL=' + (path.indexOf('/') === 0 ? '' : '/') + path + - '");\n'; - } - - return contents; - } - }); -});/** - * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint regexp: true, plusplus: true */ -/*global define: false */ - -define('pragma', ['parse', 'logger'], function (parse, logger) { - 'use strict'; - function Temp() {} - - function create(obj, mixin) { - Temp.prototype = obj; - var temp = new Temp(), prop; - - //Avoid any extra memory hanging around - Temp.prototype = null; - - if (mixin) { - for (prop in mixin) { - if (mixin.hasOwnProperty(prop) && !temp.hasOwnProperty(prop)) { - temp[prop] = mixin[prop]; - } - } - } - - return temp; // Object - } - - var pragma = { - conditionalRegExp: /(exclude|include)Start\s*\(\s*["'](\w+)["']\s*,(.*)\)/, - useStrictRegExp: /['"]use strict['"];/g, - hasRegExp: /has\s*\(\s*['"]([^'"]+)['"]\s*\)/g, - nsRegExp: /(^|[^\.])(requirejs|require|define)(\.config)?\s*\(/g, - nsWrapRegExp: /\/\*requirejs namespace: true \*\//, - apiDefRegExp: /var requirejs, require, define;/, - defineCheckRegExp: /typeof\s+define\s*===\s*["']function["']\s*&&\s*define\s*\.\s*amd/g, - defineTypeFirstCheckRegExp: /\s*["']function["']\s*===\s*typeof\s+define\s*&&\s*define\s*\.\s*amd/g, - defineJQueryRegExp: /typeof\s+define\s*===\s*["']function["']\s*&&\s*define\s*\.\s*amd\s*&&\s*define\s*\.\s*amd\s*\.\s*jQuery/g, - defineHasRegExp: /typeof\s+define\s*==(=)?\s*['"]function['"]\s*&&\s*typeof\s+define\.amd\s*==(=)?\s*['"]object['"]\s*&&\s*define\.amd/g, - defineTernaryRegExp: /typeof\s+define\s*===\s*['"]function["']\s*&&\s*define\s*\.\s*amd\s*\?\s*define/, - amdefineRegExp: /if\s*\(\s*typeof define\s*\!==\s*'function'\s*\)\s*\{\s*[^\{\}]+amdefine[^\{\}]+\}/g, - - removeStrict: function (contents, config) { - return config.useStrict ? contents : contents.replace(pragma.useStrictRegExp, ''); - }, - - namespace: function (fileContents, ns, onLifecycleName) { - if (ns) { - //Namespace require/define calls - fileContents = fileContents.replace(pragma.nsRegExp, '$1' + ns + '.$2$3('); - - //Namespace define ternary use: - fileContents = fileContents.replace(pragma.defineTernaryRegExp, - "typeof " + ns + ".define === 'function' && " + ns + ".define.amd ? " + ns + ".define"); - - //Namespace define jquery use: - fileContents = fileContents.replace(pragma.defineJQueryRegExp, - "typeof " + ns + ".define === 'function' && " + ns + ".define.amd && " + ns + ".define.amd.jQuery"); - - //Namespace has.js define use: - fileContents = fileContents.replace(pragma.defineHasRegExp, - "typeof " + ns + ".define === 'function' && typeof " + ns + ".define.amd === 'object' && " + ns + ".define.amd"); - - //Namespace define checks. - //Do these ones last, since they are a subset of the more specific - //checks above. - fileContents = fileContents.replace(pragma.defineCheckRegExp, - "typeof " + ns + ".define === 'function' && " + ns + ".define.amd"); - fileContents = fileContents.replace(pragma.defineTypeFirstCheckRegExp, - "'function' === typeof " + ns + ".define && " + ns + ".define.amd"); - - //Check for require.js with the require/define definitions - if (pragma.apiDefRegExp.test(fileContents) && - fileContents.indexOf("if (typeof " + ns + " === 'undefined')") === -1) { - //Wrap the file contents in a typeof check, and a function - //to contain the API globals. - fileContents = "var " + ns + ";(function () { if (typeof " + - ns + " === 'undefined') {\n" + - ns + ' = {};\n' + - fileContents + - "\n" + - ns + ".requirejs = requirejs;" + - ns + ".require = require;" + - ns + ".define = define;\n" + - "}\n}());"; - } - - //Finally, if the file wants a special wrapper because it ties - //in to the requirejs internals in a way that would not fit - //the above matches, do that. Look for /*requirejs namespace: true*/ - if (pragma.nsWrapRegExp.test(fileContents)) { - //Remove the pragma. - fileContents = fileContents.replace(pragma.nsWrapRegExp, ''); - - //Alter the contents. - fileContents = '(function () {\n' + - 'var require = ' + ns + '.require,' + - 'requirejs = ' + ns + '.requirejs,' + - 'define = ' + ns + '.define;\n' + - fileContents + - '\n}());'; - } - } - - return fileContents; - }, - - /** - * processes the fileContents for some //>> conditional statements - */ - process: function (fileName, fileContents, config, onLifecycleName, pluginCollector) { - /*jslint evil: true */ - var foundIndex = -1, startIndex = 0, lineEndIndex, conditionLine, - matches, type, marker, condition, isTrue, endRegExp, endMatches, - endMarkerIndex, shouldInclude, startLength, lifecycleHas, deps, - i, dep, moduleName, collectorMod, - lifecyclePragmas, pragmas = config.pragmas, hasConfig = config.has, - //Legacy arg defined to help in dojo conversion script. Remove later - //when dojo no longer needs conversion: - kwArgs = pragmas; - - //Mix in a specific lifecycle scoped object, to allow targeting - //some pragmas/has tests to only when files are saved, or at different - //lifecycle events. Do not bother with kwArgs in this section, since - //the old dojo kwArgs were for all points in the build lifecycle. - if (onLifecycleName) { - lifecyclePragmas = config['pragmas' + onLifecycleName]; - lifecycleHas = config['has' + onLifecycleName]; - - if (lifecyclePragmas) { - pragmas = create(pragmas || {}, lifecyclePragmas); - } - - if (lifecycleHas) { - hasConfig = create(hasConfig || {}, lifecycleHas); - } - } - - //Replace has references if desired - if (hasConfig) { - fileContents = fileContents.replace(pragma.hasRegExp, function (match, test) { - if (hasConfig.hasOwnProperty(test)) { - return !!hasConfig[test]; - } - return match; - }); - } - - if (!config.skipPragmas) { - - while ((foundIndex = fileContents.indexOf("//>>", startIndex)) !== -1) { - //Found a conditional. Get the conditional line. - lineEndIndex = fileContents.indexOf("\n", foundIndex); - if (lineEndIndex === -1) { - lineEndIndex = fileContents.length - 1; - } - - //Increment startIndex past the line so the next conditional search can be done. - startIndex = lineEndIndex + 1; - - //Break apart the conditional. - conditionLine = fileContents.substring(foundIndex, lineEndIndex + 1); - matches = conditionLine.match(pragma.conditionalRegExp); - if (matches) { - type = matches[1]; - marker = matches[2]; - condition = matches[3]; - isTrue = false; - //See if the condition is true. - try { - isTrue = !!eval("(" + condition + ")"); - } catch (e) { - throw "Error in file: " + - fileName + - ". Conditional comment: " + - conditionLine + - " failed with this error: " + e; - } - - //Find the endpoint marker. - endRegExp = new RegExp('\\/\\/\\>\\>\\s*' + type + 'End\\(\\s*[\'"]' + marker + '[\'"]\\s*\\)', "g"); - endMatches = endRegExp.exec(fileContents.substring(startIndex, fileContents.length)); - if (endMatches) { - endMarkerIndex = startIndex + endRegExp.lastIndex - endMatches[0].length; - - //Find the next line return based on the match position. - lineEndIndex = fileContents.indexOf("\n", endMarkerIndex); - if (lineEndIndex === -1) { - lineEndIndex = fileContents.length - 1; - } - - //Should we include the segment? - shouldInclude = ((type === "exclude" && !isTrue) || (type === "include" && isTrue)); - - //Remove the conditional comments, and optionally remove the content inside - //the conditional comments. - startLength = startIndex - foundIndex; - fileContents = fileContents.substring(0, foundIndex) + - (shouldInclude ? fileContents.substring(startIndex, endMarkerIndex) : "") + - fileContents.substring(lineEndIndex + 1, fileContents.length); - - //Move startIndex to foundIndex, since that is the new position in the file - //where we need to look for more conditionals in the next while loop pass. - startIndex = foundIndex; - } else { - throw "Error in file: " + - fileName + - ". Cannot find end marker for conditional comment: " + - conditionLine; - - } - } - } - } - - //If need to find all plugin resources to optimize, do that now, - //before namespacing, since the namespacing will change the API - //names. - //If there is a plugin collector, scan the file for plugin resources. - if (config.optimizeAllPluginResources && pluginCollector) { - try { - deps = parse.findDependencies(fileName, fileContents); - if (deps.length) { - for (i = 0; i < deps.length; i++) { - dep = deps[i]; - if (dep.indexOf('!') !== -1) { - moduleName = dep.split('!')[0]; - collectorMod = pluginCollector[moduleName]; - if (!collectorMod) { - collectorMod = pluginCollector[moduleName] = []; - } - collectorMod.push(dep); - } - } - } - } catch (eDep) { - logger.error('Parse error looking for plugin resources in ' + - fileName + ', skipping.'); - } - } - - //Strip amdefine use for node-shared modules. - fileContents = fileContents.replace(pragma.amdefineRegExp, ''); - - //Do namespacing - if (onLifecycleName === 'OnSave' && config.namespace) { - fileContents = pragma.namespace(fileContents, config.namespace, onLifecycleName); - } - - - return pragma.removeStrict(fileContents, config); - } - }; - - return pragma; -}); -if(env === 'node') { -/** - * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint strict: false */ -/*global define: false */ - -define('node/optimize', {}); - -} - -if(env === 'rhino') { -/** - * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint strict: false, plusplus: false */ -/*global define: false, java: false, Packages: false */ - -define('rhino/optimize', ['logger'], function (logger) { - - //Add .reduce to Rhino so UglifyJS can run in Rhino, - //inspired by https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce - //but rewritten for brevity, and to be good enough for use by UglifyJS. - if (!Array.prototype.reduce) { - Array.prototype.reduce = function (fn /*, initialValue */) { - var i = 0, - length = this.length, - accumulator; - - if (arguments.length >= 2) { - accumulator = arguments[1]; - } else { - do { - if (i in this) { - accumulator = this[i++]; - break; - } - } - while (true); - } - - for (; i < length; i++) { - if (i in this) { - accumulator = fn.call(undefined, accumulator, this[i], i, this); - } - } - - return accumulator; - }; - } - - var JSSourceFilefromCode, optimize; - - //Bind to Closure compiler, but if it is not available, do not sweat it. - try { - JSSourceFilefromCode = java.lang.Class.forName('com.google.javascript.jscomp.JSSourceFile').getMethod('fromCode', [java.lang.String, java.lang.String]); - } catch (e) {} - - //Helper for closure compiler, because of weird Java-JavaScript interactions. - function closurefromCode(filename, content) { - return JSSourceFilefromCode.invoke(null, [filename, content]); - } - - optimize = { - closure: function (fileName, fileContents, keepLines, config) { - config = config || {}; - var jscomp = Packages.com.google.javascript.jscomp, - flags = Packages.com.google.common.flags, - //Fake extern - externSourceFile = closurefromCode("fakeextern.js", " "), - //Set up source input - jsSourceFile = closurefromCode(String(fileName), String(fileContents)), - options, option, FLAG_compilation_level, compiler, - Compiler = Packages.com.google.javascript.jscomp.Compiler, - result; - - logger.trace("Minifying file: " + fileName); - - //Set up options - options = new jscomp.CompilerOptions(); - for (option in config.CompilerOptions) { - // options are false by default and jslint wanted an if statement in this for loop - if (config.CompilerOptions[option]) { - options[option] = config.CompilerOptions[option]; - } - - } - options.prettyPrint = keepLines || options.prettyPrint; - - FLAG_compilation_level = jscomp.CompilationLevel[config.CompilationLevel || 'SIMPLE_OPTIMIZATIONS']; - FLAG_compilation_level.setOptionsForCompilationLevel(options); - - //Trigger the compiler - Compiler.setLoggingLevel(Packages.java.util.logging.Level[config.loggingLevel || 'WARNING']); - compiler = new Compiler(); - - result = compiler.compile(externSourceFile, jsSourceFile, options); - if (!result.success) { - logger.error('Cannot closure compile file: ' + fileName + '. Skipping it.'); - } else { - fileContents = compiler.toSource(); - } - - return fileContents; - } - }; - - return optimize; -}); -} -/** - * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint plusplus: true, nomen: true, regexp: true */ -/*global define: false */ - -define('optimize', [ 'lang', 'logger', 'env!env/optimize', 'env!env/file', 'parse', - 'pragma', 'uglifyjs/index'], -function (lang, logger, envOptimize, file, parse, - pragma, uglify) { - 'use strict'; - - var optimize, - cssImportRegExp = /\@import\s+(url\()?\s*([^);]+)\s*(\))?([\w, ]*)(;)?/g, - cssCommentImportRegExp = /\/\*[^\*]*@import[^\*]*\*\//g, - cssUrlRegExp = /\url\(\s*([^\)]+)\s*\)?/g; - - /** - * If an URL from a CSS url value contains start/end quotes, remove them. - * This is not done in the regexp, since my regexp fu is not that strong, - * and the CSS spec allows for ' and " in the URL if they are backslash escaped. - * @param {String} url - */ - function cleanCssUrlQuotes(url) { - //Make sure we are not ending in whitespace. - //Not very confident of the css regexps above that there will not be ending - //whitespace. - url = url.replace(/\s+$/, ""); - - if (url.charAt(0) === "'" || url.charAt(0) === "\"") { - url = url.substring(1, url.length - 1); - } - - return url; - } - - /** - * Inlines nested stylesheets that have @import calls in them. - * @param {String} fileName the file name - * @param {String} fileContents the file contents - * @param {String} cssImportIgnore comma delimited string of files to ignore - * @param {Object} included an object used to track the files already imported - */ - function flattenCss(fileName, fileContents, cssImportIgnore, included) { - //Find the last slash in the name. - fileName = fileName.replace(lang.backSlashRegExp, "/"); - var endIndex = fileName.lastIndexOf("/"), - //Make a file path based on the last slash. - //If no slash, so must be just a file name. Use empty string then. - filePath = (endIndex !== -1) ? fileName.substring(0, endIndex + 1) : "", - //store a list of merged files - importList = [], - skippedList = []; - - //First make a pass by removing an commented out @import calls. - fileContents = fileContents.replace(cssCommentImportRegExp, ''); - - //Make sure we have a delimited ignore list to make matching faster - if (cssImportIgnore && cssImportIgnore.charAt(cssImportIgnore.length - 1) !== ",") { - cssImportIgnore += ","; - } - - fileContents = fileContents.replace(cssImportRegExp, function (fullMatch, urlStart, importFileName, urlEnd, mediaTypes) { - //Only process media type "all" or empty media type rules. - if (mediaTypes && ((mediaTypes.replace(/^\s\s*/, '').replace(/\s\s*$/, '')) !== "all")) { - skippedList.push(fileName); - return fullMatch; - } - - importFileName = cleanCssUrlQuotes(importFileName); - - //Ignore the file import if it is part of an ignore list. - if (cssImportIgnore && cssImportIgnore.indexOf(importFileName + ",") !== -1) { - return fullMatch; - } - - //Make sure we have a unix path for the rest of the operation. - importFileName = importFileName.replace(lang.backSlashRegExp, "/"); - - try { - //if a relative path, then tack on the filePath. - //If it is not a relative path, then the readFile below will fail, - //and we will just skip that import. - var fullImportFileName = importFileName.charAt(0) === "/" ? importFileName : filePath + importFileName, - importContents = file.readFile(fullImportFileName), i, - importEndIndex, importPath, fixedUrlMatch, colonIndex, parts, flat; - - //Skip the file if it has already been included. - if (included[fullImportFileName]) { - return ''; - } - included[fullImportFileName] = true; - - //Make sure to flatten any nested imports. - flat = flattenCss(fullImportFileName, importContents, cssImportIgnore, included); - importContents = flat.fileContents; - - if (flat.importList.length) { - importList.push.apply(importList, flat.importList); - } - if (flat.skippedList.length) { - skippedList.push.apply(skippedList, flat.skippedList); - } - - //Make the full import path - importEndIndex = importFileName.lastIndexOf("/"); - - //Make a file path based on the last slash. - //If no slash, so must be just a file name. Use empty string then. - importPath = (importEndIndex !== -1) ? importFileName.substring(0, importEndIndex + 1) : ""; - - //fix url() on relative import (#5) - importPath = importPath.replace(/^\.\//, ''); - - //Modify URL paths to match the path represented by this file. - importContents = importContents.replace(cssUrlRegExp, function (fullMatch, urlMatch) { - fixedUrlMatch = cleanCssUrlQuotes(urlMatch); - fixedUrlMatch = fixedUrlMatch.replace(lang.backSlashRegExp, "/"); - - //Only do the work for relative URLs. Skip things that start with / or have - //a protocol. - colonIndex = fixedUrlMatch.indexOf(":"); - if (fixedUrlMatch.charAt(0) !== "/" && (colonIndex === -1 || colonIndex > fixedUrlMatch.indexOf("/"))) { - //It is a relative URL, tack on the path prefix - urlMatch = importPath + fixedUrlMatch; - } else { - logger.trace(importFileName + "\n URL not a relative URL, skipping: " + urlMatch); - } - - //Collapse .. and . - parts = urlMatch.split("/"); - for (i = parts.length - 1; i > 0; i--) { - if (parts[i] === ".") { - parts.splice(i, 1); - } else if (parts[i] === "..") { - if (i !== 0 && parts[i - 1] !== "..") { - parts.splice(i - 1, 2); - i -= 1; - } - } - } - - return "url(" + parts.join("/") + ")"; - }); - - importList.push(fullImportFileName); - return importContents; - } catch (e) { - logger.warn(fileName + "\n Cannot inline css import, skipping: " + importFileName); - return fullMatch; - } - }); - - return { - importList : importList, - skippedList: skippedList, - fileContents : fileContents - }; - } - - optimize = { - /** - * Optimizes a file that contains JavaScript content. Optionally collects - * plugin resources mentioned in a file, and then passes the content - * through an minifier if one is specified via config.optimize. - * - * @param {String} fileName the name of the file to optimize - * @param {String} fileContents the contents to optimize. If this is - * a null value, then fileName will be used to read the fileContents. - * @param {String} outFileName the name of the file to use for the - * saved optimized content. - * @param {Object} config the build config object. - * @param {Array} [pluginCollector] storage for any plugin resources - * found. - */ - jsFile: function (fileName, fileContents, outFileName, config, pluginCollector) { - if (!fileContents) { - fileContents = file.readFile(fileName); - } - - fileContents = optimize.js(fileName, fileContents, config, pluginCollector); - - file.saveUtf8File(outFileName, fileContents); - }, - - /** - * Optimizes a file that contains JavaScript content. Optionally collects - * plugin resources mentioned in a file, and then passes the content - * through an minifier if one is specified via config.optimize. - * - * @param {String} fileName the name of the file that matches the - * fileContents. - * @param {String} fileContents the string of JS to optimize. - * @param {Object} [config] the build config object. - * @param {Array} [pluginCollector] storage for any plugin resources - * found. - */ - js: function (fileName, fileContents, config, pluginCollector) { - var parts = (String(config.optimize)).split('.'), - optimizerName = parts[0], - keepLines = parts[1] === 'keepLines', - licenseContents = '', - optFunc; - - config = config || {}; - - //Apply pragmas/namespace renaming - fileContents = pragma.process(fileName, fileContents, config, 'OnSave', pluginCollector); - - //Optimize the JS files if asked. - if (optimizerName && optimizerName !== 'none') { - optFunc = envOptimize[optimizerName] || optimize.optimizers[optimizerName]; - if (!optFunc) { - throw new Error('optimizer with name of "' + - optimizerName + - '" not found for this environment'); - } - - if (config.preserveLicenseComments) { - //Pull out any license comments for prepending after optimization. - try { - licenseContents = parse.getLicenseComments(fileName, fileContents); - } catch (e) { - logger.error('Cannot parse file: ' + fileName + ' for comments. Skipping it. Error is:\n' + e.toString()); - } - } - - fileContents = licenseContents + optFunc(fileName, fileContents, keepLines, - config[optimizerName]); - } - - return fileContents; - }, - - /** - * Optimizes one CSS file, inlining @import calls, stripping comments, and - * optionally removes line returns. - * @param {String} fileName the path to the CSS file to optimize - * @param {String} outFileName the path to save the optimized file. - * @param {Object} config the config object with the optimizeCss and - * cssImportIgnore options. - */ - cssFile: function (fileName, outFileName, config) { - - //Read in the file. Make sure we have a JS string. - var originalFileContents = file.readFile(fileName), - flat = flattenCss(fileName, originalFileContents, config.cssImportIgnore, {}), - //Do not use the flattened CSS if there was one that was skipped. - fileContents = flat.skippedList.length ? originalFileContents : flat.fileContents, - startIndex, endIndex, buildText, comment; - - if (flat.skippedList.length) { - logger.warn('Cannot inline @imports for ' + fileName + - ',\nthe following files had media queries in them:\n' + - flat.skippedList.join('\n')); - } - - //Do comment removal. - try { - if (config.optimizeCss.indexOf(".keepComments") === -1) { - startIndex = 0; - //Get rid of comments. - while ((startIndex = fileContents.indexOf("/*", startIndex)) !== -1) { - endIndex = fileContents.indexOf("*/", startIndex + 2); - if (endIndex === -1) { - throw "Improper comment in CSS file: " + fileName; - } - comment = fileContents.substring(startIndex, endIndex); - - if (config.preserveLicenseComments && - (comment.indexOf('license') !== -1 || - comment.indexOf('opyright') !== -1 || - comment.indexOf('(c)') !== -1)) { - //Keep the comment, just increment the startIndex - startIndex = endIndex; - } else { - fileContents = fileContents.substring(0, startIndex) + fileContents.substring(endIndex + 2, fileContents.length); - startIndex = 0; - } - } - } - //Get rid of newlines. - if (config.optimizeCss.indexOf(".keepLines") === -1) { - fileContents = fileContents.replace(/[\r\n]/g, ""); - fileContents = fileContents.replace(/\s+/g, " "); - fileContents = fileContents.replace(/\{\s/g, "{"); - fileContents = fileContents.replace(/\s\}/g, "}"); - } else { - //Remove multiple empty lines. - fileContents = fileContents.replace(/(\r\n)+/g, "\r\n"); - fileContents = fileContents.replace(/(\n)+/g, "\n"); - } - } catch (e) { - fileContents = originalFileContents; - logger.error("Could not optimized CSS file: " + fileName + ", error: " + e); - } - - file.saveUtf8File(outFileName, fileContents); - - //text output to stdout and/or written to build.txt file - buildText = "\n"+ outFileName.replace(config.dir, "") +"\n----------------\n"; - flat.importList.push(fileName); - buildText += flat.importList.map(function(path){ - return path.replace(config.dir, ""); - }).join("\n"); - return buildText +"\n"; - }, - - /** - * Optimizes CSS files, inlining @import calls, stripping comments, and - * optionally removes line returns. - * @param {String} startDir the path to the top level directory - * @param {Object} config the config object with the optimizeCss and - * cssImportIgnore options. - */ - css: function (startDir, config) { - var buildText = "", - i, fileName, fileList; - if (config.optimizeCss.indexOf("standard") !== -1) { - fileList = file.getFilteredFileList(startDir, /\.css$/, true); - if (fileList) { - for (i = 0; i < fileList.length; i++) { - fileName = fileList[i]; - logger.trace("Optimizing (" + config.optimizeCss + ") CSS file: " + fileName); - buildText += optimize.cssFile(fileName, fileName, config); - } - } - } - return buildText; - }, - - optimizers: { - uglify: function (fileName, fileContents, keepLines, config) { - var parser = uglify.parser, - processor = uglify.uglify, - ast, errMessage, errMatch; - - config = config || {}; - - logger.trace("Uglifying file: " + fileName); - - try { - ast = parser.parse(fileContents, config.strict_semicolons); - ast = processor.ast_mangle(ast, config); - ast = processor.ast_squeeze(ast, config); - - fileContents = processor.gen_code(ast, config); - - if (config.max_line_length) { - fileContents = processor.split_lines(fileContents, config.max_line_length); - } - } catch (e) { - errMessage = e.toString(); - errMatch = /\nError(\r)?\n/.exec(errMessage); - if (errMatch) { - errMessage = errMessage.substring(0, errMatch.index); - } - logger.error('Cannot uglify file: ' + fileName + '. Skipping it. Error is:\n' + errMessage); - } - return fileContents; - } - } - }; - - return optimize; -}); -/** - * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ -/* - * This file patches require.js to communicate with the build system. - */ - -//Using sloppy since this uses eval for some code like plugins, -//which may not be strict mode compliant. So if use strict is used -//below they will have strict rules applied and may cause an error. -/*jslint sloppy: true, nomen: true, plusplus: true, regexp: true */ -/*global require, define: true */ - -//NOT asking for require as a dependency since the goal is to modify the -//global require below -define('requirePatch', [ 'env!env/file', 'pragma', 'parse', 'lang', 'logger', 'commonJs'], -function (file, pragma, parse, lang, logger, commonJs) { - - var allowRun = true; - - //This method should be called when the patches to require should take hold. - return function () { - if (!allowRun) { - return; - } - allowRun = false; - - var layer, - pluginBuilderRegExp = /(["']?)pluginBuilder(["']?)\s*[=\:]\s*["']([^'"\s]+)["']/, - oldNewContext = require.s.newContext, - oldDef, - - //create local undefined values for module and exports, - //so that when files are evaled in this function they do not - //see the node values used for r.js - exports, - module; - - //Stored cached file contents for reuse in other layers. - require._cachedFileContents = {}; - - /** - * Makes sure the URL is something that can be supported by the - * optimization tool. - * @param {String} url - * @returns {Boolean} - */ - require._isSupportedBuildUrl = function (url) { - //Ignore URLs with protocols, hosts or question marks, means either network - //access is needed to fetch it or it is too dynamic. Note that - //on Windows, full paths are used for some urls, which include - //the drive, like c:/something, so need to test for something other - //than just a colon. - if (url.indexOf("://") === -1 && url.indexOf("?") === -1 && - url.indexOf('empty:') !== 0 && url.indexOf('//') !== 0) { - return true; - } else { - if (!layer.ignoredUrls[url]) { - logger.info('Cannot optimize network URL, skipping: ' + url); - layer.ignoredUrls[url] = true; - } - return false; - } - }; - - function normalizeUrlWithBase(context, moduleName, url) { - //Adjust the URL if it was not transformed to use baseUrl. - if (require.jsExtRegExp.test(moduleName)) { - url = (context.config.dir || context.config.dirBaseUrl) + url; - } - return url; - } - - //Overrides the new context call to add existing tracking features. - require.s.newContext = function (name) { - var context = oldNewContext(name), - oldEnable = context.enable, - moduleProto = context.Module.prototype, - oldInit = moduleProto.init, - oldCallPlugin = moduleProto.callPlugin; - - //Only do this for the context used for building. - if (name === '_') { - context.needFullExec = {}; - context.fullExec = {}; - context.plugins = {}; - - //Override the shim exports function generator to just - //spit out strings that can be used in the stringified - //build output. - context.makeShimExports = function (exports) { - var result; - if (typeof exports === 'string') { - result = function () { - return '(function (global) {\n' + - ' return function () {\n' + - ' return global.' + exports + ';\n' + - ' }\n' + - '}(this))'; - }; - } else { - result = function () { - return '(function (global) {\n' + - ' return function () {\n' + - ' var func = ' + exports.toString() + ';\n' + - ' return func.apply(global, arguments);\n' + - ' }\n' + - '}(this))'; - }; - } - - //Mark the result has being tranformed by the build already. - result.__buildReady = true; - return result; - }; - - context.enable = function (depMap, parent) { - var id = depMap.id, - parentId = parent && parent.map.id, - needFullExec = context.needFullExec, - fullExec = context.fullExec, - mod = context.registry[id]; - - if (mod && !mod.defined) { - if (parentId && needFullExec[parentId]) { - needFullExec[id] = true; - } - } else if ((needFullExec[id] && !fullExec[id]) || - (parentId && needFullExec[parentId] && !fullExec[id])) { - context.undef(id); - } - - return oldEnable.apply(context, arguments); - }; - - //Override load so that the file paths can be collected. - context.load = function (moduleName, url) { - /*jslint evil: true */ - var contents, pluginBuilderMatch, builderName; - - //Do not mark the url as fetched if it is - //not an empty: URL, used by the optimizer. - //In that case we need to be sure to call - //load() for each module that is mapped to - //empty: so that dependencies are satisfied - //correctly. - if (url.indexOf('empty:') === 0) { - delete context.urlFetched[url]; - } - - //Only handle urls that can be inlined, so that means avoiding some - //URLs like ones that require network access or may be too dynamic, - //like JSONP - if (require._isSupportedBuildUrl(url)) { - //Adjust the URL if it was not transformed to use baseUrl. - url = normalizeUrlWithBase(context, moduleName, url); - - //Save the module name to path and path to module name mappings. - layer.buildPathMap[moduleName] = url; - layer.buildFileToModule[url] = moduleName; - - if (context.plugins.hasOwnProperty(moduleName)) { - //plugins need to have their source evaled as-is. - context.needFullExec[moduleName] = true; - } - - try { - if (require._cachedFileContents.hasOwnProperty(url) && - (!context.needFullExec[moduleName] || context.fullExec[moduleName])) { - contents = require._cachedFileContents[url]; - } else { - //Load the file contents, process for conditionals, then - //evaluate it. - contents = file.readFile(url); - - if (context.config.cjsTranslate) { - contents = commonJs.convert(url, contents); - } - - //If there is a read filter, run it now. - if (context.config.onBuildRead) { - contents = context.config.onBuildRead(moduleName, url, contents); - } - - contents = pragma.process(url, contents, context.config, 'OnExecute'); - - //Find out if the file contains a require() definition. Need to know - //this so we can inject plugins right after it, but before they are needed, - //and to make sure this file is first, so that define calls work. - //This situation mainly occurs when the build is done on top of the output - //of another build, where the first build may include require somewhere in it. - try { - if (!layer.existingRequireUrl && parse.definesRequire(url, contents)) { - layer.existingRequireUrl = url; - } - } catch (e1) { - throw new Error('Parse error using UglifyJS ' + - 'for file: ' + url + '\n' + e1); - } - - if (context.plugins.hasOwnProperty(moduleName)) { - //This is a loader plugin, check to see if it has a build extension, - //otherwise the plugin will act as the plugin builder too. - pluginBuilderMatch = pluginBuilderRegExp.exec(contents); - if (pluginBuilderMatch) { - //Load the plugin builder for the plugin contents. - builderName = context.makeModuleMap(pluginBuilderMatch[3], - context.makeModuleMap(moduleName), - null, - true).id; - contents = file.readFile(context.nameToUrl(builderName)); - } - } - - //Parse out the require and define calls. - //Do this even for plugins in case they have their own - //dependencies that may be separate to how the pluginBuilder works. - try { - if (!context.needFullExec[moduleName]) { - contents = parse(moduleName, url, contents, { - insertNeedsDefine: true, - has: context.config.has, - findNestedDependencies: context.config.findNestedDependencies - }); - } - } catch (e2) { - throw new Error('Parse error using UglifyJS ' + - 'for file: ' + url + '\n' + e2); - } - - require._cachedFileContents[url] = contents; - } - - if (contents) { - eval(contents); - } - - //Need to close out completion of this module - //so that listeners will get notified that it is available. - try { - context.completeLoad(moduleName); - } catch (e) { - //Track which module could not complete loading. - if (!e.moduleTree) { - e.moduleTree = []; - } - e.moduleTree.push(moduleName); - throw e; - } - - } catch (eOuter) { - if (!eOuter.fileName) { - eOuter.fileName = url; - } - throw eOuter; - } - } else { - //With unsupported URLs still need to call completeLoad to - //finish loading. - context.completeLoad(moduleName); - } - }; - - //Marks module has having a name, and optionally executes the - //callback, but only if it meets certain criteria. - context.execCb = function (name, cb, args, exports) { - if (!layer.needsDefine[name]) { - layer.modulesWithNames[name] = true; - } - if (cb.__requireJsBuild || layer.context.needFullExec[name]) { - return cb.apply(exports, args); - } - return undefined; - }; - - moduleProto.init = function(depMaps) { - if (context.needFullExec[this.map.id]) { - lang.each(depMaps, lang.bind(this, function (depMap) { - if (typeof depMap === 'string') { - depMap = context.makeModuleMap(depMap, - (this.map.isDefine ? this.map : this.map.parentMap)); - } - - if (!context.fullExec[depMap.id]) { - context.undef(depMap.id); - } - })); - } - - return oldInit.apply(this, arguments); - }; - - moduleProto.callPlugin = function () { - var map = this.map, - pluginMap = context.makeModuleMap(map.prefix), - pluginId = pluginMap.id, - pluginMod = context.registry[pluginId]; - - context.plugins[pluginId] = true; - context.needFullExec[pluginId] = true; - - //If the module is not waiting to finish being defined, - //undef it and start over, to get full execution. - if (!context.fullExec[pluginId] && (!pluginMod || pluginMod.defined)) { - context.undef(pluginMap.id); - } - - return oldCallPlugin.apply(this, arguments); - }; - } - - return context; - }; - - //Clear up the existing context so that the newContext modifications - //above will be active. - delete require.s.contexts._; - - /** Reset state for each build layer pass. */ - require._buildReset = function () { - var oldContext = require.s.contexts._; - - //Clear up the existing context. - delete require.s.contexts._; - - //Set up new context, so the layer object can hold onto it. - require({}); - - layer = require._layer = { - buildPathMap: {}, - buildFileToModule: {}, - buildFilePaths: [], - pathAdded: {}, - modulesWithNames: {}, - needsDefine: {}, - existingRequireUrl: "", - ignoredUrls: {}, - context: require.s.contexts._ - }; - - //Return the previous context in case it is needed, like for - //the basic config object. - return oldContext; - }; - - require._buildReset(); - - //Override define() to catch modules that just define an object, so that - //a dummy define call is not put in the build file for them. They do - //not end up getting defined via context.execCb, so we need to catch them - //at the define call. - oldDef = define; - - //This function signature does not have to be exact, just match what we - //are looking for. - define = function (name) { - if (typeof name === "string" && !layer.needsDefine[name]) { - layer.modulesWithNames[name] = true; - } - return oldDef.apply(require, arguments); - }; - - define.amd = oldDef.amd; - - //Add some utilities for plugins - require._readFile = file.readFile; - require._fileExists = function (path) { - return file.exists(path); - }; - - //Called when execManager runs for a dependency. Used to figure out - //what order of execution. - require.onResourceLoad = function (context, map) { - var id = map.id, - url; - - //If build needed a full execution, indicate it - //has been done now. But only do it if the context is tracking - //that. Only valid for the context used in a build, not for - //other contexts being run, like for useLib, plain requirejs - //use in node/rhino. - if (context.needFullExec && context.needFullExec[id]) { - context.fullExec[id] = true; - } - - //A plugin. - if (map.prefix) { - if (!layer.pathAdded[id]) { - layer.buildFilePaths.push(id); - //For plugins the real path is not knowable, use the name - //for both module to file and file to module mappings. - layer.buildPathMap[id] = id; - layer.buildFileToModule[id] = id; - layer.modulesWithNames[id] = true; - layer.pathAdded[id] = true; - } - } else if (map.url && require._isSupportedBuildUrl(map.url)) { - //If the url has not been added to the layer yet, and it - //is from an actual file that was loaded, add it now. - url = normalizeUrlWithBase(context, id, map.url); - if (!layer.pathAdded[url] && layer.buildPathMap[id]) { - //Remember the list of dependencies for this layer. - layer.buildFilePaths.push(url); - layer.pathAdded[url] = true; - } - } - }; - - //Called by output of the parse() function, when a file does not - //explicitly call define, probably just require, but the parse() - //function normalizes on define() for dependency mapping and file - //ordering works correctly. - require.needsDefine = function (moduleName) { - layer.needsDefine[moduleName] = true; - }; - }; -}); -/** - * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint */ -/*global define: false, console: false */ - -define('commonJs', ['env!env/file', 'parse'], function (file, parse) { - 'use strict'; - var commonJs = { - //Set to false if you do not want this file to log. Useful in environments - //like node where you want the work to happen without noise. - useLog: true, - - convertDir: function (commonJsPath, savePath) { - var fileList, i, - jsFileRegExp = /\.js$/, - fileName, convertedFileName, fileContents; - - //Get list of files to convert. - fileList = file.getFilteredFileList(commonJsPath, /\w/, true); - - //Normalize on front slashes and make sure the paths do not end in a slash. - commonJsPath = commonJsPath.replace(/\\/g, "/"); - savePath = savePath.replace(/\\/g, "/"); - if (commonJsPath.charAt(commonJsPath.length - 1) === "/") { - commonJsPath = commonJsPath.substring(0, commonJsPath.length - 1); - } - if (savePath.charAt(savePath.length - 1) === "/") { - savePath = savePath.substring(0, savePath.length - 1); - } - - //Cycle through all the JS files and convert them. - if (!fileList || !fileList.length) { - if (commonJs.useLog) { - if (commonJsPath === "convert") { - //A request just to convert one file. - console.log('\n\n' + commonJs.convert(savePath, file.readFile(savePath))); - } else { - console.log("No files to convert in directory: " + commonJsPath); - } - } - } else { - for (i = 0; i < fileList.length; i++) { - fileName = fileList[i]; - convertedFileName = fileName.replace(commonJsPath, savePath); - - //Handle JS files. - if (jsFileRegExp.test(fileName)) { - fileContents = file.readFile(fileName); - fileContents = commonJs.convert(fileName, fileContents); - file.saveUtf8File(convertedFileName, fileContents); - } else { - //Just copy the file over. - file.copyFile(fileName, convertedFileName, true); - } - } - } - }, - - /** - * Does the actual file conversion. - * - * @param {String} fileName the name of the file. - * - * @param {String} fileContents the contents of a file :) - * - * @returns {String} the converted contents - */ - convert: function (fileName, fileContents) { - //Strip out comments. - try { - var preamble = '', - commonJsProps = parse.usesCommonJs(fileName, fileContents); - - //First see if the module is not already RequireJS-formatted. - if (parse.usesAmdOrRequireJs(fileName, fileContents) || !commonJsProps) { - return fileContents; - } - - if (commonJsProps.dirname || commonJsProps.filename) { - preamble = 'var __filename = module.uri || "", ' + - '__dirname = __filename.substring(0, __filename.lastIndexOf("/") + 1);\n'; - } - - //Construct the wrapper boilerplate. - fileContents = 'define(function (require, exports, module) {\n' + - preamble + - fileContents + - '\n});\n'; - - } catch (e) { - console.log("commonJs.convert: COULD NOT CONVERT: " + fileName + ", so skipping it. Error was: " + e); - return fileContents; - } - - return fileContents; - } - }; - - return commonJs; -}); -/** - * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/*jslint plusplus: true, nomen: true, regexp: true */ -/*global define, require */ - - -define('build', [ 'lang', 'logger', 'env!env/file', 'parse', 'optimize', 'pragma', - 'transform', 'env!env/load', 'requirePatch', 'env!env/quit', - 'commonJs'], -function (lang, logger, file, parse, optimize, pragma, - transform, load, requirePatch, quit, - commonJs) { - 'use strict'; - - var build, buildBaseConfig, - endsWithSemiColonRegExp = /;\s*$/; - - buildBaseConfig = { - appDir: "", - pragmas: {}, - paths: {}, - optimize: "uglify", - optimizeCss: "standard.keepLines", - inlineText: true, - isBuild: true, - optimizeAllPluginResources: false, - findNestedDependencies: false, - preserveLicenseComments: true, - //By default, all files/directories are copied, unless - //they match this regexp, by default just excludes .folders - dirExclusionRegExp: file.dirExclusionRegExp - }; - - /** - * Some JS may not be valid if concatenated with other JS, in particular - * the style of omitting semicolons and rely on ASI. Add a semicolon in - * those cases. - */ - function addSemiColon(text) { - if (endsWithSemiColonRegExp.test(text)) { - return text; - } else { - return text + ";"; - } - } - - function endsWithSlash(dirName) { - if (dirName.charAt(dirName.length - 1) !== "/") { - dirName += "/"; - } - return dirName; - } - - //Method used by plugin writeFile calls, defined up here to avoid - //jslint warning about "making a function in a loop". - function makeWriteFile(namespace, layer) { - function writeFile(name, contents) { - logger.trace('Saving plugin-optimized file: ' + name); - file.saveUtf8File(name, contents); - } - - writeFile.asModule = function (moduleName, fileName, contents) { - writeFile(fileName, - build.toTransport(namespace, moduleName, fileName, contents, layer)); - }; - - return writeFile; - } - - /** - * Main API entry point into the build. The args argument can either be - * an array of arguments (like the onese passed on a command-line), - * or it can be a JavaScript object that has the format of a build profile - * file. - * - * If it is an object, then in addition to the normal properties allowed in - * a build profile file, the object should contain one other property: - * - * The object could also contain a "buildFile" property, which is a string - * that is the file path to a build profile that contains the rest - * of the build profile directives. - * - * This function does not return a status, it should throw an error if - * there is a problem completing the build. - */ - build = function (args) { - var stackRegExp = /( {4}at[^\n]+)\n/, - standardIndent = ' ', - buildFile, cmdConfig, errorMsg, errorStack, stackMatch, errorTree, - i, j, errorMod; - - try { - if (!args || lang.isArray(args)) { - if (!args || args.length < 1) { - logger.error("build.js buildProfile.js\n" + - "where buildProfile.js is the name of the build file (see example.build.js for hints on how to make a build file)."); - return undefined; - } - - //Next args can include a build file path as well as other build args. - //build file path comes first. If it does not contain an = then it is - //a build file path. Otherwise, just all build args. - if (args[0].indexOf("=") === -1) { - buildFile = args[0]; - args.splice(0, 1); - } - - //Remaining args are options to the build - cmdConfig = build.convertArrayToObject(args); - cmdConfig.buildFile = buildFile; - } else { - cmdConfig = args; - } - - return build._run(cmdConfig); - } catch (e) { - errorMsg = e.toString(); - errorTree = e.moduleTree; - stackMatch = stackRegExp.exec(errorMsg); - - if (stackMatch) { - errorMsg += errorMsg.substring(0, stackMatch.index + stackMatch[0].length + 1); - } - - //If a module tree that shows what module triggered the error, - //print it out. - if (errorTree && errorTree.length > 0) { - errorMsg += '\nIn module tree:\n'; - - for (i = errorTree.length - 1; i > -1; i--) { - errorMod = errorTree[i]; - if (errorMod) { - for (j = errorTree.length - i; j > -1; j--) { - errorMsg += standardIndent; - } - errorMsg += errorMod + '\n'; - } - } - - logger.error(errorMsg); - } - - errorStack = e.stack; - - if (typeof args === 'string' && args.indexOf('stacktrace=true') !== -1) { - errorMsg += '\n' + errorStack; - } else { - if (!stackMatch && errorStack) { - //Just trim out the first "at" in the stack. - stackMatch = stackRegExp.exec(errorStack); - if (stackMatch) { - errorMsg += '\n' + stackMatch[0] || ''; - } - } - } - - if (logger.level > logger.ERROR) { - throw new Error(errorMsg); - } else { - logger.error(errorMsg); - quit(1); - } - } - }; - - build._run = function (cmdConfig) { - var buildFileContents = "", - pluginCollector = {}, - buildPaths, fileName, fileNames, - prop, paths, i, - baseConfig, config, - modules, builtModule, srcPath, buildContext, - destPath, moduleName, moduleMap, parentModuleMap, context, - resources, resource, pluginProcessed = {}, plugin, fileContents; - - //Can now run the patches to require.js to allow it to be used for - //build generation. Do it here instead of at the top of the module - //because we want normal require behavior to load the build tool - //then want to switch to build mode. - requirePatch(); - - config = build.createConfig(cmdConfig); - paths = config.paths; - - if (config.logLevel) { - logger.logLevel(config.logLevel); - } - - //Remove the previous build dir, in case it contains source transforms, - //like the ones done with onBuildRead and onBuildWrite. - if (config.dir && !config.keepBuildDir && file.exists(config.dir)) { - file.deleteFile(config.dir); - } - - if (!config.out && !config.cssIn) { - //This is not just a one-off file build but a full build profile, with - //lots of files to process. - - //First copy all the baseUrl content - file.copyDir((config.appDir || config.baseUrl), config.dir, /\w/, true); - - //Adjust baseUrl if config.appDir is in play, and set up build output paths. - buildPaths = {}; - if (config.appDir) { - //All the paths should be inside the appDir, so just adjust - //the paths to use the dirBaseUrl - for (prop in paths) { - if (paths.hasOwnProperty(prop)) { - buildPaths[prop] = paths[prop].replace(config.appDir, config.dir); - } - } - } else { - //If no appDir, then make sure to copy the other paths to this directory. - for (prop in paths) { - if (paths.hasOwnProperty(prop)) { - //Set up build path for each path prefix, but only do so - //if the path falls out of the current baseUrl - if (paths[prop].indexOf(config.baseUrl) === 0) { - buildPaths[prop] = paths[prop].replace(config.baseUrl, config.dirBaseUrl); - } else { - buildPaths[prop] = paths[prop] === 'empty:' ? 'empty:' : prop.replace(/\./g, "/"); - - //Make sure source path is fully formed with baseUrl, - //if it is a relative URL. - srcPath = paths[prop]; - if (srcPath.indexOf('/') !== 0 && srcPath.indexOf(':') === -1) { - srcPath = config.baseUrl + srcPath; - } - - destPath = config.dirBaseUrl + buildPaths[prop]; - - //Skip empty: paths - if (srcPath !== 'empty:') { - //If the srcPath is a directory, copy the whole directory. - if (file.exists(srcPath) && file.isDirectory(srcPath)) { - //Copy files to build area. Copy all files (the /\w/ regexp) - file.copyDir(srcPath, destPath, /\w/, true); - } else { - //Try a .js extension - srcPath += '.js'; - destPath += '.js'; - file.copyFile(srcPath, destPath); - } - } - } - } - } - } - } - - //Figure out source file location for each module layer. Do this by seeding require - //with source area configuration. This is needed so that later the module layers - //can be manually copied over to the source area, since the build may be - //require multiple times and the above copyDir call only copies newer files. - require({ - baseUrl: config.baseUrl, - paths: paths, - packagePaths: config.packagePaths, - packages: config.packages - }); - buildContext = require.s.contexts._; - modules = config.modules; - - if (modules) { - modules.forEach(function (module) { - if (module.name) { - module._sourcePath = buildContext.nameToUrl(module.name); - //If the module does not exist, and this is not a "new" module layer, - //as indicated by a true "create" property on the module, and - //it is not a plugin-loaded resource, then throw an error. - if (!file.exists(module._sourcePath) && !module.create && - module.name.indexOf('!') === -1) { - throw new Error("ERROR: module path does not exist: " + - module._sourcePath + " for module named: " + module.name + - ". Path is relative to: " + file.absPath('.')); - } - } - }); - } - - if (config.out) { - //Just set up the _buildPath for the module layer. - require(config); - if (!config.cssIn) { - config.modules[0]._buildPath = typeof config.out === 'function' ? - 'FUNCTION' : config.out; - } - } else if (!config.cssIn) { - //Now set up the config for require to use the build area, and calculate the - //build file locations. Pass along any config info too. - baseConfig = { - baseUrl: config.dirBaseUrl, - paths: buildPaths - }; - - lang.mixin(baseConfig, config); - require(baseConfig); - - if (modules) { - modules.forEach(function (module) { - if (module.name) { - module._buildPath = buildContext.nameToUrl(module.name, null); - if (!module.create) { - file.copyFile(module._sourcePath, module._buildPath); - } - } - }); - } - } - - //Run CSS optimizations before doing JS module tracing, to allow - //things like text loader plugins loading CSS to get the optimized - //CSS. - if (config.optimizeCss && config.optimizeCss !== "none" && config.dir) { - buildFileContents += optimize.css(config.dir, config); - } - - if (modules) { - //For each module layer, call require to calculate dependencies. - modules.forEach(function (module) { - module.layer = build.traceDependencies(module, config); - }); - - //Now build up shadow layers for anything that should be excluded. - //Do this after tracing dependencies for each module, in case one - //of those modules end up being one of the excluded values. - modules.forEach(function (module) { - if (module.exclude) { - module.excludeLayers = []; - module.exclude.forEach(function (exclude, i) { - //See if it is already in the list of modules. - //If not trace dependencies for it. - module.excludeLayers[i] = build.findBuildModule(exclude, modules) || - {layer: build.traceDependencies({name: exclude}, config)}; - }); - } - }); - - modules.forEach(function (module) { - if (module.exclude) { - //module.exclude is an array of module names. For each one, - //get the nested dependencies for it via a matching entry - //in the module.excludeLayers array. - module.exclude.forEach(function (excludeModule, i) { - var excludeLayer = module.excludeLayers[i].layer, map = excludeLayer.buildPathMap, prop; - for (prop in map) { - if (map.hasOwnProperty(prop)) { - build.removeModulePath(prop, map[prop], module.layer); - } - } - }); - } - if (module.excludeShallow) { - //module.excludeShallow is an array of module names. - //shallow exclusions are just that module itself, and not - //its nested dependencies. - module.excludeShallow.forEach(function (excludeShallowModule) { - var path = module.layer.buildPathMap[excludeShallowModule]; - if (path) { - build.removeModulePath(excludeShallowModule, path, module.layer); - } - }); - } - - //Flatten them and collect the build output for each module. - builtModule = build.flattenModule(module, module.layer, config); - - //Save it to a temp file for now, in case there are other layers that - //contain optimized content that should not be included in later - //layer optimizations. See issue #56. - if (module._buildPath === 'FUNCTION') { - module._buildText = builtModule.text; - } else { - file.saveUtf8File(module._buildPath + '-temp', builtModule.text); - } - buildFileContents += builtModule.buildText; - }); - - //Now move the build layers to their final position. - modules.forEach(function (module) { - var finalPath = module._buildPath; - if (finalPath !== 'FUNCTION') { - if (file.exists(finalPath)) { - file.deleteFile(finalPath); - } - file.renameFile(finalPath + '-temp', finalPath); - - //And finally, if removeCombined is specified, remove - //any of the files that were used in this layer. - //Be sure not to remove other build layers. - if (config.removeCombined) { - module.layer.buildFilePaths.forEach(function (path) { - if (file.exists(path) && !modules.some(function (mod) { - return mod._buildPath === path; - })) { - file.deleteFile(path); - } - }); - } - } - }); - } - - //If removeCombined in play, remove any empty directories that - //may now exist because of its use - if (config.removeCombined && !config.out && config.dir) { - file.deleteEmptyDirs(config.dir); - } - - //Do other optimizations. - if (config.out && !config.cssIn) { - //Just need to worry about one JS file. - fileName = config.modules[0]._buildPath; - if (fileName === 'FUNCTION') { - config.modules[0]._buildText = optimize.js(fileName, - config.modules[0]._buildText, - config); - } else { - optimize.jsFile(fileName, null, fileName, config); - } - } else if (!config.cssIn) { - //Normal optimizations across modules. - - //JS optimizations. - fileNames = file.getFilteredFileList(config.dir, /\.js$/, true); - for (i = 0; i < fileNames.length; i++) { - fileName = fileNames[i]; - - //Generate the module name from the config.dir root. - moduleName = fileName.replace(config.dir, ''); - //Get rid of the extension - moduleName = moduleName.substring(0, moduleName.length - 3); - - //Convert the file to transport format, but without a name - //inserted (by passing null for moduleName) since the files are - //standalone, one module per file. - fileContents = file.readFile(fileName); - - //For builds, if wanting cjs translation, do it now, so that - //the individual modules can be loaded cross domain via - //plain script tags. - if (config.cjsTranslate) { - fileContents = commonJs.convert(fileName, fileContents); - } - - fileContents = build.toTransport(config.namespace, - null, - fileName, - fileContents); - - optimize.jsFile(fileName, fileContents, fileName, config, pluginCollector); - } - - //Normalize all the plugin resources. - context = require.s.contexts._; - - for (moduleName in pluginCollector) { - if (pluginCollector.hasOwnProperty(moduleName)) { - parentModuleMap = context.makeModuleMap(moduleName); - resources = pluginCollector[moduleName]; - for (i = 0; i < resources.length; i++) { - resource = resources[i]; - moduleMap = context.makeModuleMap(resource, parentModuleMap); - if (!context.plugins[moduleMap.prefix]) { - //Set the value in context.plugins so it - //will be evaluated as a full plugin. - context.plugins[moduleMap.prefix] = true; - - //Do not bother if the plugin is not available. - if (!file.exists(require.toUrl(moduleMap.prefix + '.js'))) { - continue; - } - - //Rely on the require in the build environment - //to be synchronous - context.require([moduleMap.prefix]); - - //Now that the plugin is loaded, redo the moduleMap - //since the plugin will need to normalize part of the path. - moduleMap = context.makeModuleMap(resource, parentModuleMap); - } - - //Only bother with plugin resources that can be handled - //processed by the plugin, via support of the writeFile - //method. - if (!pluginProcessed[moduleMap.id]) { - //Only do the work if the plugin was really loaded. - //Using an internal access because the file may - //not really be loaded. - plugin = context.defined[moduleMap.prefix]; - if (plugin && plugin.writeFile) { - plugin.writeFile( - moduleMap.prefix, - moduleMap.name, - require, - makeWriteFile( - config.namespace - ), - context.config - ); - } - - pluginProcessed[moduleMap.id] = true; - } - } - - } - } - - //console.log('PLUGIN COLLECTOR: ' + JSON.stringify(pluginCollector, null, " ")); - - - //All module layers are done, write out the build.txt file. - file.saveUtf8File(config.dir + "build.txt", buildFileContents); - } - - //If just have one CSS file to optimize, do that here. - if (config.cssIn) { - buildFileContents += optimize.cssFile(config.cssIn, config.out, config); - } - - if (typeof config.out === 'function') { - config.out(config.modules[0]._buildText); - } - - //Print out what was built into which layers. - if (buildFileContents) { - logger.info(buildFileContents); - return buildFileContents; - } - - return ''; - }; - - /** - * Converts command line args like "paths.foo=../some/path" - * result.paths = { foo: '../some/path' } where prop = paths, - * name = paths.foo and value = ../some/path, so it assumes the - * name=value splitting has already happened. - */ - function stringDotToObj(result, name, value) { - var parts = name.split('.'), - prop = parts[0]; - - parts.forEach(function (prop, i) { - if (i === parts.length - 1) { - result[prop] = value; - } else { - if (!result[prop]) { - result[prop] = {}; - } - result = result[prop]; - } - - }); - } - - //Used by convertArrayToObject to convert some things from prop.name=value - //to a prop: { name: value} - build.dotProps = [ - 'paths.', - 'wrap.', - 'pragmas.', - 'pragmasOnSave.', - 'has.', - 'hasOnSave.', - 'wrap.', - 'uglify.', - 'closure.' - ]; - - build.hasDotPropMatch = function (prop) { - return build.dotProps.some(function (dotProp) { - return prop.indexOf(dotProp) === 0; - }); - }; - - /** - * Converts an array that has String members of "name=value" - * into an object, where the properties on the object are the names in the array. - * Also converts the strings "true" and "false" to booleans for the values. - * member name/value pairs, and converts some comma-separated lists into - * arrays. - * @param {Array} ary - */ - build.convertArrayToObject = function (ary) { - var result = {}, i, separatorIndex, prop, value, - needArray = { - "include": true, - "exclude": true, - "excludeShallow": true, - "insertRequire": true - }; - - for (i = 0; i < ary.length; i++) { - separatorIndex = ary[i].indexOf("="); - if (separatorIndex === -1) { - throw "Malformed name/value pair: [" + ary[i] + "]. Format should be name=value"; - } - - value = ary[i].substring(separatorIndex + 1, ary[i].length); - if (value === "true") { - value = true; - } else if (value === "false") { - value = false; - } - - prop = ary[i].substring(0, separatorIndex); - - //Convert to array if necessary - if (needArray[prop]) { - value = value.split(","); - } - - if (build.hasDotPropMatch(prop)) { - stringDotToObj(result, prop, value); - } else { - result[prop] = value; - } - } - return result; //Object - }; - - build.makeAbsPath = function (path, absFilePath) { - //Add abspath if necessary. If path starts with a slash or has a colon, - //then already is an abolute path. - if (path.indexOf('/') !== 0 && path.indexOf(':') === -1) { - path = absFilePath + - (absFilePath.charAt(absFilePath.length - 1) === '/' ? '' : '/') + - path; - path = file.normalize(path); - } - return path.replace(lang.backSlashRegExp, '/'); - }; - - build.makeAbsObject = function (props, obj, absFilePath) { - var i, prop; - if (obj) { - for (i = 0; i < props.length; i++) { - prop = props[i]; - if (obj.hasOwnProperty(prop) && typeof obj[prop] === 'string') { - obj[prop] = build.makeAbsPath(obj[prop], absFilePath); - } - } - } - }; - - /** - * For any path in a possible config, make it absolute relative - * to the absFilePath passed in. - */ - build.makeAbsConfig = function (config, absFilePath) { - var props, prop, i; - - props = ["appDir", "dir", "baseUrl"]; - for (i = 0; i < props.length; i++) { - prop = props[i]; - - if (config[prop]) { - //Add abspath if necessary, make sure these paths end in - //slashes - if (prop === "baseUrl") { - config.originalBaseUrl = config.baseUrl; - if (config.appDir) { - //If baseUrl with an appDir, the baseUrl is relative to - //the appDir, *not* the absFilePath. appDir and dir are - //made absolute before baseUrl, so this will work. - config.baseUrl = build.makeAbsPath(config.originalBaseUrl, config.appDir); - } else { - //The dir output baseUrl is same as regular baseUrl, both - //relative to the absFilePath. - config.baseUrl = build.makeAbsPath(config[prop], absFilePath); - } - } else { - config[prop] = build.makeAbsPath(config[prop], absFilePath); - } - - config[prop] = endsWithSlash(config[prop]); - } - } - - build.makeAbsObject(["out", "cssIn"], config, absFilePath); - build.makeAbsObject(["startFile", "endFile"], config.wrap, absFilePath); - }; - - build.nestedMix = { - paths: true, - has: true, - hasOnSave: true, - pragmas: true, - pragmasOnSave: true - }; - - /** - * Mixes additional source config into target config, and merges some - * nested config, like paths, correctly. - */ - function mixConfig(target, source) { - var prop, value; - - for (prop in source) { - if (source.hasOwnProperty(prop)) { - //If the value of the property is a plain object, then - //allow a one-level-deep mixing of it. - value = source[prop]; - if (typeof value === 'object' && value && - !lang.isArray(value) && !lang.isFunction(value) && - !lang.isRegExp(value)) { - target[prop] = lang.mixin({}, target[prop], value, true); - } else { - target[prop] = value; - } - } - } - } - - /** - * Creates a config object for an optimization build. - * It will also read the build profile if it is available, to create - * the configuration. - * - * @param {Object} cfg config options that take priority - * over defaults and ones in the build file. These options could - * be from a command line, for instance. - * - * @param {Object} the created config object. - */ - build.createConfig = function (cfg) { - /*jslint evil: true */ - var config = {}, buildFileContents, buildFileConfig, mainConfig, - mainConfigFile, mainConfigPath, prop, buildFile, absFilePath; - - //Make sure all paths are relative to current directory. - absFilePath = file.absPath('.'); - build.makeAbsConfig(cfg, absFilePath); - build.makeAbsConfig(buildBaseConfig, absFilePath); - - lang.mixin(config, buildBaseConfig); - lang.mixin(config, cfg, true); - - if (config.buildFile) { - //A build file exists, load it to get more config. - buildFile = file.absPath(config.buildFile); - - //Find the build file, and make sure it exists, if this is a build - //that has a build profile, and not just command line args with an in=path - if (!file.exists(buildFile)) { - throw new Error("ERROR: build file does not exist: " + buildFile); - } - - absFilePath = config.baseUrl = file.absPath(file.parent(buildFile)); - - //Load build file options. - buildFileContents = file.readFile(buildFile); - try { - buildFileConfig = eval("(" + buildFileContents + ")"); - build.makeAbsConfig(buildFileConfig, absFilePath); - - //Mix in the config now so that items in mainConfigFile can - //be resolved relative to them if necessary, like if appDir - //is set here, but the baseUrl is in mainConfigFile. Will - //re-mix in the same build config later after mainConfigFile - //is processed, since build config should take priority. - mixConfig(config, buildFileConfig); - } catch (e) { - throw new Error("Build file " + buildFile + " is malformed: " + e); - } - } - - mainConfigFile = config.mainConfigFile || (buildFileConfig && buildFileConfig.mainConfigFile); - if (mainConfigFile) { - mainConfigFile = build.makeAbsPath(mainConfigFile, absFilePath); - if (!file.exists(mainConfigFile)) { - throw new Error(mainConfigFile + ' does not exist.'); - } - try { - mainConfig = parse.findConfig(mainConfigFile, file.readFile(mainConfigFile)); - } catch (configError) { - throw new Error('The config in mainConfigFile ' + - mainConfigFile + - ' cannot be used because it cannot be evaluated' + - ' correctly while running in the optimizer. Try only' + - ' using a config that is also valid JSON, or do not use' + - ' mainConfigFile and instead copy the config values needed' + - ' into a build file or command line arguments given to the optimizer.'); - } - if (mainConfig) { - mainConfigPath = mainConfigFile.substring(0, mainConfigFile.lastIndexOf('/')); - - //Add in some existing config, like appDir, since they can be - //used inside the mainConfigFile -- paths and baseUrl are - //relative to them. - if (config.appDir && !mainConfig.appDir) { - mainConfig.appDir = config.appDir; - } - - //If no baseUrl, then use the directory holding the main config. - if (!mainConfig.baseUrl) { - mainConfig.baseUrl = mainConfigPath; - } - - build.makeAbsConfig(mainConfig, mainConfigPath); - mixConfig(config, mainConfig); - } - } - - //Mix in build file config, but only after mainConfig has been mixed in. - if (buildFileConfig) { - mixConfig(config, buildFileConfig); - } - - //Re-apply the override config values. Command line - //args should take precedence over build file values. - mixConfig(config, cfg); - - //Fix paths to full paths so that they can be adjusted consistently - //lately to be in the output area. - lang.eachProp(config.paths, function (value, prop) { - config.paths[prop] = build.makeAbsPath(value, config.baseUrl); - }); - - //Set final output dir - if (config.hasOwnProperty("baseUrl")) { - if (config.appDir) { - config.dirBaseUrl = build.makeAbsPath(config.originalBaseUrl, config.dir); - } else { - config.dirBaseUrl = config.dir || config.baseUrl; - } - //Make sure dirBaseUrl ends in a slash, since it is - //concatenated with other strings. - config.dirBaseUrl = endsWithSlash(config.dirBaseUrl); - } - - //Check for errors in config - if (config.main) { - throw new Error('"main" passed as an option, but the ' + - 'supported option is called "name".'); - } - if (!config.name && !config.modules && !config.include && !config.cssIn) { - throw new Error('Missing either a "name", "include" or "modules" ' + - 'option'); - } - if (config.cssIn && !config.out) { - throw new Error("ERROR: 'out' option missing."); - } - if (!config.cssIn && !config.baseUrl) { - //Just use the current directory as the baseUrl - config.baseUrl = './'; - } - if (!config.out && !config.dir) { - throw new Error('Missing either an "out" or "dir" config value. ' + - 'If using "appDir" for a full project optimization, ' + - 'use "dir". If you want to optimize to one file, ' + - 'use "out".'); - } - if (config.appDir && config.out) { - throw new Error('"appDir" is not compatible with "out". Use "dir" ' + - 'instead. appDir is used to copy whole projects, ' + - 'where "out" is used to just optimize to one file.'); - } - if (config.out && config.dir) { - throw new Error('The "out" and "dir" options are incompatible.' + - ' Use "out" if you are targeting a single file for' + - ' for optimization, and "dir" if you want the appDir' + - ' or baseUrl directories optimized.'); - } - - if (config.insertRequire && !lang.isArray(config.insertRequire)) { - throw new Error('insertRequire should be a list of module IDs' + - ' to insert in to a require([]) call.'); - } - - if ((config.name || config.include) && !config.modules) { - //Just need to build one file, but may be part of a whole appDir/ - //baseUrl copy, but specified on the command line, so cannot do - //the modules array setup. So create a modules section in that - //case. - config.modules = [ - { - name: config.name, - out: config.out, - include: config.include, - exclude: config.exclude, - excludeShallow: config.excludeShallow, - insertRequire: config.insertRequire - } - ]; - } else if (config.modules && config.out) { - throw new Error('If the "modules" option is used, then there ' + - 'should be a "dir" option set and "out" should ' + - 'not be used since "out" is only for single file ' + - 'optimization output.'); - } else if (config.modules && config.name) { - throw new Error('"name" and "modules" options are incompatible. ' + - 'Either use "name" if doing a single file ' + - 'optimization, or "modules" if you want to target ' + - 'more than one file for optimization.'); - } - - if (config.out && !config.cssIn) { - //Just one file to optimize. - - //Does not have a build file, so set up some defaults. - //Optimizing CSS should not be allowed, unless explicitly - //asked for on command line. In that case the only task is - //to optimize a CSS file. - if (!cfg.optimizeCss) { - config.optimizeCss = "none"; - } - } - - //Create a hash lookup for the stubModules config to make lookup - //cheaper later. - if (config.stubModules) { - config.stubModules._byName = {}; - config.stubModules.forEach(function (id) { - config.stubModules._byName[id] = true; - }); - } - - //Get any wrap text. - try { - if (config.wrap) { - if (config.wrap === true) { - //Use default values. - config.wrap = { - start: '(function () {', - end: '}());' - }; - } else { - config.wrap.start = config.wrap.start || - file.readFile(build.makeAbsPath(config.wrap.startFile, absFilePath)); - config.wrap.end = config.wrap.end || - file.readFile(build.makeAbsPath(config.wrap.endFile, absFilePath)); - } - } - } catch (wrapError) { - throw new Error('Malformed wrap config: need both start/end or ' + - 'startFile/endFile: ' + wrapError.toString()); - } - - //Do final input verification - if (config.context) { - throw new Error('The build argument "context" is not supported' + - ' in a build. It should only be used in web' + - ' pages.'); - } - - //Set file.fileExclusionRegExp if desired - if (config.hasOwnProperty('fileExclusionRegExp')) { - if (typeof config.fileExclusionRegExp === "string") { - file.exclusionRegExp = new RegExp(config.fileExclusionRegExp); - } else { - file.exclusionRegExp = config.fileExclusionRegExp; - } - } else if (config.hasOwnProperty('dirExclusionRegExp')) { - //Set file.dirExclusionRegExp if desired, this is the old - //name for fileExclusionRegExp before 1.0.2. Support for backwards - //compatibility - file.exclusionRegExp = config.dirExclusionRegExp; - } - - //Remove things that may cause problems in the build. - delete config.jQuery; - - return config; - }; - - /** - * finds the module being built/optimized with the given moduleName, - * or returns null. - * @param {String} moduleName - * @param {Array} modules - * @returns {Object} the module object from the build profile, or null. - */ - build.findBuildModule = function (moduleName, modules) { - var i, module; - for (i = 0; i < modules.length; i++) { - module = modules[i]; - if (module.name === moduleName) { - return module; - } - } - return null; - }; - - /** - * Removes a module name and path from a layer, if it is supposed to be - * excluded from the layer. - * @param {String} moduleName the name of the module - * @param {String} path the file path for the module - * @param {Object} layer the layer to remove the module/path from - */ - build.removeModulePath = function (module, path, layer) { - var index = layer.buildFilePaths.indexOf(path); - if (index !== -1) { - layer.buildFilePaths.splice(index, 1); - } - }; - - /** - * Uses the module build config object to trace the dependencies for the - * given module. - * - * @param {Object} module the module object from the build config info. - * @param {Object} the build config object. - * - * @returns {Object} layer information about what paths and modules should - * be in the flattened module. - */ - build.traceDependencies = function (module, config) { - var include, override, layer, context, baseConfig, oldContext, - registry, id, idParts, pluginId, - errMessage = '', - failedPluginMap = {}, - failedPluginIds = [], - errIds = [], - errUrlMap = {}, - errUrlConflicts = {}, - hasErrUrl = false, - errUrl, prop; - - //Reset some state set up in requirePatch.js, and clean up require's - //current context. - oldContext = require._buildReset(); - - //Grab the reset layer and context after the reset, but keep the - //old config to reuse in the new context. - baseConfig = oldContext.config; - layer = require._layer; - context = layer.context; - - //Put back basic config, use a fresh object for it. - //WARNING: probably not robust for paths and packages/packagePaths, - //since those property's objects can be modified. But for basic - //config clone it works out. - require(lang.mixin({}, baseConfig, true)); - - logger.trace("\nTracing dependencies for: " + (module.name || module.out)); - include = module.name && !module.create ? [module.name] : []; - if (module.include) { - include = include.concat(module.include); - } - - //If there are overrides to basic config, set that up now.; - if (module.override) { - override = lang.mixin({}, baseConfig, true); - lang.mixin(override, module.override, true); - require(override); - } - - //Figure out module layer dependencies by calling require to do the work. - require(include); - - //Reset config - if (module.override) { - require(baseConfig); - } - - //Check to see if it all loaded. If not, then stop, and give - //a message on what is left. - registry = context.registry; - for (id in registry) { - if (registry.hasOwnProperty(id) && id.indexOf('_@r') !== 0) { - if (id.indexOf('_unnormalized') === -1 && registry[id].enabled) { - errIds.push(id); - errUrl = registry[id].map.url; - - if (errUrlMap[errUrl]) { - hasErrUrl = true; - //This error module has the same URL as another - //error module, could be misconfiguration. - if (!errUrlConflicts[errUrl]) { - errUrlConflicts[errUrl] = []; - //Store the original module that had the same URL. - errUrlConflicts[errUrl].push(errUrlMap[errUrl]); - } - errUrlConflicts[errUrl].push(id); - } else { - errUrlMap[errUrl] = id; - } - } - - //Look for plugins that did not call load() - idParts = id.split('!'); - pluginId = idParts[0]; - if (idParts.length > 1 && !failedPluginMap.hasOwnProperty(pluginId)) { - failedPluginIds.push(pluginId); - failedPluginMap[pluginId] = true; - } - } - } - - if (errIds.length || failedPluginIds.length) { - if (failedPluginIds.length) { - errMessage += 'Loader plugin' + - (failedPluginIds.length === 1 ? '' : 's') + - ' did not call ' + - 'the load callback in the build: ' + - failedPluginIds.join(', ') + '\n'; - } - errMessage += 'Module loading did not complete for: ' + errIds.join(', '); - - if (hasErrUrl) { - errMessage += '\nThe following modules share the same URL. This ' + - 'could be a misconfiguration if that URL only has ' + - 'one anonymous module in it:'; - for (prop in errUrlConflicts) { - if (errUrlConflicts.hasOwnProperty(prop)) { - errMessage += '\n' + prop + ': ' + - errUrlConflicts[prop].join(', '); - } - } - } - throw new Error(errMessage); - } - - return layer; - }; - - /** - * Uses the module build config object to create an flattened version - * of the module, with deep dependencies included. - * - * @param {Object} module the module object from the build config info. - * - * @param {Object} layer the layer object returned from build.traceDependencies. - * - * @param {Object} the build config object. - * - * @returns {Object} with two properties: "text", the text of the flattened - * module, and "buildText", a string of text representing which files were - * included in the flattened module text. - */ - build.flattenModule = function (module, layer, config) { - var buildFileContents = "", - namespace = config.namespace || '', - namespaceWithDot = namespace ? namespace + '.' : '', - stubModulesByName = (config.stubModules && config.stubModules._byName) || {}, - context = layer.context, - path, reqIndex, fileContents, currContents, - i, moduleName, shim, packageConfig, - parts, builder, writeApi; - - //Use override settings, particularly for pragmas - if (module.override) { - config = lang.mixin({}, config, true); - lang.mixin(config, module.override, true); - } - - //Start build output for the module. - buildFileContents += "\n" + - (config.dir ? module._buildPath.replace(config.dir, "") : module._buildPath) + - "\n----------------\n"; - - //If there was an existing file with require in it, hoist to the top. - if (layer.existingRequireUrl) { - reqIndex = layer.buildFilePaths.indexOf(layer.existingRequireUrl); - if (reqIndex !== -1) { - layer.buildFilePaths.splice(reqIndex, 1); - layer.buildFilePaths.unshift(layer.existingRequireUrl); - } - } - - //Write the built module to disk, and build up the build output. - fileContents = ""; - for (i = 0; i < layer.buildFilePaths.length; i++) { - path = layer.buildFilePaths[i]; - moduleName = layer.buildFileToModule[path]; - - //If the moduleName is for a package main, then update it to the - //real main value. - packageConfig = layer.context.config.pkgs && - layer.context.config.pkgs[moduleName]; - if (packageConfig) { - moduleName += '/' + packageConfig.main; - } - - //Figure out if the module is a result of a build plugin, and if so, - //then delegate to that plugin. - parts = context.makeModuleMap(moduleName); - builder = parts.prefix && context.defined[parts.prefix]; - if (builder) { - if (builder.write) { - writeApi = function (input) { - fileContents += "\n" + addSemiColon(input); - if (config.onBuildWrite) { - fileContents = config.onBuildWrite(moduleName, path, fileContents); - } - }; - writeApi.asModule = function (moduleName, input) { - fileContents += "\n" + - addSemiColon( - build.toTransport(namespace, moduleName, path, input, layer, { - useSourceUrl: layer.context.config.useSourceUrl - })); - if (config.onBuildWrite) { - fileContents = config.onBuildWrite(moduleName, path, fileContents); - } - }; - builder.write(parts.prefix, parts.name, writeApi); - } - } else { - if (stubModulesByName.hasOwnProperty(moduleName)) { - //Just want to insert a simple module definition instead - //of the source module. Useful for plugins that inline - //all their resources. - if (layer.context.plugins.hasOwnProperty(moduleName)) { - //Slightly different content for plugins, to indicate - //that dynamic loading will not work. - currContents = 'define({load: function(id){throw new Error("Dynamic load not allowed: " + id);}});'; - } else { - currContents = 'define({});'; - } - } else { - currContents = file.readFile(path); - } - - if (config.cjsTranslate) { - currContents = commonJs.convert(path, currContents); - } - - if (config.onBuildRead) { - currContents = config.onBuildRead(moduleName, path, currContents); - } - - if (namespace) { - currContents = pragma.namespace(currContents, namespace); - } - - currContents = build.toTransport(namespace, moduleName, path, currContents, layer, { - useSourceUrl: config.useSourceUrl - }); - - if (packageConfig) { - currContents = addSemiColon(currContents) + '\n'; - currContents += namespaceWithDot + "define('" + - packageConfig.name + "', ['" + moduleName + - "'], function (main) { return main; });\n"; - } - - if (config.onBuildWrite) { - currContents = config.onBuildWrite(moduleName, path, currContents); - } - - //Semicolon is for files that are not well formed when - //concatenated with other content. - fileContents += "\n" + addSemiColon(currContents); - } - - buildFileContents += path.replace(config.dir, "") + "\n"; - //Some files may not have declared a require module, and if so, - //put in a placeholder call so the require does not try to load them - //after the module is processed. - //If we have a name, but no defined module, then add in the placeholder. - if (moduleName && !layer.modulesWithNames[moduleName] && !config.skipModuleInsertion) { - shim = config.shim && config.shim[moduleName]; - if (shim) { - fileContents += '\n' + namespaceWithDot + 'define("' + moduleName + '", ' + - (shim.deps && shim.deps.length ? - build.makeJsArrayString(shim.deps) + ', ' : '') + - (shim.exports ? shim.exports() : 'function(){}') + - ');\n'; - } else { - fileContents += '\n' + namespaceWithDot + 'define("' + moduleName + '", function(){});\n'; - } - } - } - - //Add a require at the end to kick start module execution, if that - //was desired. Usually this is only specified when using small shim - //loaders like almond. - if (module.insertRequire) { - fileContents += '\n' + namespaceWithDot + 'require(["' + module.insertRequire.join('", "') + '"]);\n'; - } - - return { - text: config.wrap ? - config.wrap.start + fileContents + config.wrap.end : - fileContents, - buildText: buildFileContents - }; - }; - - //Converts an JS array of strings to a string representation. - //Not using JSON.stringify() for Rhino's sake. - build.makeJsArrayString = function (ary) { - return '["' + ary.map(function (item) { - //Escape any double quotes, backslashes - return lang.jsEscape(item); - }).join('","') + '"]'; - }; - - build.toTransport = function (namespace, moduleName, path, contents, layer, options) { - var baseUrl = layer && layer.context.config.baseUrl; - - function onFound(info) { - //Only mark this module as having a name if not a named module, - //or if a named module and the name matches expectations. - if (layer && (info.needsId || info.foundId === moduleName)) { - layer.modulesWithNames[moduleName] = true; - } - } - - //Convert path to be a local one to the baseUrl, useful for - //useSourceUrl. - if (baseUrl) { - path = path.replace(baseUrl, ''); - } - - return transform.toTransport(namespace, moduleName, path, contents, onFound, options); - }; - - return build; -}); - - } - - - /** - * Sets the default baseUrl for requirejs to be directory of top level - * script. - */ - function setBaseUrl(fileName) { - //Use the file name's directory as the baseUrl if available. - dir = fileName.replace(/\\/g, '/'); - if (dir.indexOf('/') !== -1) { - dir = dir.split('/'); - dir.pop(); - dir = dir.join('/'); - exec("require({baseUrl: '" + dir + "'});"); - } - } - - //If in Node, and included via a require('requirejs'), just export and - //THROW IT ON THE GROUND! - if (env === 'node' && reqMain !== module) { - setBaseUrl(path.resolve(reqMain ? reqMain.filename : '.')); - - //Create a method that will run the optimzer given an object - //config. - requirejs.optimize = function (config, callback) { - if (!loadedOptimizedLib) { - loadLib(); - loadedOptimizedLib = true; - } - - //Create the function that will be called once build modules - //have been loaded. - var runBuild = function (build, logger) { - //Make sure config has a log level, and if not, - //make it "silent" by default. - config.logLevel = config.hasOwnProperty('logLevel') ? - config.logLevel : logger.SILENT; - - var result = build(config); - - //Reset build internals on each run. - requirejs._buildReset(); - - if (callback) { - callback(result); - } - }; - - requirejs({ - context: 'build' - }, ['build', 'logger'], runBuild); - }; - - requirejs.tools = { - useLib: function (contextName, callback) { - if (!callback) { - callback = contextName; - contextName = 'uselib'; - } - - if (!useLibLoaded[contextName]) { - loadLib(); - useLibLoaded[contextName] = true; - } - - var req = requirejs({ - context: contextName - }); - - req(['build'], function () { - callback(req); - }); - } - }; - - requirejs.define = define; - - module.exports = requirejs; - return; - } - - if (commandOption === 'o') { - //Do the optimizer work. - loadLib(); - - /** - * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ - -/* - * Create a build.js file that has the build options you want and pass that - * build file to this file to do the build. See example.build.js for more information. - */ - -/*jslint strict: false, nomen: false */ -/*global require: false */ - -require({ - baseUrl: require.s.contexts._.config.baseUrl, - //Use a separate context than the default context so that the - //build can use the default context. - context: 'build', - catchError: { - define: true - } -}, ['env!env/args', 'build'], -function (args, build) { - build(args); -}); - - - } else if (commandOption === 'v') { - console.log('r.js: ' + version + ', RequireJS: ' + this.requirejsVars.require.version); - } else if (commandOption === 'convert') { - loadLib(); - - this.requirejsVars.require(['env!env/args', 'commonJs', 'env!env/print'], - function (args, commonJs, print) { - - var srcDir, outDir; - srcDir = args[0]; - outDir = args[1]; - - if (!srcDir || !outDir) { - print('Usage: path/to/commonjs/modules output/dir'); - return; - } - - commonJs.convertDir(args[0], args[1]); - }); - } else { - //Just run an app - - //Load the bundled libraries for use in the app. - if (commandOption === 'lib') { - loadLib(); - } - - setBaseUrl(fileName); - - if (exists(fileName)) { - exec(readFile(fileName), fileName); - } else { - showHelp(); - } - } - -}((typeof console !== 'undefined' ? console : undefined), - (typeof Packages !== 'undefined' ? Array.prototype.slice.call(arguments, 0) : []), - (typeof readFile !== 'undefined' ? readFile : undefined))); \ No newline at end of file diff --git a/build/server b/build/server deleted file mode 100644 index c239640..0000000 --- a/build/server +++ /dev/null @@ -1,15 +0,0 @@ -var fs = require("fs"); -var express = require("express"); -var site = express.createServer(); - -site.use(express.static(__dirname + '/..')); - -site.use(express.favicon("./favicon.ico")); - -site.get("*", function(req, res) { - fs.createReadStream("./index.html").pipe(res); -}); - -site.listen(1337); - -console.log("Server listening on http://localhost:1337"); From 91feecbff471e224621e4c3dfaef47d65cbf3cf2 Mon Sep 17 00:00:00 2001 From: Nietzsche Date: Sat, 28 Jul 2012 12:26:58 +1000 Subject: [PATCH 007/531] travis error and updated title --- index.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.html b/index.html index 1187370..ee23d82 100644 --- a/index.html +++ b/index.html @@ -1,8 +1,7 @@ - - ApiDocco + ApiEngine From 7277c6f751d74079496730b02995919d973e4e8e Mon Sep 17 00:00:00 2001 From: Nietzsche Date: Sat, 28 Jul 2012 12:28:24 +1000 Subject: [PATCH 008/531] fixed doctype --- index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/index.html b/index.html index ee23d82..6a98dee 100644 --- a/index.html +++ b/index.html @@ -1,3 +1,4 @@ + From 584c94341edb3ab068b47d66c14a8ae84b942211 Mon Sep 17 00:00:00 2001 From: Nietzsche Date: Sun, 29 Jul 2012 15:00:53 +1000 Subject: [PATCH 009/531] I suck at commit messages --- js/collections/resources.js | 3 ++ js/views/apis/details.js | 3 +- js/views/app.js | 4 +- js/views/methods/list.js | 26 ++++++--- js/views/resource/list.js | 1 + templates/apis/details.html | 96 ---------------------------------- templates/methods/details.html | 5 +- templates/methods/edit.html | 71 ++++++++++++++----------- templates/methods/list.html | 7 ++- templates/resource/list.html | 17 ++++-- 10 files changed, 91 insertions(+), 142 deletions(-) diff --git a/js/collections/resources.js b/js/collections/resources.js index f4d88fc..fd9b4a2 100644 --- a/js/collections/resources.js +++ b/js/collections/resources.js @@ -10,6 +10,9 @@ define([ }, initialize: function () { console.log(this); + }, + comparator: function (resource) { + return resource.get('tag'); } }); diff --git a/js/views/apis/details.js b/js/views/apis/details.js index e512f53..199cdf5 100644 --- a/js/views/apis/details.js +++ b/js/views/apis/details.js @@ -27,7 +27,6 @@ define([ events: { 'click .js-new-resource': 'newResource', 'click .js-new-method': 'newMethod', - 'submit .js-new-resource-form': 'saveResource', 'submit .js-new-method-form': 'saveMethod' }, newResource: function () { @@ -41,7 +40,7 @@ define([ saveMethod: function (ev) { var that = this; var methodData = $(ev.currentTarget).serializeObject(); - console.log(methodData); + console.log('hoot', methodData); var methodModel = new MethodModel({ username: this.options.username, version: this.options.version, diff --git a/js/views/app.js b/js/views/app.js index 73ce8ea..03f0aef 100644 --- a/js/views/app.js +++ b/js/views/app.js @@ -34,8 +34,8 @@ define([ $.ajaxPrefilter( function( options, originalOptions, jqXHR ) { // Your server goes below //options.url = 'http://localhost:8000' + options.url; - //options.url = 'http://50.116.42.155:8000' + options.url; - options.url = 'http://apidocco.com:3000' + options.url; + options.url = 'http://192.168.111.193:4000' + options.url; + //options.url = 'http://apidocco.com:3000' + options.url; }); diff --git a/js/views/methods/list.js b/js/views/methods/list.js index 1880be6..9e27f2e 100644 --- a/js/views/methods/list.js +++ b/js/views/methods/list.js @@ -3,22 +3,36 @@ define([ 'underscore', 'backbone', 'bootstrap', + 'vm', 'models/session', 'text!templates/methods/list.html', + 'views/forms/resource', 'collections/methods', 'models/method' - ], function($, _, Backbone, bootstrap, Session, resourceListTemplate, ResourcesCollection, MethodModel){ + ], function($, _, Backbone, bootstrap, Vm, Session, resourceListTemplate, ResourceForm, ResourcesCollection, MethodModel){ var ApisPage = Backbone.View.extend({ el: '.method-list-container', initialize: function () { var that = this; }, + events: { + 'click .js-edit-resource': 'editResource' + }, + editResource: function () { + var resourceForm = Vm.create(this, 'resourceform', ResourceForm, { + username: this.options.username, + version: this.options.version, + api: this.options.api, + resource: this.resource + }); + resourceForm.render(); + + return false; + }, render: function () { - console.log('render methods'); var that = this; - var resources = new ResourcesCollection(); - var resource = new MethodModel(); + this.resource = new MethodModel(); /* resources.username = that.options.username; resources.api = that.options.api; @@ -34,7 +48,7 @@ define([ */ that.$el.attr('data-resource-id', that.options.resourceId); - resource.set({ + this.resource.set({ username: that.options.username, api: that.options.api, version: that.options.version, @@ -42,7 +56,7 @@ define([ }); if($('.method-list-container').length !== 0) { - resource.fetch({ + this.resource.fetch({ success: function (model) { console.log(model); that.$el.html(_.template(resourceListTemplate, {_:_, is_public: that.options.is_public, resource: model, username: Session.get('login'), selectedMethod: that.options.method, location: that.options.location})); diff --git a/js/views/resource/list.js b/js/views/resource/list.js index c53617f..d96b74f 100644 --- a/js/views/resource/list.js +++ b/js/views/resource/list.js @@ -23,6 +23,7 @@ define([ that.$el.attr('data-api-id', that.options.api); resources.fetch({ success: function (collection) { + console.log('hey', collection); console.log(that.options.resourceId); that.$el.html(_.template(resourceListTemplate, {_:_, selectedResource: that.options.resourceId, is_public: that.options.is_public, resources: collection, username: Session.get('login'), location: that.options.location})); $('.js-api-filter').button(); diff --git a/templates/apis/details.html b/templates/apis/details.html index e5700f9..31c4a74 100644 --- a/templates/apis/details.html +++ b/templates/apis/details.html @@ -136,101 +136,5 @@

Warning!

- - - - - \ No newline at end of file From 02a61d1a7b8f4411fd3e112947dcc958067f6963 Mon Sep 17 00:00:00 2001 From: Nietzsche Date: Sun, 29 Jul 2012 21:31:42 +1000 Subject: [PATCH 012/531] Asda --- js/models/session.js | 4 ++-- js/views/apis/details.js | 14 +++++++------- js/views/app.js | 15 +++++++++++++-- js/views/resource/list.js | 3 +++ 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/js/models/session.js b/js/models/session.js index 64f7584..2787eaf 100644 --- a/js/models/session.js +++ b/js/models/session.js @@ -12,12 +12,12 @@ define([ // The server must allow this through response headers $.ajaxPrefilter( function( options, originalOptions, jqXHR ) { options.xhrFields = { - withCredentials: true + // withCredentials: true }; // If we have a csrf token send it through with the next request if(typeof that.get('csrf') !== 'undefined') { console.log(that.get('csrf')); - jqXHR.setRequestHeader('X-CSRF-Token', that.get('csrf')); + // jqXHR.setRequestHeader('X-CSRF-Token', that.get('csrf')); } }); }, diff --git a/js/views/apis/details.js b/js/views/apis/details.js index e83aed5..3f14862 100644 --- a/js/views/apis/details.js +++ b/js/views/apis/details.js @@ -86,13 +86,13 @@ define([ var resourceListView = Vm.create(that, 'resourceListView', ResourceListView, {username: that.options.username, api: that.options.apiname, version: that.options.version, resourceId: that.options.resourceId}); resourceListView.render(); }; - if(typeof that.options.resourceId !== 'undefined' && $('.method-list-container').attr('data-resource-id') !== that.options.resourceId) { - that.showMethodList(); - } - if(typeof that.options.method !== 'undefined') { - var methodView = new MethodView({username: that.options.username, api: that.options.apiname, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); - methodView.render(); - } + // if(typeof that.options.resourceId !== 'undefined' && $('.method-list-container').attr('data-resource-id') !== that.options.resourceId) { + // that.showMethodList(); + //} + // if(typeof that.options.method !== 'undefined') { + // var methodView = new MethodView({username: that.options.username, api: that.options.apiname, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); + // methodView.render(); + // } }, render: function () { var that = this; diff --git a/js/views/app.js b/js/views/app.js index 03f0aef..db6dfa1 100644 --- a/js/views/app.js +++ b/js/views/app.js @@ -30,11 +30,22 @@ define([ return o; }; - + + $.ajaxPrefilter( function( options, originalOptions, jqXHR ) { // Your server goes below //options.url = 'http://localhost:8000' + options.url; - options.url = 'http://192.168.111.193:4000' + options.url; + // console.log('network request', Session.get('auth'), options); + if(Session.get('auth') || options.url.indexOf('session') !== -1) { + // options.url = 'http://apidocco.com:3000' + options.url; + options.url = 'http://192.168.111.193:4000' + options.url; + } else { + options.url = 'http://d2i1j8bdf3iqn6.cloudfront.net' + options.url; + //options.url = 'http://apidocco.com:3000' + options.url; + + + }; + //options.url = 'http://192.168.111.193:4000' + options.url; //options.url = 'http://apidocco.com:3000' + options.url; }); diff --git a/js/views/resource/list.js b/js/views/resource/list.js index d96b74f..b22a286 100644 --- a/js/views/resource/list.js +++ b/js/views/resource/list.js @@ -27,6 +27,9 @@ define([ console.log(that.options.resourceId); that.$el.html(_.template(resourceListTemplate, {_:_, selectedResource: that.options.resourceId, is_public: that.options.is_public, resources: collection, username: Session.get('login'), location: that.options.location})); $('.js-api-filter').button(); + //if(typeof that.options.resourceId !== 'undefined' && $('.method-list-container').attr('data-resource-id') !== that.options.resourceId) { + // that.showMethodList(); + //} } }); From b61f0df6dc4ff619a6721ec756e3658abc208589 Mon Sep 17 00:00:00 2001 From: Nietzsche Date: Mon, 30 Jul 2012 23:35:23 +1000 Subject: [PATCH 013/531] getting rid of cache stuff for now: --- js/views/app.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/js/views/app.js b/js/views/app.js index db6dfa1..3e6b2f0 100644 --- a/js/views/app.js +++ b/js/views/app.js @@ -36,15 +36,15 @@ define([ // Your server goes below //options.url = 'http://localhost:8000' + options.url; // console.log('network request', Session.get('auth'), options); - if(Session.get('auth') || options.url.indexOf('session') !== -1) { - // options.url = 'http://apidocco.com:3000' + options.url; - options.url = 'http://192.168.111.193:4000' + options.url; - } else { - options.url = 'http://d2i1j8bdf3iqn6.cloudfront.net' + options.url; + // if(Session.get('auth') || options.url.indexOf('session') !== -1) { + options.url = 'http://apidocco.com:3000' + options.url; + // options.url = 'http://192.168.111.193:4000' + options.url; + // } else { + // options.url = 'http://d2i1j8bdf3iqn6.cloudfront.net' + options.url; //options.url = 'http://apidocco.com:3000' + options.url; - }; + // }; //options.url = 'http://192.168.111.193:4000' + options.url; //options.url = 'http://apidocco.com:3000' + options.url; From bb22cf26f7374bc3939c8bb594c8c3b6640e7b15 Mon Sep 17 00:00:00 2001 From: Nietzsche Date: Mon, 30 Jul 2012 23:36:41 +1000 Subject: [PATCH 014/531] erm --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2355959..386c29b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ + [![Build Status](https://secure.travis-ci.org/ApiEngine/apiengine-client.png?branch=master)](http://travis-ci.org/ApiEngine/apiengine-client) From 976bb9e36a18b17c48a80217807e28f44d98da5e Mon Sep 17 00:00:00 2001 From: Nietzsche Date: Wed, 1 Aug 2012 20:47:29 +1000 Subject: [PATCH 015/531] hrmm --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 386c29b..673d936 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ + [![Build Status](https://secure.travis-ci.org/ApiEngine/apiengine-client.png?branch=master)](http://travis-ci.org/ApiEngine/apiengine-client) From a94c4afe50fb46a0018cbe8c6fd85911b67a64b3 Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Tue, 7 Aug 2012 10:22:24 +1000 Subject: [PATCH 016/531] Update js/models/session.js --- js/models/session.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/models/session.js b/js/models/session.js index 2787eaf..64f7584 100644 --- a/js/models/session.js +++ b/js/models/session.js @@ -12,12 +12,12 @@ define([ // The server must allow this through response headers $.ajaxPrefilter( function( options, originalOptions, jqXHR ) { options.xhrFields = { - // withCredentials: true + withCredentials: true }; // If we have a csrf token send it through with the next request if(typeof that.get('csrf') !== 'undefined') { console.log(that.get('csrf')); - // jqXHR.setRequestHeader('X-CSRF-Token', that.get('csrf')); + jqXHR.setRequestHeader('X-CSRF-Token', that.get('csrf')); } }); }, From fe3803a60f0434f40ae726d9183f6d1dfbf178f3 Mon Sep 17 00:00:00 2001 From: Nietzsche Date: Wed, 8 Aug 2012 18:25:03 +1000 Subject: [PATCH 017/531] some changes hopefully not broken build --- img/logo.jpg | Bin 14203 -> 7270 bytes js/views/apis/details.js | 4 +--- js/views/methods/list.js | 5 ++++- js/views/resource/list.js | 5 ++++- templates/home/page.html | 3 +-- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/img/logo.jpg b/img/logo.jpg index 236812f6edf6bbfce25861d001832ad4dcd3dfb4..361757e40144cafca27a64255ce284baa83ecbd0 100644 GIT binary patch literal 7270 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 CzNYv9 literal 14203 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 diff --git a/js/views/apis/details.js b/js/views/apis/details.js index 3f14862..af041ab 100644 --- a/js/views/apis/details.js +++ b/js/views/apis/details.js @@ -9,16 +9,14 @@ define([ 'text!templates/apis/details.html', 'models/api', 'collections/methods', - 'views/methods/list', 'views/resource/list', 'views/methods/details', 'models/api', 'models/resource', 'models/method', 'libs/highlight/highlight', - 'views/methods/details', 'views/forms/resource' -], function($, _, Backbone, Bootstrap, Router, Vm, Session, apiDetailsTemplate, ApiModel, MethodsCollection, MethodsListView, ResourceListView, MethodDetailView, ApiModel, ResourceModel, MethodModel, hljs, MethodView, ResourceForm){ +], function($, _, Backbone, Bootstrap, Router, Vm, Session, apiDetailsTemplate, ApiModel, MethodsCollection, ResourceListView, MethodDetailView, ApiModel, ResourceModel, MethodModel, hljs, ResourceForm){ var NewApiPage = Backbone.View.extend({ el: '.page', initialize: function () { diff --git a/js/views/methods/list.js b/js/views/methods/list.js index 85deca1..c20d10b 100644 --- a/js/views/methods/list.js +++ b/js/views/methods/list.js @@ -8,9 +8,10 @@ define([ 'text!templates/methods/list.html', 'views/forms/resource', 'views/forms/method', + 'views/methods/details', 'collections/methods', 'models/method' - ], function($, _, Backbone, bootstrap, Vm, Session, resourceListTemplate, ResourceForm, MethodForm, ResourcesCollection, MethodModel){ + ], function($, _, Backbone, bootstrap, Vm, Session, resourceListTemplate, ResourceForm, MethodForm, MethodView, ResourcesCollection, MethodModel){ var ApisPage = Backbone.View.extend({ el: '.method-list-container', initialize: function () { @@ -73,6 +74,8 @@ define([ console.log(model); that.$el.html(_.template(resourceListTemplate, {_:_, is_public: that.options.is_public, resource: model, username: Session.get('login'), selectedMethod: that.options.method, location: that.options.location})); $('.js-api-filter').button(); + var methodView = new MethodView({username: that.options.username, api: that.options.api, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); + methodView.render(); } }); }; diff --git a/js/views/resource/list.js b/js/views/resource/list.js index b22a286..487439d 100644 --- a/js/views/resource/list.js +++ b/js/views/resource/list.js @@ -6,8 +6,9 @@ define([ 'models/session', 'text!templates/resource/list.html', 'collections/resources', + 'views/methods/list', 'models/resource' -], function($, _, Backbone, bootstrap, Session, resourceListTemplate, ResourcesCollection, ResourceModel){ +], function($, _, Backbone, bootstrap, Session, resourceListTemplate, ResourcesCollection, MethodsListView, ResourceModel){ var ApisPage = Backbone.View.extend({ el: '.resource-list-container', initialize: function () { @@ -30,6 +31,8 @@ define([ //if(typeof that.options.resourceId !== 'undefined' && $('.method-list-container').attr('data-resource-id') !== that.options.resourceId) { // that.showMethodList(); //} + var methodListView = new MethodsListView({username: that.options.username, api: that.options.api, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); + methodListView.render(); } }); diff --git a/templates/home/page.html b/templates/home/page.html index a2942f9..508bdae 100644 --- a/templates/home/page.html +++ b/templates/home/page.html @@ -5,8 +5,7 @@
-

ApiDocco is a web app built as a tool to significantly aid your applications RESTful API development.

-

The goal is to build a platform that allows developers to take their API to the next level with the following planned features

+

Plan, build and publish your API documentation the way you want to on a secure and collaborative platform. Keep your API's private or publish them for all of the world to see. ApiEngine gives you the keys to launch your ideas and turbo-charge your projects.

<% if(!username) { %>

Free!

From a633fc641e332e39b05bbc7f0268ddc9ffeb856d Mon Sep 17 00:00:00 2001 From: Nietzsche Date: Wed, 8 Aug 2012 21:49:58 +1000 Subject: [PATCH 018/531] Fixed up some loading order shit --- js/views/apis/details.js | 6 ++++-- js/views/app.js | 2 +- js/views/methods/details.js | 3 +++ js/views/methods/list.js | 20 ++++++++++++++++++-- js/views/resource/list.js | 14 ++++++++++++-- templates/methods/list.html | 2 +- templates/resource/list.html | 2 +- 7 files changed, 40 insertions(+), 9 deletions(-) diff --git a/js/views/apis/details.js b/js/views/apis/details.js index af041ab..40128dd 100644 --- a/js/views/apis/details.js +++ b/js/views/apis/details.js @@ -80,9 +80,11 @@ define([ }, showDetails: function () { var that = this; + console.log('show details'); if($('.resource-list-container').attr('data-api-id') !== that.options.apiname) { - var resourceListView = Vm.create(that, 'resourceListView', ResourceListView, {username: that.options.username, api: that.options.apiname, version: that.options.version, resourceId: that.options.resourceId}); + var resourceListView = Vm.create(that, 'resourceListView', ResourceListView, {username: that.options.username, api: that.options.apiname, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); resourceListView.render(); + console.log('show list container'); }; // if(typeof that.options.resourceId !== 'undefined' && $('.method-list-container').attr('data-resource-id') !== that.options.resourceId) { // that.showMethodList(); @@ -94,7 +96,7 @@ define([ }, render: function () { var that = this; - + console.log('re-render'); if($('.api-container').length === 0) { this.$el.html('Loading API'); diff --git a/js/views/app.js b/js/views/app.js index 3e6b2f0..790bfaa 100644 --- a/js/views/app.js +++ b/js/views/app.js @@ -37,7 +37,7 @@ define([ //options.url = 'http://localhost:8000' + options.url; // console.log('network request', Session.get('auth'), options); // if(Session.get('auth') || options.url.indexOf('session') !== -1) { - options.url = 'http://apidocco.com:3000' + options.url; + options.url = 'http://z.apiengine.io' + options.url; // options.url = 'http://192.168.111.193:4000' + options.url; // } else { // options.url = 'http://d2i1j8bdf3iqn6.cloudfront.net' + options.url; diff --git a/js/views/methods/details.js b/js/views/methods/details.js index 3d64303..f3efd10 100644 --- a/js/views/methods/details.js +++ b/js/views/methods/details.js @@ -31,6 +31,9 @@ define([ }, render: function () { var that = this; + $('[data-method-id].active').removeClass('active'); + $('[data-method-id='+ this.options.method +']').addClass('active'); + this.method = new MethodModel(); this.method.set({ id: this.options.method, diff --git a/js/views/methods/list.js b/js/views/methods/list.js index c20d10b..3e8f3e7 100644 --- a/js/views/methods/list.js +++ b/js/views/methods/list.js @@ -43,7 +43,21 @@ define([ return false; }, + events: { + 'click [data-method-id]': 'showMethodView' + }, + showMethodView: function (ev) { + var that = this; + if(ev) { + console.log('ooo') + that.options.method = $(ev.currentTarget).attr('data-method-id'); + } + var methodView = new MethodView({username: that.options.username, api: that.options.api, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); + methodView.render(); + }, render: function () { + $('[data-resource-id].active').removeClass('active'); + $('[data-resource-id='+ this.options.resourceId +']').addClass('active'); var that = this; this.resource = new MethodModel(); /* @@ -74,8 +88,10 @@ define([ console.log(model); that.$el.html(_.template(resourceListTemplate, {_:_, is_public: that.options.is_public, resource: model, username: Session.get('login'), selectedMethod: that.options.method, location: that.options.location})); $('.js-api-filter').button(); - var methodView = new MethodView({username: that.options.username, api: that.options.api, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); - methodView.render(); + console.log(that.options.method); + if(typeof that.options.method !== 'undefined') { + that.showMethodView(); + } } }); }; diff --git a/js/views/resource/list.js b/js/views/resource/list.js index 487439d..dec5e07 100644 --- a/js/views/resource/list.js +++ b/js/views/resource/list.js @@ -15,6 +15,17 @@ define([ var that = this; }, + events: { + 'click [data-resource-id]': 'showMethodList' + }, + showMethodList: function (ev) { + var that = this; + if(ev) { + this.options.resourceId = $(ev.currentTarget).attr('data-resource-id'); + } + var methodListView = new MethodsListView({username: that.options.username, api: that.options.api, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); + methodListView.render(); + }, render: function () { var that = this; var resources = new ResourcesCollection(); @@ -31,8 +42,7 @@ define([ //if(typeof that.options.resourceId !== 'undefined' && $('.method-list-container').attr('data-resource-id') !== that.options.resourceId) { // that.showMethodList(); //} - var methodListView = new MethodsListView({username: that.options.username, api: that.options.api, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); - methodListView.render(); + that.showMethodList(); } }); diff --git a/templates/methods/list.html b/templates/methods/list.html index 4cc504d..d9bb81b 100644 --- a/templates/methods/list.html +++ b/templates/methods/list.html @@ -13,7 +13,7 @@ Methods <% _.each(resource.get('methods'), function (method) { %> -
  • +
  • diff --git a/templates/resource/list.html b/templates/resource/list.html index cc5bb91..53516bf 100644 --- a/templates/resource/list.html +++ b/templates/resource/list.html @@ -17,7 +17,7 @@ }; lastTag = resource.get('tag'); %> -
  • +
  • <%= resource.get('label') %> From 7da3fa0225e4a6c182491cebdd83d3cbd3463692 Mon Sep 17 00:00:00 2001 From: Nietzsche Date: Fri, 10 Aug 2012 16:22:28 +1000 Subject: [PATCH 019/531] oo --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 6a98dee..a382d97 100644 --- a/index.html +++ b/index.html @@ -9,7 +9,7 @@
    - +

    Testing

    From 4ed27121a535d4fd82fe7edfb5845c3828ac0310 Mon Sep 17 00:00:00 2001 From: Nietzsche Date: Fri, 10 Aug 2012 18:42:23 +1000 Subject: [PATCH 020/531] messing --- index.html | 1 - js/router.js | 9 ++++++++- templates/home/login.html | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index a382d97..3e073eb 100644 --- a/index.html +++ b/index.html @@ -9,7 +9,6 @@
    -

    Testing

    diff --git a/js/router.js b/js/router.js index 32f4f09..0cd1e5d 100644 --- a/js/router.js +++ b/js/router.js @@ -15,6 +15,7 @@ define([ 'apis/:id/method/:method_id': 'showApi', 'apis/:id/methods/edit': 'editMethod', 'login': 'login', + 'forgot_password': 'forgot_password', 'register': 'register', '': 'home', ':username/:apiname/version/:version/resource/:resource/:method': 'apiPage', @@ -47,7 +48,13 @@ define([ loginView.render(); }); }); - + + router.on('route:forgot_password', function (apiId) { + require(['views/home/forgot_password'], function (ForgotView) { + var forgotView = Vm.create(appView, 'ForgotView', ForgotView, {}); + forgotView.render(); + }); + }); router.on('route:register', function (apiId) { require(['views/home/register'], function (RegisterView) { var registerView = Vm.create(appView, 'RegisterView', RegisterView, {}); diff --git a/templates/home/login.html b/templates/home/login.html index 555a496..246b043 100644 --- a/templates/home/login.html +++ b/templates/home/login.html @@ -4,7 +4,7 @@

    Login


    - +
    From 661979a0852711f6ec484145e0178ee364f91983 Mon Sep 17 00:00:00 2001 From: Nietzsche Date: Fri, 10 Aug 2012 18:52:34 +1000 Subject: [PATCH 021/531] added new files --- js/views/home/forgot_password.js | 42 +++++++++++++++++++++++++++++ templates/home/forgot_password.html | 11 ++++++++ 2 files changed, 53 insertions(+) create mode 100644 js/views/home/forgot_password.js create mode 100644 templates/home/forgot_password.html diff --git a/js/views/home/forgot_password.js b/js/views/home/forgot_password.js new file mode 100644 index 0000000..e77ffa3 --- /dev/null +++ b/js/views/home/forgot_password.js @@ -0,0 +1,42 @@ +define([ + 'jquery', + 'underscore', + 'backbone', + 'models/session', + 'text!templates/home/forgot_password.html', +], function($, _, Backbone, Session, loginTemplate){ + var ForgotPage = Backbone.View.extend({ + el: '.page', + initialize: function () { + var that = this; + // Bind to the Session auth attribute so we + // make our view act recordingly when auth changes + + }, + render: function () { + this.$el.html(_.template(loginTemplate, {errors: Session.get('errors'), _: _})); + + }, + events: { + + 'submit form.forgot': 'forgotPassword', // On form submission + }, + forgotPassword: function (ev) { + // Disable the button + $('[type=submit]', ev.currentTarget).val('Logging in').attr('disabled', 'disabled'); + // Serialize the form into an object using a jQuery plgin + var ForgotToken = Backbone.Model.extend({ + urlRoot: '/passwordreset' + }); + var forgotToken = new ForgotToken(); + forgotToken.set({email: 'thomasalwyndavis@gmail.com'}); + forgotToken.save({}, { + success: function () { + console.log(arguments); + } + }); + return false; + } + }); + return ForgotPage; +}); diff --git a/templates/home/forgot_password.html b/templates/home/forgot_password.html new file mode 100644 index 0000000..18a5b33 --- /dev/null +++ b/templates/home/forgot_password.html @@ -0,0 +1,11 @@ +
    +

    Forgot Password

    +
    + + + + +
    + + +
    From 50881e640e2f4d05b4356eaf7064300b7c50b37a Mon Sep 17 00:00:00 2001 From: Nietzsche Date: Sun, 12 Aug 2012 23:26:01 +1000 Subject: [PATCH 022/531] forgot password stuff --- js/router.js | 5 +++-- js/views/app.js | 15 +++++++-------- js/views/home/forgot_password.js | 33 +++++++++++++++++++++++++++++--- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/js/router.js b/js/router.js index 0cd1e5d..138f5ae 100644 --- a/js/router.js +++ b/js/router.js @@ -15,6 +15,7 @@ define([ 'apis/:id/method/:method_id': 'showApi', 'apis/:id/methods/edit': 'editMethod', 'login': 'login', + 'forgot_password/*token': 'forgot_password', 'forgot_password': 'forgot_password', 'register': 'register', '': 'home', @@ -49,9 +50,9 @@ define([ }); }); - router.on('route:forgot_password', function (apiId) { + router.on('route:forgot_password', function (token) { require(['views/home/forgot_password'], function (ForgotView) { - var forgotView = Vm.create(appView, 'ForgotView', ForgotView, {}); + var forgotView = Vm.create(appView, 'ForgotView', ForgotView, {token: token}); forgotView.render(); }); }); diff --git a/js/views/app.js b/js/views/app.js index 790bfaa..ed61288 100644 --- a/js/views/app.js +++ b/js/views/app.js @@ -34,31 +34,30 @@ define([ $.ajaxPrefilter( function( options, originalOptions, jqXHR ) { // Your server goes below - //options.url = 'http://localhost:8000' + options.url; - // console.log('network request', Session.get('auth'), options); // if(Session.get('auth') || options.url.indexOf('session') !== -1) { options.url = 'http://z.apiengine.io' + options.url; - // options.url = 'http://192.168.111.193:4000' + options.url; // } else { - // options.url = 'http://d2i1j8bdf3iqn6.cloudfront.net' + options.url; - //options.url = 'http://apidocco.com:3000' + options.url; + // options.url = 'http://d3gscmgl75g1oq.cloudfront.net' + options.url; // }; - //options.url = 'http://192.168.111.193:4000' + options.url; - //options.url = 'http://apidocco.com:3000' + options.url; }); }, render: function () { + var that = this; $(this.el).html(layoutTemplate); var headerView = new HeaderView(); headerView.render(); Session.getAuth(function () { Backbone.history.start(); - }); + }); + +//$.ajax('http://d3gscmgl75g1oq.cloudfront.net/user/thomasdavis/api/ApiEngine/1/resource/8', { + //success: function () {console.log(arguments);} +//}); } }); return AppView; diff --git a/js/views/home/forgot_password.js b/js/views/home/forgot_password.js index e77ffa3..3dc1d39 100644 --- a/js/views/home/forgot_password.js +++ b/js/views/home/forgot_password.js @@ -3,8 +3,9 @@ define([ 'underscore', 'backbone', 'models/session', - 'text!templates/home/forgot_password.html', -], function($, _, Backbone, Session, loginTemplate){ + 'text!templates/home/password_reset.html', + 'text!templates/home/forgot_password.html' +], function($, _, Backbone, Session, passwordResetTemplate, loginTemplate){ var ForgotPage = Backbone.View.extend({ el: '.page', initialize: function () { @@ -13,13 +14,21 @@ define([ // make our view act recordingly when auth changes }, - render: function () { + render: function (options) { + console.log(this.options); + if(typeof this.options.token !== 'undefined') { + this.$el.html(_.template(passwordResetTemplate, {errors: Session.get('errors'), _: _})); + + } else { this.$el.html(_.template(loginTemplate, {errors: Session.get('errors'), _: _})); + } + }, events: { 'submit form.forgot': 'forgotPassword', // On form submission + 'submit form.reset_password': 'resetPassword' // On form submission }, forgotPassword: function (ev) { // Disable the button @@ -35,6 +44,24 @@ define([ console.log(arguments); } }); + return false; + }, + resetPassword: function (ev) { + // Disable the button + $('[type=submit]', ev.currentTarget).val('Logging in').attr('disabled', 'disabled'); + // Serialize the form into an object using a jQuery plgin + var ForgotToken = Backbone.Model.extend({ + urlRoot: '/passwordreset/' + this.options.token + }); + var creds = $(ev.currentTarget).serializeObject(); + + var forgotToken = new ForgotToken(); + forgotToken.save(creds, { + success: function () { + console.log(arguments); + } + }); + return false; } }); From e2b36c7a06419b249c503d911f8a5e27f103e263 Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Sat, 25 Aug 2012 06:23:11 +0000 Subject: [PATCH 023/531] WORK IN PROGRESS --- css/Aller_Std_Rg.ttf | Bin 0 -> 96396 bytes css/bootstrap.css | 2170 ++++++++++++++++++---------- css/styles.css | 5 +- css/theme.css | 60 +- img/api-engine-logo.png | Bin 0 -> 2828 bytes img/titlebar-bg-grad.png | Bin 0 -> 1059 bytes js/router.js | 1 + js/views/app.js | 11 +- js/views/header/account-menu.js | 1 + js/views/home/register.js | 2 +- js/views/profile/page.js | 8 +- templates/404.html | 1 + templates/header/account-menu.html | 4 +- templates/header/main-menu.html | 31 +- templates/home/page.html | 20 +- 15 files changed, 1522 insertions(+), 792 deletions(-) create mode 100644 css/Aller_Std_Rg.ttf create mode 100644 img/api-engine-logo.png create mode 100644 img/titlebar-bg-grad.png create mode 100644 templates/404.html diff --git a/css/Aller_Std_Rg.ttf b/css/Aller_Std_Rg.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8f384ee43d61d8d60f36bd157ae622c98be75a5e GIT binary patch literal 96396 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 literal 0 HcmV?d00001 diff --git a/css/bootstrap.css b/css/bootstrap.css index bf70879..0664207 100644 --- a/css/bootstrap.css +++ b/css/bootstrap.css @@ -1,5 +1,5 @@ /*! - * Bootstrap v2.0.4 + * Bootstrap v2.1.0 * * Copyright 2012 Twitter, Inc * Licensed under the Apache License v2.0 @@ -67,6 +67,7 @@ sub { } img { + height: auto; max-width: 100%; vertical-align: middle; border: 0; @@ -130,6 +131,7 @@ textarea { .clearfix:before, .clearfix:after { display: table; + line-height: 0; content: ""; } @@ -148,18 +150,17 @@ textarea { .input-block-level { display: block; width: 100%; - min-height: 28px; + min-height: 30px; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; - -ms-box-sizing: border-box; box-sizing: border-box; } body { margin: 0; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 13px; - line-height: 18px; + font-size: 14px; + line-height: 20px; color: #333333; background-color: #ffffff; } @@ -174,6 +175,28 @@ a:hover { text-decoration: underline; } +.img-rounded { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.img-polaroid { + padding: 4px; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +.img-circle { + -webkit-border-radius: 500px; + -moz-border-radius: 500px; + border-radius: 500px; +} + .row { margin-left: -20px; *zoom: 1; @@ -182,6 +205,7 @@ a:hover { .row:before, .row:after { display: table; + line-height: 0; content: ""; } @@ -195,8 +219,10 @@ a:hover { } .container, +.navbar-static-top .container, .navbar-fixed-top .container, .navbar-fixed-bottom .container { + width: 940px; } .span12 { @@ -303,6 +329,7 @@ a:hover { .row-fluid:before, .row-fluid:after { display: table; + line-height: 0; content: ""; } @@ -314,12 +341,11 @@ a:hover { display: block; float: left; width: 100%; - min-height: 28px; - margin-left: 2.127659574%; - *margin-left: 2.0744680846382977%; + min-height: 30px; + margin-left: 2.127659574468085%; + *margin-left: 2.074468085106383%; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; - -ms-box-sizing: border-box; box-sizing: border-box; } @@ -328,63 +354,193 @@ a:hover { } .row-fluid .span12 { - width: 99.99999998999999%; - *width: 99.94680850063828%; + width: 100%; + *width: 99.94680851063829%; } .row-fluid .span11 { - width: 91.489361693%; - *width: 91.4361702036383%; + width: 91.48936170212765%; + *width: 91.43617021276594%; } .row-fluid .span10 { - width: 82.97872339599999%; - *width: 82.92553190663828%; + width: 82.97872340425532%; + *width: 82.92553191489361%; } .row-fluid .span9 { - width: 74.468085099%; - *width: 74.4148936096383%; + width: 74.46808510638297%; + *width: 74.41489361702126%; } .row-fluid .span8 { - width: 65.95744680199999%; - *width: 65.90425531263828%; + width: 65.95744680851064%; + *width: 65.90425531914893%; } .row-fluid .span7 { - width: 57.446808505%; - *width: 57.3936170156383%; + width: 57.44680851063829%; + *width: 57.39361702127659%; } .row-fluid .span6 { - width: 48.93617020799999%; - *width: 48.88297871863829%; + width: 48.93617021276595%; + *width: 48.88297872340425%; } .row-fluid .span5 { - width: 40.425531911%; - *width: 40.3723404216383%; + width: 40.42553191489362%; + *width: 40.37234042553192%; } .row-fluid .span4 { - width: 31.914893614%; - *width: 31.8617021246383%; + width: 31.914893617021278%; + *width: 31.861702127659576%; } .row-fluid .span3 { - width: 23.404255317%; - *width: 23.3510638276383%; + width: 23.404255319148934%; + *width: 23.351063829787233%; } .row-fluid .span2 { - width: 14.89361702%; - *width: 14.8404255306383%; + width: 14.893617021276595%; + *width: 14.840425531914894%; } .row-fluid .span1 { - width: 6.382978723%; - *width: 6.329787233638298%; + width: 6.382978723404255%; + *width: 6.329787234042553%; +} + +.row-fluid .offset12 { + margin-left: 104.25531914893617%; + *margin-left: 104.14893617021275%; +} + +.row-fluid .offset12:first-child { + margin-left: 102.12765957446808%; + *margin-left: 102.02127659574467%; +} + +.row-fluid .offset11 { + margin-left: 95.74468085106382%; + *margin-left: 95.6382978723404%; +} + +.row-fluid .offset11:first-child { + margin-left: 93.61702127659574%; + *margin-left: 93.51063829787232%; +} + +.row-fluid .offset10 { + margin-left: 87.23404255319149%; + *margin-left: 87.12765957446807%; +} + +.row-fluid .offset10:first-child { + margin-left: 85.1063829787234%; + *margin-left: 84.99999999999999%; +} + +.row-fluid .offset9 { + margin-left: 78.72340425531914%; + *margin-left: 78.61702127659572%; +} + +.row-fluid .offset9:first-child { + margin-left: 76.59574468085106%; + *margin-left: 76.48936170212764%; +} + +.row-fluid .offset8 { + margin-left: 70.2127659574468%; + *margin-left: 70.10638297872339%; +} + +.row-fluid .offset8:first-child { + margin-left: 68.08510638297872%; + *margin-left: 67.9787234042553%; +} + +.row-fluid .offset7 { + margin-left: 61.70212765957446%; + *margin-left: 61.59574468085106%; +} + +.row-fluid .offset7:first-child { + margin-left: 59.574468085106375%; + *margin-left: 59.46808510638297%; +} + +.row-fluid .offset6 { + margin-left: 53.191489361702125%; + *margin-left: 53.085106382978715%; +} + +.row-fluid .offset6:first-child { + margin-left: 51.063829787234035%; + *margin-left: 50.95744680851063%; +} + +.row-fluid .offset5 { + margin-left: 44.68085106382979%; + *margin-left: 44.57446808510638%; +} + +.row-fluid .offset5:first-child { + margin-left: 42.5531914893617%; + *margin-left: 42.4468085106383%; +} + +.row-fluid .offset4 { + margin-left: 36.170212765957444%; + *margin-left: 36.06382978723405%; +} + +.row-fluid .offset4:first-child { + margin-left: 34.04255319148936%; + *margin-left: 33.93617021276596%; +} + +.row-fluid .offset3 { + margin-left: 27.659574468085104%; + *margin-left: 27.5531914893617%; +} + +.row-fluid .offset3:first-child { + margin-left: 25.53191489361702%; + *margin-left: 25.425531914893618%; +} + +.row-fluid .offset2 { + margin-left: 19.148936170212764%; + *margin-left: 19.04255319148936%; +} + +.row-fluid .offset2:first-child { + margin-left: 17.02127659574468%; + *margin-left: 16.914893617021278%; +} + +.row-fluid .offset1 { + margin-left: 10.638297872340425%; + *margin-left: 10.53191489361702%; +} + +.row-fluid .offset1:first-child { + margin-left: 8.51063829787234%; + *margin-left: 8.404255319148938%; +} + +[class*="span"].hide, +.row-fluid [class*="span"].hide { + display: none; +} + +[class*="span"].pull-right, +.row-fluid [class*="span"].pull-right { + float: right; } .container { @@ -396,6 +552,7 @@ a:hover { .container:before, .container:after { display: table; + line-height: 0; content: ""; } @@ -412,6 +569,7 @@ a:hover { .container-fluid:before, .container-fluid:after { display: table; + line-height: 0; content: ""; } @@ -420,19 +578,34 @@ a:hover { } p { - margin: 0 0 9px; -} - -p small { - font-size: 11px; - color: #999999; + margin: 0 0 10px; } .lead { - margin-bottom: 18px; + margin-bottom: 20px; font-size: 20px; font-weight: 200; - line-height: 27px; + line-height: 30px; +} + +small { + font-size: 85%; +} + +strong { + font-weight: bold; +} + +em { + font-style: italic; +} + +cite { + font-style: normal; +} + +.muted { + color: #999999; } h1, @@ -441,9 +614,10 @@ h3, h4, h5, h6 { - margin: 0; + margin: 10px 0; font-family: inherit; font-weight: bold; + line-height: 1; color: inherit; text-rendering: optimizelegibility; } @@ -455,74 +629,66 @@ h4 small, h5 small, h6 small { font-weight: normal; + line-height: 1; color: #999999; } h1 { - font-size: 30px; - line-height: 36px; -} - -h1 small { - font-size: 18px; + font-size: 36px; + line-height: 40px; } h2 { - font-size: 24px; - line-height: 36px; + font-size: 30px; + line-height: 40px; } -h2 small { - font-size: 18px; +h3 { + font-size: 24px; + line-height: 40px; } -h3 { +h4 { font-size: 18px; - line-height: 27px; + line-height: 20px; } -h3 small { +h5 { font-size: 14px; + line-height: 20px; } -h4, -h5, h6 { - line-height: 18px; + font-size: 12px; + line-height: 20px; } -h4 { - font-size: 14px; +h1 small { + font-size: 24px; } -h4 small { - font-size: 12px; +h2 small { + font-size: 18px; } -h5 { - font-size: 12px; +h3 small { + font-size: 14px; } -h6 { - font-size: 11px; - color: #999999; - text-transform: uppercase; +h4 small { + font-size: 14px; } .page-header { - padding-bottom: 17px; - margin: 18px 0; + padding-bottom: 9px; + margin: 20px 0 30px; border-bottom: 1px solid #eeeeee; } -.page-header h1 { - line-height: 1; -} - ul, ol { padding: 0; - margin: 0 0 9px 25px; + margin: 0 0 10px 25px; } ul ul, @@ -532,16 +698,8 @@ ol ul { margin-bottom: 0; } -ul { - list-style: disc; -} - -ol { - list-style: decimal; -} - li { - line-height: 18px; + line-height: 20px; } ul.unstyled, @@ -551,21 +709,20 @@ ol.unstyled { } dl { - margin-bottom: 18px; + margin-bottom: 20px; } dt, dd { - line-height: 18px; + line-height: 20px; } dt { font-weight: bold; - line-height: 17px; } dd { - margin-left: 9px; + margin-left: 10px; } .dl-horizontal dt { @@ -583,24 +740,12 @@ dd { } hr { - margin: 18px 0; + margin: 20px 0; border: 0; border-top: 1px solid #eeeeee; border-bottom: 1px solid #ffffff; } -strong { - font-weight: bold; -} - -em { - font-style: italic; -} - -.muted { - color: #999999; -} - abbr[title] { cursor: help; border-bottom: 1px dotted #999999; @@ -613,7 +758,7 @@ abbr.initialism { blockquote { padding: 0 0 0 15px; - margin: 0 0 18px; + margin: 0 0 20px; border-left: 5px solid #eeeeee; } @@ -621,12 +766,12 @@ blockquote p { margin-bottom: 0; font-size: 16px; font-weight: 300; - line-height: 22.5px; + line-height: 25px; } blockquote small { display: block; - line-height: 18px; + line-height: 20px; color: #999999; } @@ -647,6 +792,14 @@ blockquote.pull-right small { text-align: right; } +blockquote.pull-right small:before { + content: ''; +} + +blockquote.pull-right small:after { + content: '\00A0 \2014'; +} + q:before, q:after, blockquote:before, @@ -656,23 +809,15 @@ blockquote:after { address { display: block; - margin-bottom: 18px; - font-style: normal; - line-height: 18px; -} - -small { - font-size: 100%; -} - -cite { + margin-bottom: 20px; font-style: normal; + line-height: 20px; } code, pre { padding: 0 3px 2px; - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: #333333; -webkit-border-radius: 3px; @@ -689,10 +834,10 @@ code { pre { display: block; - padding: 8.5px; - margin: 0 0 9px; - font-size: 12.025px; - line-height: 18px; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 20px; word-break: break-all; word-wrap: break-word; white-space: pre; @@ -706,7 +851,7 @@ pre { } pre.prettyprint { - margin-bottom: 18px; + margin-bottom: 20px; } pre code { @@ -722,7 +867,7 @@ pre code { } form { - margin: 0 0 18px; + margin: 0 0 20px; } fieldset { @@ -735,16 +880,16 @@ legend { display: block; width: 100%; padding: 0; - margin-bottom: 27px; - font-size: 19.5px; - line-height: 36px; + margin-bottom: 20px; + font-size: 21px; + line-height: 40px; color: #333333; border: 0; border-bottom: 1px solid #e5e5e5; } legend small { - font-size: 13.5px; + font-size: 15px; color: #999999; } @@ -753,9 +898,9 @@ input, button, select, textarea { - font-size: 13px; + font-size: 14px; font-weight: normal; - line-height: 18px; + line-height: 20px; } input, @@ -788,12 +933,15 @@ input[type="tel"], input[type="color"], .uneditable-input { display: inline-block; - height: 18px; - padding: 4px; + height: 20px; + padding: 4px 6px; margin-bottom: 9px; - font-size: 13px; - line-height: 18px; + font-size: 14px; + line-height: 20px; color: #555555; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; } input, @@ -823,15 +971,11 @@ input[type="color"], .uneditable-input { background-color: #ffffff; border: 1px solid #cccccc; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; -moz-transition: border linear 0.2s, box-shadow linear 0.2s; - -ms-transition: border linear 0.2s, box-shadow linear 0.2s; -o-transition: border linear 0.2s, box-shadow linear 0.2s; transition: border linear 0.2s, box-shadow linear 0.2s; } @@ -864,14 +1008,15 @@ input[type="color"]:focus, input[type="radio"], input[type="checkbox"] { - margin: 3px 0; + margin: 4px 0 0; + margin-top: 1px \9; *margin-top: 0; - /* IE7 */ - line-height: normal; cursor: pointer; } +input[type="file"], +input[type="image"], input[type="submit"], input[type="reset"], input[type="button"], @@ -880,24 +1025,20 @@ input[type="checkbox"] { width: auto; } -.uneditable-textarea { - width: auto; - height: auto; -} - select, input[type="file"] { - height: 28px; + height: 30px; /* In IE7, the height of the select element cannot be changed by height, only font-size */ *margin-top: 4px; /* For IE7, add top margin to align select with labels */ - line-height: 28px; + line-height: 30px; } select { width: 220px; + background-color: #ffffff; border: 1px solid #bbb; } @@ -915,6 +1056,42 @@ input[type="checkbox"]:focus { outline-offset: -2px; } +.uneditable-input, +.uneditable-textarea { + color: #999999; + cursor: not-allowed; + background-color: #fcfcfc; + border-color: #cccccc; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); +} + +.uneditable-input { + overflow: hidden; + white-space: nowrap; +} + +.uneditable-textarea { + width: auto; + height: auto; +} + +input:-moz-placeholder, +textarea:-moz-placeholder { + color: #999999; +} + +input:-ms-input-placeholder, +textarea:-ms-input-placeholder { + color: #999999; +} + +input::-webkit-input-placeholder, +textarea::-webkit-input-placeholder { + color: #999999; +} + .radio, .checkbox { min-height: 18px; @@ -985,6 +1162,10 @@ textarea[class*="span"], .input-append .uneditable-input[class*="span"], .input-prepend input[class*="span"], .input-prepend .uneditable-input[class*="span"], +.row-fluid input[class*="span"], +.row-fluid select[class*="span"], +.row-fluid textarea[class*="span"], +.row-fluid .uneditable-input[class*="span"], .row-fluid .input-prepend [class*="span"], .row-fluid .input-append [class*="span"] { display: inline-block; @@ -996,76 +1177,99 @@ textarea, margin-left: 0; } -input.span12, -textarea.span12, +.controls-row [class*="span"] + [class*="span"] { + margin-left: 20px; +} + +input.span12, +textarea.span12, .uneditable-input.span12 { - width: 930px; + width: 926px; } input.span11, textarea.span11, .uneditable-input.span11 { - width: 850px; + width: 846px; } input.span10, textarea.span10, .uneditable-input.span10 { - width: 770px; + width: 766px; } input.span9, textarea.span9, .uneditable-input.span9 { - width: 690px; + width: 686px; } input.span8, textarea.span8, .uneditable-input.span8 { - width: 610px; + width: 606px; } input.span7, textarea.span7, .uneditable-input.span7 { - width: 530px; + width: 526px; } input.span6, textarea.span6, .uneditable-input.span6 { - width: 450px; + width: 446px; } input.span5, textarea.span5, .uneditable-input.span5 { - width: 370px; + width: 366px; } input.span4, textarea.span4, .uneditable-input.span4 { - width: 290px; + width: 286px; } input.span3, textarea.span3, .uneditable-input.span3 { - width: 210px; + width: 206px; } input.span2, textarea.span2, .uneditable-input.span2 { - width: 130px; + width: 126px; } input.span1, textarea.span1, .uneditable-input.span1 { - width: 50px; + width: 46px; +} + +.controls-row { + *zoom: 1; +} + +.controls-row:before, +.controls-row:after { + display: table; + line-height: 0; + content: ""; +} + +.controls-row:after { + clear: both; +} + +.controls-row [class*="span"] { + float: left; } input[disabled], @@ -1076,7 +1280,6 @@ select[readonly], textarea[readonly] { cursor: not-allowed; background-color: #eeeeee; - border-color: #ddd; } input[type="radio"][disabled], @@ -1099,6 +1302,9 @@ input[type="checkbox"][readonly] { .control-group.warning textarea { color: #c09853; border-color: #c09853; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .control-group.warning .checkbox:focus, @@ -1107,9 +1313,9 @@ input[type="checkbox"][readonly] { .control-group.warning select:focus, .control-group.warning textarea:focus { border-color: #a47e3c; - -webkit-box-shadow: 0 0 6px #dbc59e; - -moz-box-shadow: 0 0 6px #dbc59e; - box-shadow: 0 0 6px #dbc59e; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; } .control-group.warning .input-prepend .add-on, @@ -1132,6 +1338,9 @@ input[type="checkbox"][readonly] { .control-group.error textarea { color: #b94a48; border-color: #b94a48; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .control-group.error .checkbox:focus, @@ -1140,9 +1349,9 @@ input[type="checkbox"][readonly] { .control-group.error select:focus, .control-group.error textarea:focus { border-color: #953b39; - -webkit-box-shadow: 0 0 6px #d59392; - -moz-box-shadow: 0 0 6px #d59392; - box-shadow: 0 0 6px #d59392; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; } .control-group.error .input-prepend .add-on, @@ -1165,6 +1374,9 @@ input[type="checkbox"][readonly] { .control-group.success textarea { color: #468847; border-color: #468847; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .control-group.success .checkbox:focus, @@ -1173,9 +1385,9 @@ input[type="checkbox"][readonly] { .control-group.success select:focus, .control-group.success textarea:focus { border-color: #356635; - -webkit-box-shadow: 0 0 6px #7aba7b; - -moz-box-shadow: 0 0 6px #7aba7b; - box-shadow: 0 0 6px #7aba7b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; } .control-group.success .input-prepend .add-on, @@ -1202,9 +1414,9 @@ select:focus:required:invalid:focus { } .form-actions { - padding: 17px 20px 18px; - margin-top: 18px; - margin-bottom: 18px; + padding: 19px 20px 20px; + margin-top: 20px; + margin-bottom: 20px; background-color: #f5f5f5; border-top: 1px solid #e5e5e5; *zoom: 1; @@ -1213,6 +1425,7 @@ select:focus:required:invalid:focus { .form-actions:before, .form-actions:after { display: table; + line-height: 0; content: ""; } @@ -1220,37 +1433,14 @@ select:focus:required:invalid:focus { clear: both; } -.uneditable-input { - overflow: hidden; - white-space: nowrap; - cursor: not-allowed; - background-color: #ffffff; - border-color: #eee; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); -} - -:-moz-placeholder { - color: #999999; -} - -:-ms-input-placeholder { - color: #999999; -} - -::-webkit-input-placeholder { - color: #999999; -} - .help-block, .help-inline { - color: #555555; + color: #595959; } .help-block { display: block; - margin-bottom: 9px; + margin-bottom: 10px; } .help-inline { @@ -1261,68 +1451,67 @@ select:focus:required:invalid:focus { *zoom: 1; } -.input-prepend, -.input-append { +.input-append, +.input-prepend { margin-bottom: 5px; + font-size: 0; + white-space: nowrap; } -.input-prepend input, .input-append input, -.input-prepend select, +.input-prepend input, .input-append select, -.input-prepend .uneditable-input, -.input-append .uneditable-input { +.input-prepend select, +.input-append .uneditable-input, +.input-prepend .uneditable-input { position: relative; margin-bottom: 0; *margin-left: 0; - vertical-align: middle; + font-size: 14px; + vertical-align: top; -webkit-border-radius: 0 3px 3px 0; -moz-border-radius: 0 3px 3px 0; border-radius: 0 3px 3px 0; } -.input-prepend input:focus, .input-append input:focus, -.input-prepend select:focus, +.input-prepend input:focus, .input-append select:focus, -.input-prepend .uneditable-input:focus, -.input-append .uneditable-input:focus { +.input-prepend select:focus, +.input-append .uneditable-input:focus, +.input-prepend .uneditable-input:focus { z-index: 2; } -.input-prepend .uneditable-input, -.input-append .uneditable-input { - border-left-color: #ccc; -} - -.input-prepend .add-on, -.input-append .add-on { +.input-append .add-on, +.input-prepend .add-on { display: inline-block; width: auto; - height: 18px; + height: 20px; min-width: 16px; padding: 4px 5px; + font-size: 14px; font-weight: normal; - line-height: 18px; + line-height: 20px; text-align: center; text-shadow: 0 1px 0 #ffffff; - vertical-align: middle; background-color: #eeeeee; border: 1px solid #ccc; } -.input-prepend .add-on, .input-append .add-on, -.input-prepend .btn, -.input-append .btn { +.input-prepend .add-on, +.input-append .btn, +.input-prepend .btn { margin-left: -1px; + vertical-align: top; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } -.input-prepend .active, -.input-append .active { +.input-append .active, +.input-prepend .active { background-color: #a9dba9; border-color: #46a546; } @@ -1347,11 +1536,6 @@ select:focus:required:invalid:focus { border-radius: 3px 0 0 3px; } -.input-append .uneditable-input { - border-right-color: #ccc; - border-left-color: #eee; -} - .input-append .add-on:last-child, .input-append .btn:last-child { -webkit-border-radius: 0 3px 3px 0; @@ -1383,7 +1567,7 @@ select:focus:required:invalid:focus { border-radius: 0 3px 3px 0; } -.search-query { +input.search-query { padding-right: 14px; padding-right: 4px \9; padding-left: 14px; @@ -1391,9 +1575,42 @@ select:focus:required:invalid:focus { /* IE7-8 doesn't have border-radius, so don't indent the padding */ margin-bottom: 0; - -webkit-border-radius: 14px; - -moz-border-radius: 14px; - border-radius: 14px; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} + +/* Allow for input prepend/append in search forms */ + +.form-search .input-append .search-query, +.form-search .input-prepend .search-query { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.form-search .input-append .search-query { + -webkit-border-radius: 14px 0 0 14px; + -moz-border-radius: 14px 0 0 14px; + border-radius: 14px 0 0 14px; +} + +.form-search .input-append .btn { + -webkit-border-radius: 0 14px 14px 0; + -moz-border-radius: 0 14px 14px 0; + border-radius: 0 14px 14px 0; +} + +.form-search .input-prepend .search-query { + -webkit-border-radius: 0 14px 14px 0; + -moz-border-radius: 0 14px 14px 0; + border-radius: 0 14px 14px 0; +} + +.form-search .input-prepend .btn { + -webkit-border-radius: 14px 0 0 14px; + -moz-border-radius: 14px 0 0 14px; + border-radius: 14px 0 0 14px; } .form-search input, @@ -1420,6 +1637,7 @@ select:focus:required:invalid:focus { display: inline-block; *display: inline; margin-bottom: 0; + vertical-align: middle; *zoom: 1; } @@ -1430,7 +1648,9 @@ select:focus:required:invalid:focus { } .form-search label, -.form-inline label { +.form-inline label, +.form-search .btn-group, +.form-inline .btn-group { display: inline-block; } @@ -1460,22 +1680,23 @@ select:focus:required:invalid:focus { } .control-group { - margin-bottom: 9px; + margin-bottom: 10px; } legend + .control-group { - margin-top: 18px; + margin-top: 20px; -webkit-margin-top-collapse: separate; } .form-horizontal .control-group { - margin-bottom: 18px; + margin-bottom: 20px; *zoom: 1; } .form-horizontal .control-group:before, .form-horizontal .control-group:after { display: table; + line-height: 0; content: ""; } @@ -1502,7 +1723,7 @@ legend + .control-group { } .form-horizontal .help-block { - margin-top: 9px; + margin-top: 10px; margin-bottom: 0; } @@ -1519,13 +1740,13 @@ table { .table { width: 100%; - margin-bottom: 18px; + margin-bottom: 20px; } .table th, .table td { padding: 8px; - line-height: 18px; + line-height: 20px; text-align: left; vertical-align: top; border-top: 1px solid #dddddd; @@ -1560,7 +1781,7 @@ table { .table-bordered { border: 1px solid #dddddd; border-collapse: separate; - *border-collapse: collapsed; + *border-collapse: collapse; border-left: 0; -webkit-border-radius: 4px; -moz-border-radius: 4px; @@ -1599,7 +1820,8 @@ table { } .table-bordered thead:last-child tr:last-child th:first-child, -.table-bordered tbody:last-child tr:last-child td:first-child { +.table-bordered tbody:last-child tr:last-child td:first-child, +.table-bordered tfoot:last-child tr:last-child td:first-child { -webkit-border-radius: 0 0 0 4px; -moz-border-radius: 0 0 0 4px; border-radius: 0 0 0 4px; @@ -1609,22 +1831,48 @@ table { } .table-bordered thead:last-child tr:last-child th:last-child, -.table-bordered tbody:last-child tr:last-child td:last-child { +.table-bordered tbody:last-child tr:last-child td:last-child, +.table-bordered tfoot:last-child tr:last-child td:last-child { -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; -moz-border-radius-bottomright: 4px; } +.table-bordered caption + thead tr:first-child th:first-child, +.table-bordered caption + tbody tr:first-child td:first-child, +.table-bordered colgroup + thead tr:first-child th:first-child, +.table-bordered colgroup + tbody tr:first-child td:first-child { + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; +} + +.table-bordered caption + thead tr:first-child th:last-child, +.table-bordered caption + tbody tr:first-child td:last-child, +.table-bordered colgroup + thead tr:first-child th:last-child, +.table-bordered colgroup + tbody tr:first-child td:last-child { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-right-topleft: 4px; +} + .table-striped tbody tr:nth-child(odd) td, .table-striped tbody tr:nth-child(odd) th { background-color: #f9f9f9; } -.table tbody tr:hover td, -.table tbody tr:hover th { +.table-hover tbody tr:hover td, +.table-hover tbody tr:hover th { background-color: #f5f5f5; } +table [class*=span], +.row-fluid table [class*=span] { + display: table-cell; + float: none; + margin-left: 0; +} + table .span1 { float: none; width: 44px; @@ -1769,11 +2017,24 @@ table .span24 { margin-left: 0; } +.table tbody tr.success td { + background-color: #dff0d8; +} + +.table tbody tr.error td { + background-color: #f2dede; +} + +.table tbody tr.info td { + background-color: #d9edf7; +} + [class^="icon-"], [class*=" icon-"] { display: inline-block; width: 14px; height: 14px; + margin-top: 1px; *margin-right: .3em; line-height: 14px; vertical-align: text-top; @@ -1782,12 +2043,15 @@ table .span24 { background-repeat: no-repeat; } -[class^="icon-"]:last-child, -[class*=" icon-"]:last-child { - *margin-left: 0; -} +/* White icons with optional class, or on hover/active states of certain elements */ -.icon-white { +.icon-white, +.nav > .active > a > [class^="icon-"], +.nav > .active > a > [class*=" icon-"], +.dropdown-menu > li > a:hover > [class^="icon-"], +.dropdown-menu > li > a:hover > [class*=" icon-"], +.dropdown-menu > .active > a > [class^="icon-"], +.dropdown-menu > .active > a > [class*=" icon-"] { background-image: url("../img/glyphicons-halflings-white.png"); } @@ -2228,6 +2492,7 @@ table .span24 { } .icon-random { + width: 16px; background-position: -216px -120px; } @@ -2260,6 +2525,7 @@ table .span24 { } .icon-folder-open { + width: 16px; background-position: -408px -120px; } @@ -2374,8 +2640,6 @@ table .span24 { border-right: 4px solid transparent; border-left: 4px solid transparent; content: ""; - opacity: 0.3; - filter: alpha(opacity=30); } .dropdown .caret { @@ -2383,12 +2647,6 @@ table .span24 { margin-left: 2px; } -.dropdown:hover .caret, -.open .caret { - opacity: 1; - filter: alpha(opacity=100); -} - .dropdown-menu { position: absolute; top: 100%; @@ -2397,17 +2655,17 @@ table .span24 { display: none; float: left; min-width: 160px; - padding: 4px 0; - margin: 1px 0 0; + padding: 5px 0; + margin: 2px 0 0; list-style: none; background-color: #ffffff; border: 1px solid #ccc; border: 1px solid rgba(0, 0, 0, 0.2); *border-right-width: 2px; *border-bottom-width: 2px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); @@ -2424,7 +2682,7 @@ table .span24 { .dropdown-menu .divider { *width: 100%; height: 1px; - margin: 8px 1px; + margin: 9px 1px; *margin: -5px 0 5px; overflow: hidden; background-color: #e5e5e5; @@ -2433,20 +2691,55 @@ table .span24 { .dropdown-menu a { display: block; - padding: 3px 15px; + padding: 3px 20px; clear: both; font-weight: normal; - line-height: 18px; + line-height: 20px; color: #333333; white-space: nowrap; } .dropdown-menu li > a:hover, +.dropdown-menu li > a:focus, +.dropdown-submenu:hover > a { + color: #ffffff; + text-decoration: none; + background-color: #0088cc; + background-color: #0081c2; + background-image: -moz-linear-gradient(top, #0088cc, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); + background-image: -o-linear-gradient(top, #0088cc, #0077b3); + background-image: linear-gradient(to bottom, #0088cc, #0077b3); + background-repeat: repeat-x; + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); +} + .dropdown-menu .active > a, .dropdown-menu .active > a:hover { color: #ffffff; text-decoration: none; background-color: #0088cc; + background-color: #0081c2; + background-image: linear-gradient(to bottom, #0088cc, #0077b3); + background-image: -moz-linear-gradient(top, #0088cc, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); + background-image: -o-linear-gradient(top, #0088cc, #0077b3); + background-repeat: repeat-x; + outline: 0; + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); +} + +.dropdown-menu .disabled > a, +.dropdown-menu .disabled > a:hover { + color: #999999; +} + +.dropdown-menu .disabled > a:hover { + text-decoration: none; + cursor: default; + background-color: transparent; } .open { @@ -2476,6 +2769,47 @@ table .span24 { margin-bottom: 1px; } +.dropdown-submenu { + position: relative; +} + +.dropdown-submenu > .dropdown-menu { + top: 0; + left: 100%; + margin-top: -6px; + margin-left: -1px; + -webkit-border-radius: 0 6px 6px 6px; + -moz-border-radius: 0 6px 6px 6px; + border-radius: 0 6px 6px 6px; +} + +.dropdown-submenu:hover .dropdown-menu { + display: block; +} + +.dropdown-submenu > a:after { + display: block; + float: right; + width: 0; + height: 0; + margin-top: 5px; + margin-right: -10px; + border-color: transparent; + border-left-color: #cccccc; + border-style: solid; + border-width: 5px 0 5px 5px; + content: " "; +} + +.dropdown-submenu:hover > a:after { + border-left-color: #ffffff; +} + +.dropdown .dropdown-menu .nav-header { + padding-right: 20px; + padding-left: 20px; +} + .typeahead { margin-top: 2px; -webkit-border-radius: 4px; @@ -2488,8 +2822,7 @@ table .span24 { padding: 19px; margin-bottom: 20px; background-color: #f5f5f5; - border: 1px solid #eee; - border: 1px solid rgba(0, 0, 0, 0.05); + border: 1px solid #e3e3e3; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; @@ -2521,7 +2854,6 @@ table .span24 { opacity: 0; -webkit-transition: opacity 0.15s linear; -moz-transition: opacity 0.15s linear; - -ms-transition: opacity 0.15s linear; -o-transition: opacity 0.15s linear; transition: opacity 0.15s linear; } @@ -2534,9 +2866,9 @@ table .span24 { position: relative; height: 0; overflow: hidden; + overflow: visible \9; -webkit-transition: height 0.35s ease; -moz-transition: height 0.35s ease; - -ms-transition: height 0.35s ease; -o-transition: height 0.35s ease; transition: height 0.35s ease; } @@ -2549,7 +2881,7 @@ table .span24 { float: right; font-size: 20px; font-weight: bold; - line-height: 18px; + line-height: 20px; color: #000000; text-shadow: 0 1px 0 #ffffff; opacity: 0.2; @@ -2575,11 +2907,11 @@ button.close { .btn { display: inline-block; *display: inline; - padding: 4px 10px 4px; + padding: 4px 14px; margin-bottom: 0; *margin-left: .3em; - font-size: 13px; - line-height: 18px; + font-size: 14px; + line-height: 20px; *line-height: 20px; color: #333333; text-align: center; @@ -2588,22 +2920,21 @@ button.close { cursor: pointer; background-color: #f5f5f5; *background-color: #e6e6e6; - background-image: -ms-linear-gradient(top, #ffffff, #e6e6e6); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); - background-image: linear-gradient(top, #ffffff, #e6e6e6); + background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); background-repeat: repeat-x; - border: 1px solid #cccccc; + border: 1px solid #bbbbbb; *border: 0; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border-color: #e6e6e6 #e6e6e6 #bfbfbf; - border-bottom-color: #b3b3b3; + border-bottom-color: #a2a2a2; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); filter: progid:dximagetransform.microsoft.gradient(enabled=false); *zoom: 1; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); @@ -2616,6 +2947,7 @@ button.close { .btn.active, .btn.disabled, .btn[disabled] { + color: #333333; background-color: #e6e6e6; *background-color: #d9d9d9; } @@ -2639,7 +2971,6 @@ button.close { background-position: 0 -15px; -webkit-transition: background-position 0.1s linear; -moz-transition: background-position 0.1s linear; - -ms-transition: background-position 0.1s linear; -o-transition: background-position 0.1s linear; transition: background-position 0.1s linear; } @@ -2675,7 +3006,7 @@ button.close { .btn-large { padding: 9px 14px; - font-size: 15px; + font-size: 16px; line-height: normal; -webkit-border-radius: 5px; -moz-border-radius: 5px; @@ -2683,39 +3014,37 @@ button.close { } .btn-large [class^="icon-"] { - margin-top: 1px; + margin-top: 2px; } .btn-small { - padding: 5px 9px; - font-size: 11px; - line-height: 16px; + padding: 3px 9px; + font-size: 12px; + line-height: 18px; } .btn-small [class^="icon-"] { - margin-top: -1px; + margin-top: 0; } .btn-mini { padding: 2px 6px; font-size: 11px; - line-height: 14px; + line-height: 16px; } -.btn-primary, -.btn-primary:hover, -.btn-warning, -.btn-warning:hover, -.btn-danger, -.btn-danger:hover, -.btn-success, -.btn-success:hover, -.btn-info, -.btn-info:hover, -.btn-inverse, -.btn-inverse:hover { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +.btn-block { + display: block; + width: 100%; + padding-right: 0; + padding-left: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.btn-block + .btn-block { + margin-top: 5px; } .btn-primary.active, @@ -2728,23 +3057,24 @@ button.close { } .btn { - border-color: #ccc; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + border-color: #c5c5c5; + border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25); } .btn-primary { - background-color: #0074cc; - *background-color: #0055cc; - background-image: -ms-linear-gradient(top, #0088cc, #0055cc); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0055cc)); - background-image: -webkit-linear-gradient(top, #0088cc, #0055cc); - background-image: -o-linear-gradient(top, #0088cc, #0055cc); - background-image: -moz-linear-gradient(top, #0088cc, #0055cc); - background-image: linear-gradient(top, #0088cc, #0055cc); + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #006dcc; + *background-color: #0044cc; + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); + background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); + background-image: -o-linear-gradient(top, #0088cc, #0044cc); + background-image: linear-gradient(to bottom, #0088cc, #0044cc); + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); background-repeat: repeat-x; - border-color: #0055cc #0055cc #003580; + border-color: #0044cc #0044cc #002a80; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#0088cc', endColorstr='#0055cc', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0); filter: progid:dximagetransform.microsoft.gradient(enabled=false); } @@ -2753,28 +3083,30 @@ button.close { .btn-primary.active, .btn-primary.disabled, .btn-primary[disabled] { - background-color: #0055cc; - *background-color: #004ab3; + color: #ffffff; + background-color: #0044cc; + *background-color: #003bb3; } .btn-primary:active, .btn-primary.active { - background-color: #004099 \9; + background-color: #003399 \9; } .btn-warning { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); background-color: #faa732; *background-color: #f89406; - background-image: -ms-linear-gradient(top, #fbb450, #f89406); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); background-image: -webkit-linear-gradient(top, #fbb450, #f89406); background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(to bottom, #fbb450, #f89406); background-image: -moz-linear-gradient(top, #fbb450, #f89406); - background-image: linear-gradient(top, #fbb450, #f89406); background-repeat: repeat-x; border-color: #f89406 #f89406 #ad6704; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); filter: progid:dximagetransform.microsoft.gradient(enabled=false); } @@ -2783,6 +3115,7 @@ button.close { .btn-warning.active, .btn-warning.disabled, .btn-warning[disabled] { + color: #ffffff; background-color: #f89406; *background-color: #df8505; } @@ -2793,18 +3126,19 @@ button.close { } .btn-danger { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); background-color: #da4f49; *background-color: #bd362f; - background-image: -ms-linear-gradient(top, #ee5f5b, #bd362f); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); + background-image: linear-gradient(to bottom, #ee5f5b, #bd362f); background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); - background-image: linear-gradient(top, #ee5f5b, #bd362f); background-repeat: repeat-x; border-color: #bd362f #bd362f #802420; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#bd362f', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0); filter: progid:dximagetransform.microsoft.gradient(enabled=false); } @@ -2813,6 +3147,7 @@ button.close { .btn-danger.active, .btn-danger.disabled, .btn-danger[disabled] { + color: #ffffff; background-color: #bd362f; *background-color: #a9302a; } @@ -2823,18 +3158,19 @@ button.close { } .btn-success { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); background-color: #5bb75b; *background-color: #51a351; - background-image: -ms-linear-gradient(top, #62c462, #51a351); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); background-image: -webkit-linear-gradient(top, #62c462, #51a351); background-image: -o-linear-gradient(top, #62c462, #51a351); + background-image: linear-gradient(to bottom, #62c462, #51a351); background-image: -moz-linear-gradient(top, #62c462, #51a351); - background-image: linear-gradient(top, #62c462, #51a351); background-repeat: repeat-x; border-color: #51a351 #51a351 #387038; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#62c462', endColorstr='#51a351', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0); filter: progid:dximagetransform.microsoft.gradient(enabled=false); } @@ -2843,6 +3179,7 @@ button.close { .btn-success.active, .btn-success.disabled, .btn-success[disabled] { + color: #ffffff; background-color: #51a351; *background-color: #499249; } @@ -2853,18 +3190,19 @@ button.close { } .btn-info { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); background-color: #49afcd; *background-color: #2f96b4; - background-image: -ms-linear-gradient(top, #5bc0de, #2f96b4); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); + background-image: linear-gradient(to bottom, #5bc0de, #2f96b4); background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); - background-image: linear-gradient(top, #5bc0de, #2f96b4); background-repeat: repeat-x; border-color: #2f96b4 #2f96b4 #1f6377; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#5bc0de', endColorstr='#2f96b4', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0); filter: progid:dximagetransform.microsoft.gradient(enabled=false); } @@ -2873,6 +3211,7 @@ button.close { .btn-info.active, .btn-info.disabled, .btn-info[disabled] { + color: #ffffff; background-color: #2f96b4; *background-color: #2a85a0; } @@ -2883,18 +3222,19 @@ button.close { } .btn-inverse { - background-color: #414141; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #363636; *background-color: #222222; - background-image: -ms-linear-gradient(top, #555555, #222222); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#555555), to(#222222)); - background-image: -webkit-linear-gradient(top, #555555, #222222); - background-image: -o-linear-gradient(top, #555555, #222222); - background-image: -moz-linear-gradient(top, #555555, #222222); - background-image: linear-gradient(top, #555555, #222222); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222)); + background-image: -webkit-linear-gradient(top, #444444, #222222); + background-image: -o-linear-gradient(top, #444444, #222222); + background-image: linear-gradient(to bottom, #444444, #222222); + background-image: -moz-linear-gradient(top, #444444, #222222); background-repeat: repeat-x; border-color: #222222 #222222 #000000; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#555555', endColorstr='#222222', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0); filter: progid:dximagetransform.microsoft.gradient(enabled=false); } @@ -2903,6 +3243,7 @@ button.close { .btn-inverse.active, .btn-inverse.disabled, .btn-inverse[disabled] { + color: #ffffff; background-color: #222222; *background-color: #151515; } @@ -2914,8 +3255,8 @@ button.close { button.btn, input[type="submit"].btn { - *padding-top: 2px; - *padding-bottom: 2px; + *padding-top: 3px; + *padding-bottom: 3px; } button.btn::-moz-focus-inner, @@ -2942,20 +3283,35 @@ input[type="submit"].btn.btn-mini { *padding-bottom: 1px; } -.btn-group { - position: relative; - *margin-left: .3em; - *zoom: 1; +.btn-link, +.btn-link:active { + background-color: transparent; + background-image: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; } -.btn-group:before, -.btn-group:after { - display: table; - content: ""; +.btn-link { + color: #0088cc; + cursor: pointer; + border-color: transparent; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; } -.btn-group:after { - clear: both; +.btn-link:hover { + color: #005580; + text-decoration: underline; + background-color: transparent; +} + +.btn-group { + position: relative; + *margin-left: .3em; + font-size: 0; + white-space: nowrap; } .btn-group:first-child { @@ -2967,8 +3323,9 @@ input[type="submit"].btn.btn-mini { } .btn-toolbar { - margin-top: 9px; - margin-bottom: 9px; + margin-top: 10px; + margin-bottom: 10px; + font-size: 0; } .btn-toolbar .btn-group { @@ -2979,15 +3336,40 @@ input[type="submit"].btn.btn-mini { *zoom: 1; } +.btn-toolbar .btn + .btn, +.btn-toolbar .btn-group + .btn, +.btn-toolbar .btn + .btn-group { + margin-left: 5px; +} + .btn-group > .btn { position: relative; - float: left; - margin-left: -1px; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } +.btn-group > .btn + .btn { + margin-left: -1px; +} + +.btn-group > .btn, +.btn-group > .dropdown-menu { + font-size: 14px; +} + +.btn-group > .btn-mini { + font-size: 11px; +} + +.btn-group > .btn-small { + font-size: 12px; +} + +.btn-group > .btn-large { + font-size: 16px; +} + .btn-group > .btn:first-child { margin-left: 0; -webkit-border-bottom-left-radius: 4px; @@ -3040,28 +3422,32 @@ input[type="submit"].btn.btn-mini { outline: 0; } -.btn-group > .dropdown-toggle { - *padding-top: 4px; +.btn-group > .btn + .dropdown-toggle { + *padding-top: 5px; padding-right: 8px; - *padding-bottom: 4px; + *padding-bottom: 5px; padding-left: 8px; -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); } -.btn-group > .btn-mini.dropdown-toggle { +.btn-group > .btn-mini + .dropdown-toggle { + *padding-top: 2px; padding-right: 5px; + *padding-bottom: 2px; padding-left: 5px; } -.btn-group > .btn-small.dropdown-toggle { - *padding-top: 4px; +.btn-group > .btn-small + .dropdown-toggle { + *padding-top: 5px; *padding-bottom: 4px; } -.btn-group > .btn-large.dropdown-toggle { +.btn-group > .btn-large + .dropdown-toggle { + *padding-top: 7px; padding-right: 12px; + *padding-bottom: 7px; padding-left: 12px; } @@ -3077,7 +3463,7 @@ input[type="submit"].btn.btn-mini { } .btn-group.open .btn-primary.dropdown-toggle { - background-color: #0055cc; + background-color: #0044cc; } .btn-group.open .btn-warning.dropdown-toggle { @@ -3101,26 +3487,17 @@ input[type="submit"].btn.btn-mini { } .btn .caret { - margin-top: 7px; + margin-top: 8px; margin-left: 0; } -.btn:hover .caret, -.open.btn-group .caret { - opacity: 1; - filter: alpha(opacity=100); -} - -.btn-mini .caret { - margin-top: 5px; -} - -.btn-small .caret { +.btn-mini .caret, +.btn-small .caret, +.btn-large .caret { margin-top: 6px; } .btn-large .caret { - margin-top: 6px; border-top-width: 5px; border-right-width: 5px; border-left-width: 5px; @@ -3139,13 +3516,57 @@ input[type="submit"].btn.btn-mini { .btn-inverse .caret { border-top-color: #ffffff; border-bottom-color: #ffffff; - opacity: 0.75; - filter: alpha(opacity=75); +} + +.btn-group-vertical { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + + *zoom: 1; +} + +.btn-group-vertical .btn { + display: block; + float: none; + width: 100%; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.btn-group-vertical .btn + .btn { + margin-top: -1px; + margin-left: 0; +} + +.btn-group-vertical .btn:first-child { + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} + +.btn-group-vertical .btn:last-child { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + +.btn-group-vertical .btn-large:first-child { + -webkit-border-radius: 6px 6px 0 0; + -moz-border-radius: 6px 6px 0 0; + border-radius: 6px 6px 0 0; +} + +.btn-group-vertical .btn-large:last-child { + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; } .alert { padding: 8px 35px 8px 14px; - margin-bottom: 18px; + margin-bottom: 20px; color: #c09853; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); background-color: #fcf8e3; @@ -3155,15 +3576,15 @@ input[type="submit"].btn.btn-mini { border-radius: 4px; } -.alert-heading { - color: inherit; +.alert h4 { + margin: 0; } .alert .close { position: relative; top: -2px; right: -21px; - line-height: 18px; + line-height: 20px; } .alert-success { @@ -3200,7 +3621,7 @@ input[type="submit"].btn.btn-mini { } .nav { - margin-bottom: 18px; + margin-bottom: 20px; margin-left: 0; list-style: none; } @@ -3218,12 +3639,12 @@ input[type="submit"].btn.btn-mini { float: right; } -.nav .nav-header { +.nav-header { display: block; padding: 3px 15px; font-size: 11px; font-weight: bold; - line-height: 18px; + line-height: 20px; color: #999999; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); text-transform: uppercase; @@ -3264,7 +3685,7 @@ input[type="submit"].btn.btn-mini { .nav-list .divider { *width: 100%; height: 1px; - margin: 8px 1px; + margin: 9px 1px; *margin: -5px 0 5px; overflow: hidden; background-color: #e5e5e5; @@ -3281,6 +3702,7 @@ input[type="submit"].btn.btn-mini { .nav-tabs:after, .nav-pills:after { display: table; + line-height: 0; content: ""; } @@ -3313,7 +3735,7 @@ input[type="submit"].btn.btn-mini { .nav-tabs > li > a { padding-top: 8px; padding-bottom: 8px; - line-height: 18px; + line-height: 20px; border: 1px solid transparent; -webkit-border-radius: 4px 4px 0 0; -moz-border-radius: 4px 4px 0 0; @@ -3369,15 +3791,21 @@ input[type="submit"].btn.btn-mini { } .nav-tabs.nav-stacked > li:first-child > a { - -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; } .nav-tabs.nav-stacked > li:last-child > a { - -webkit-border-radius: 0 0 4px 4px; - -moz-border-radius: 0 0 4px 4px; - border-radius: 0 0 4px 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomright: 4px; + -moz-border-radius-bottomleft: 4px; } .nav-tabs.nav-stacked > li > a:hover { @@ -3394,38 +3822,45 @@ input[type="submit"].btn.btn-mini { } .nav-tabs .dropdown-menu { - -webkit-border-radius: 0 0 5px 5px; - -moz-border-radius: 0 0 5px 5px; - border-radius: 0 0 5px 5px; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; } .nav-pills .dropdown-menu { - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; } -.nav-tabs .dropdown-toggle .caret, -.nav-pills .dropdown-toggle .caret { +.nav .dropdown-toggle .caret { margin-top: 6px; border-top-color: #0088cc; border-bottom-color: #0088cc; } -.nav-tabs .dropdown-toggle:hover .caret, -.nav-pills .dropdown-toggle:hover .caret { +.nav .dropdown-toggle:hover .caret { border-top-color: #005580; border-bottom-color: #005580; } -.nav-tabs .active .dropdown-toggle .caret, -.nav-pills .active .dropdown-toggle .caret { - border-top-color: #333333; - border-bottom-color: #333333; +/* move down carets for tabs */ + +.nav-tabs .dropdown-toggle .caret { + margin-top: 8px; +} + +.nav .active .dropdown-toggle .caret { + border-top-color: #fff; + border-bottom-color: #fff; +} + +.nav-tabs .active .dropdown-toggle .caret { + border-top-color: #555555; + border-bottom-color: #555555; } .nav > .dropdown.active > a:hover { - color: #000000; cursor: pointer; } @@ -3457,6 +3892,7 @@ input[type="submit"].btn.btn-mini { .tabbable:before, .tabbable:after { display: table; + line-height: 0; content: ""; } @@ -3567,34 +4003,43 @@ input[type="submit"].btn.btn-mini { *border-left-color: #ffffff; } +.nav > .disabled > a { + color: #999999; +} + +.nav > .disabled > a:hover { + text-decoration: none; + cursor: default; + background-color: transparent; +} + .navbar { *position: relative; *z-index: 2; - margin-bottom: 18px; + margin-bottom: 20px; overflow: visible; + color: #555555; } .navbar-inner { min-height: 40px; padding-right: 20px; padding-left: 20px; - background-color: #2c2c2c; - background-image: -moz-linear-gradient(top, #333333, #222222); - background-image: -ms-linear-gradient(top, #333333, #222222); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222)); - background-image: -webkit-linear-gradient(top, #333333, #222222); - background-image: -o-linear-gradient(top, #333333, #222222); - background-image: linear-gradient(top, #333333, #222222); + background-color: #fafafa; + background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2)); + background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2); + background-image: -o-linear-gradient(top, #ffffff, #f2f2f2); + background-image: linear-gradient(to bottom, #ffffff, #f2f2f2); background-repeat: repeat-x; - + border: 1px solid #d4d4d4; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; - - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0); + -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); } .navbar .container { @@ -3605,41 +4050,44 @@ input[type="submit"].btn.btn-mini { height: auto; } -.navbar { - color: #999999; -} - -.navbar .brand:hover { - text-decoration: none; -} - .navbar .brand { display: block; float: left; - padding: 8px 20px 12px; + padding: 10px 20px 10px; margin-left: -20px; font-size: 20px; font-weight: 200; - line-height: 1; - color: #999999; + color: #555555; + text-shadow: 0 1px 0 #ffffff; +} + +.navbar .brand:hover { + text-decoration: none; } -.navbar .navbar-text { +.navbar-text { margin-bottom: 0; line-height: 40px; } -.navbar .navbar-link { - color: #999999; +.navbar-link { + color: #555555; } -.navbar .navbar-link:hover { - color: #ffffff; +.navbar-link:hover { + color: #333333; +} + +.navbar .divider-vertical { + height: 40px; + margin: 0 9px; + border-right: 1px solid #ffffff; + border-left: 1px solid #f2f2f2; } .navbar .btn, .navbar .btn-group { - margin-top: 5px; + margin-top: 6px; } .navbar .btn-group .btn { @@ -3654,6 +4102,7 @@ input[type="submit"].btn.btn-mini { .navbar-form:before, .navbar-form:after { display: table; + line-height: 0; content: ""; } @@ -3669,7 +4118,8 @@ input[type="submit"].btn.btn-mini { } .navbar-form input, -.navbar-form select { +.navbar-form select, +.navbar-form .btn { display: inline-block; margin-bottom: 0; } @@ -3694,52 +4144,32 @@ input[type="submit"].btn.btn-mini { .navbar-search { position: relative; float: left; - margin-top: 6px; + margin-top: 5px; margin-bottom: 0; } .navbar-search .search-query { - padding: 4px 9px; + padding: 4px 14px; + margin-bottom: 0; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 13px; font-weight: normal; line-height: 1; - color: #ffffff; - background-color: #626262; - border: 1px solid #151515; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - -webkit-transition: none; - -moz-transition: none; - -ms-transition: none; - -o-transition: none; - transition: none; -} - -.navbar-search .search-query:-moz-placeholder { - color: #cccccc; -} - -.navbar-search .search-query:-ms-input-placeholder { - color: #cccccc; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; } -.navbar-search .search-query::-webkit-input-placeholder { - color: #cccccc; +.navbar-static-top { + position: static; + width: 100%; + margin-bottom: 0; } -.navbar-search .search-query:focus, -.navbar-search .search-query.focused { - padding: 5px 10px; - color: #333333; - text-shadow: 0 1px 0 #ffffff; - background-color: #ffffff; - border: 0; - outline: 0; - -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); - -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); - box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); +.navbar-static-top .navbar-inner { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; } .navbar-fixed-top, @@ -3751,6 +4181,12 @@ input[type="submit"].btn.btn-mini { margin-bottom: 0; } +.navbar-fixed-top .navbar-inner, +.navbar-fixed-bottom .navbar-inner, +.navbar-static-top .navbar-inner { + border: 0; +} + .navbar-fixed-top .navbar-inner, .navbar-fixed-bottom .navbar-inner { padding-right: 0; @@ -3760,6 +4196,7 @@ input[type="submit"].btn.btn-mini { border-radius: 0; } +.navbar-static-top .container, .navbar-fixed-top .container, .navbar-fixed-bottom .container { width: 940px; @@ -3769,10 +4206,23 @@ input[type="submit"].btn.btn-mini { top: 0; } +.navbar-fixed-top .navbar-inner, +.navbar-static-top .navbar-inner { + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.1), 0 1px 10px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.1), 0 1px 10px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.1), 0 1px 10px rgba(0, 0, 0, 0.1); +} + .navbar-fixed-bottom { bottom: 0; } +.navbar-fixed-bottom .navbar-inner { + -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.1), 0 -1px 10px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.1), 0 -1px 10px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.1), 0 -1px 10px rgba(0, 0, 0, 0.1); +} + .navbar .nav { position: relative; left: 0; @@ -3786,56 +4236,37 @@ input[type="submit"].btn.btn-mini { } .navbar .nav > li { - display: block; float: left; } .navbar .nav > li > a { float: none; - padding: 9px 10px 11px; - line-height: 19px; - color: #999999; + padding: 10px 15px 10px; + color: #555555; text-decoration: none; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); -} - -.navbar .btn { - display: inline-block; - padding: 4px 10px 4px; - margin: 5px 5px 6px; - line-height: 18px; + text-shadow: 0 1px 0 #ffffff; } -.navbar .btn-group { - padding: 5px 5px 6px; - margin: 0; +.navbar .nav .dropdown-toggle .caret { + margin-top: 8px; } +.navbar .nav > li > a:focus, .navbar .nav > li > a:hover { - color: #ffffff; + color: #333333; text-decoration: none; background-color: transparent; } -.navbar .nav .active > a, -.navbar .nav .active > a:hover { - color: #ffffff; +.navbar .nav > .active > a, +.navbar .nav > .active > a:hover, +.navbar .nav > .active > a:focus { + color: #555555; text-decoration: none; - background-color: #222222; -} - -.navbar .divider-vertical { - width: 1px; - height: 40px; - margin: 0 9px; - overflow: hidden; - background-color: #222222; - border-right: 1px solid #333333; -} - -.navbar .nav.pull-right { - margin-right: 0; - margin-left: 10px; + background-color: #e5e5e5; + -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); + -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); } .navbar .btn-navbar { @@ -3844,18 +4275,19 @@ input[type="submit"].btn.btn-mini { padding: 7px 10px; margin-right: 5px; margin-left: 5px; - background-color: #2c2c2c; - *background-color: #222222; - background-image: -ms-linear-gradient(top, #333333, #222222); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222)); - background-image: -webkit-linear-gradient(top, #333333, #222222); - background-image: -o-linear-gradient(top, #333333, #222222); - background-image: linear-gradient(top, #333333, #222222); - background-image: -moz-linear-gradient(top, #333333, #222222); + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #ededed; + *background-color: #e5e5e5; + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5)); + background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5); + background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5); background-repeat: repeat-x; - border-color: #222222 #222222 #000000; + border-color: #e5e5e5 #e5e5e5 #bfbfbf; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0); filter: progid:dximagetransform.microsoft.gradient(enabled=false); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); @@ -3867,13 +4299,14 @@ input[type="submit"].btn.btn-mini { .navbar .btn-navbar.active, .navbar .btn-navbar.disabled, .navbar .btn-navbar[disabled] { - background-color: #222222; - *background-color: #151515; + color: #ffffff; + background-color: #e5e5e5; + *background-color: #d9d9d9; } .navbar .btn-navbar:active, .navbar .btn-navbar.active { - background-color: #080808 \9; + background-color: #cccccc \9; } .navbar .btn-navbar .icon-bar { @@ -3893,7 +4326,7 @@ input[type="submit"].btn.btn-mini { margin-top: 3px; } -.navbar .dropdown-menu:before { +.navbar .nav > li > .dropdown-menu:before { position: absolute; top: -7px; left: 9px; @@ -3905,7 +4338,7 @@ input[type="submit"].btn.btn-mini { content: ''; } -.navbar .dropdown-menu:after { +.navbar .nav > li > .dropdown-menu:after { position: absolute; top: -6px; left: 10px; @@ -3916,7 +4349,7 @@ input[type="submit"].btn.btn-mini { content: ''; } -.navbar-fixed-bottom .dropdown-menu:before { +.navbar-fixed-bottom .nav > li > .dropdown-menu:before { top: auto; bottom: -7px; border-top: 7px solid #ccc; @@ -3924,72 +4357,211 @@ input[type="submit"].btn.btn-mini { border-top-color: rgba(0, 0, 0, 0.2); } -.navbar-fixed-bottom .dropdown-menu:after { +.navbar-fixed-bottom .nav > li > .dropdown-menu:after { top: auto; bottom: -6px; border-top: 6px solid #ffffff; border-bottom: 0; } -.navbar .nav li.dropdown .dropdown-toggle .caret, -.navbar .nav li.dropdown.open .caret { +.navbar .nav li.dropdown.open > .dropdown-toggle, +.navbar .nav li.dropdown.active > .dropdown-toggle, +.navbar .nav li.dropdown.open.active > .dropdown-toggle { + color: #555555; + background-color: #e5e5e5; +} + +.navbar .nav li.dropdown > .dropdown-toggle .caret { + border-top-color: #555555; + border-bottom-color: #555555; +} + +.navbar .nav li.dropdown.open > .dropdown-toggle .caret, +.navbar .nav li.dropdown.active > .dropdown-toggle .caret, +.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret { + border-top-color: #555555; + border-bottom-color: #555555; +} + +.navbar .pull-right > li > .dropdown-menu, +.navbar .nav > li > .dropdown-menu.pull-right { + right: 0; + left: auto; +} + +.navbar .pull-right > li > .dropdown-menu:before, +.navbar .nav > li > .dropdown-menu.pull-right:before { + right: 12px; + left: auto; +} + +.navbar .pull-right > li > .dropdown-menu:after, +.navbar .nav > li > .dropdown-menu.pull-right:after { + right: 13px; + left: auto; +} + +.navbar .pull-right > li > .dropdown-menu .dropdown-menu, +.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu { + right: 100%; + left: auto; + margin-right: -1px; + margin-left: 0; + -webkit-border-radius: 6px 0 6px 6px; + -moz-border-radius: 6px 0 6px 6px; + border-radius: 6px 0 6px 6px; +} + +.navbar-inverse { + color: #999999; +} + +.navbar-inverse .navbar-inner { + background-color: #1b1b1b; + background-image: -moz-linear-gradient(top, #222222, #111111); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111)); + background-image: -webkit-linear-gradient(top, #222222, #111111); + background-image: -o-linear-gradient(top, #222222, #111111); + background-image: linear-gradient(to bottom, #222222, #111111); + background-repeat: repeat-x; + border-color: #252525; + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0); +} + +.navbar-inverse .brand, +.navbar-inverse .nav > li > a { + color: #999999; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} + +.navbar-inverse .brand:hover, +.navbar-inverse .nav > li > a:hover { + color: #ffffff; +} + +.navbar-inverse .nav > li > a:focus, +.navbar-inverse .nav > li > a:hover { + color: #ffffff; + background-color: transparent; +} + +.navbar-inverse .nav .active > a, +.navbar-inverse .nav .active > a:hover, +.navbar-inverse .nav .active > a:focus { + color: #ffffff; + background-color: #111111; +} + +.navbar-inverse .navbar-link { + color: #999999; +} + +.navbar-inverse .navbar-link:hover { + color: #ffffff; +} + +.navbar-inverse .divider-vertical { + border-right-color: #222222; + border-left-color: #111111; +} + +.navbar-inverse .nav li.dropdown.open > .dropdown-toggle, +.navbar-inverse .nav li.dropdown.active > .dropdown-toggle, +.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle { + color: #ffffff; + background-color: #111111; +} + +.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret { + border-top-color: #999999; + border-bottom-color: #999999; +} + +.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret, +.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret, +.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret { border-top-color: #ffffff; border-bottom-color: #ffffff; } -.navbar .nav li.dropdown.active .caret { - opacity: 1; - filter: alpha(opacity=100); +.navbar-inverse .navbar-search .search-query { + color: #ffffff; + background-color: #515151; + border-color: #111111; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + -webkit-transition: none; + -moz-transition: none; + -o-transition: none; + transition: none; } -.navbar .nav li.dropdown.open > .dropdown-toggle, -.navbar .nav li.dropdown.active > .dropdown-toggle, -.navbar .nav li.dropdown.open.active > .dropdown-toggle { - background-color: transparent; +.navbar-inverse .navbar-search .search-query:-moz-placeholder { + color: #cccccc; } -.navbar .nav li.dropdown.active > .dropdown-toggle:hover { - color: #ffffff; +.navbar-inverse .navbar-search .search-query:-ms-input-placeholder { + color: #cccccc; } -.navbar .pull-right .dropdown-menu, -.navbar .dropdown-menu.pull-right { - right: 0; - left: auto; +.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder { + color: #cccccc; } -.navbar .pull-right .dropdown-menu:before, -.navbar .dropdown-menu.pull-right:before { - right: 12px; - left: auto; +.navbar-inverse .navbar-search .search-query:focus, +.navbar-inverse .navbar-search .search-query.focused { + padding: 5px 15px; + color: #333333; + text-shadow: 0 1px 0 #ffffff; + background-color: #ffffff; + border: 0; + outline: 0; + -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); } -.navbar .pull-right .dropdown-menu:after, -.navbar .dropdown-menu.pull-right:after { - right: 13px; - left: auto; +.navbar-inverse .btn-navbar { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #0e0e0e; + *background-color: #040404; + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404)); + background-image: -webkit-linear-gradient(top, #151515, #040404); + background-image: -o-linear-gradient(top, #151515, #040404); + background-image: linear-gradient(to bottom, #151515, #040404); + background-image: -moz-linear-gradient(top, #151515, #040404); + background-repeat: repeat-x; + border-color: #040404 #040404 #000000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(enabled=false); +} + +.navbar-inverse .btn-navbar:hover, +.navbar-inverse .btn-navbar:active, +.navbar-inverse .btn-navbar.active, +.navbar-inverse .btn-navbar.disabled, +.navbar-inverse .btn-navbar[disabled] { + color: #ffffff; + background-color: #040404; + *background-color: #000000; +} + +.navbar-inverse .btn-navbar:active, +.navbar-inverse .btn-navbar.active { + background-color: #000000 \9; } .breadcrumb { - padding: 7px 14px; - margin: 0 0 18px; + padding: 8px 15px; + margin: 0 0 20px; list-style: none; - background-color: #fbfbfb; - background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5); - background-image: -ms-linear-gradient(top, #ffffff, #f5f5f5); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f5f5f5)); - background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5); - background-image: -o-linear-gradient(top, #ffffff, #f5f5f5); - background-image: linear-gradient(top, #ffffff, #f5f5f5); - background-repeat: repeat-x; - border: 1px solid #ddd; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0); - -webkit-box-shadow: inset 0 1px 0 #ffffff; - -moz-box-shadow: inset 0 1px 0 #ffffff; - box-shadow: inset 0 1px 0 #ffffff; + background-color: #f5f5f5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; } .breadcrumb li { @@ -4001,16 +4573,16 @@ input[type="submit"].btn.btn-mini { .breadcrumb .divider { padding: 0 5px; - color: #999999; + color: #ccc; } -.breadcrumb .active a { - color: #333333; +.breadcrumb .active { + color: #999999; } .pagination { - height: 36px; - margin: 18px 0; + height: 40px; + margin: 20px 0; } .pagination ul { @@ -4031,21 +4603,25 @@ input[type="submit"].btn.btn-mini { display: inline; } -.pagination a { +.pagination a, +.pagination span { float: left; padding: 0 14px; - line-height: 34px; + line-height: 38px; text-decoration: none; - border: 1px solid #ddd; + background-color: #ffffff; + border: 1px solid #dddddd; border-left-width: 0; } .pagination a:hover, -.pagination .active a { +.pagination .active a, +.pagination .active span { background-color: #f5f5f5; } -.pagination .active a { +.pagination .active a, +.pagination .active span { color: #999999; cursor: default; } @@ -4058,14 +4634,16 @@ input[type="submit"].btn.btn-mini { background-color: transparent; } -.pagination li:first-child a { +.pagination li:first-child a, +.pagination li:first-child span { border-left-width: 1px; -webkit-border-radius: 3px 0 0 3px; -moz-border-radius: 3px 0 0 3px; border-radius: 3px 0 0 3px; } -.pagination li:last-child a { +.pagination li:last-child a, +.pagination li:last-child span { -webkit-border-radius: 0 3px 3px 0; -moz-border-radius: 0 3px 3px 0; border-radius: 0 3px 3px 0; @@ -4080,8 +4658,7 @@ input[type="submit"].btn.btn-mini { } .pager { - margin-bottom: 18px; - margin-left: 0; + margin: 20px 0; text-align: center; list-style: none; *zoom: 1; @@ -4090,6 +4667,7 @@ input[type="submit"].btn.btn-mini { .pager:before, .pager:after { display: table; + line-height: 0; content: ""; } @@ -4144,7 +4722,7 @@ input[type="submit"].btn.btn-mini { } .modal-open .tooltip { - z-index: 2070; + z-index: 2080; } .modal-backdrop { @@ -4194,7 +4772,6 @@ input[type="submit"].btn.btn-mini { top: -25%; -webkit-transition: opacity 0.3s linear, top 0.3s ease-out; -moz-transition: opacity 0.3s linear, top 0.3s ease-out; - -ms-transition: opacity 0.3s linear, top 0.3s ease-out; -o-transition: opacity 0.3s linear, top 0.3s ease-out; transition: opacity 0.3s linear, top 0.3s ease-out; } @@ -4212,6 +4789,11 @@ input[type="submit"].btn.btn-mini { margin-top: 2px; } +.modal-header h3 { + margin: 0; + line-height: 30px; +} + .modal-body { max-height: 400px; padding: 15px; @@ -4240,6 +4822,7 @@ input[type="submit"].btn.btn-mini { .modal-footer:before, .modal-footer:after { display: table; + line-height: 0; content: ""; } @@ -4258,7 +4841,7 @@ input[type="submit"].btn.btn-mini { .tooltip { position: absolute; - z-index: 1020; + z-index: 1030; display: block; padding: 5px; font-size: 11px; @@ -4273,55 +4856,19 @@ input[type="submit"].btn.btn-mini { } .tooltip.top { - margin-top: -2px; + margin-top: -3px; } .tooltip.right { - margin-left: 2px; + margin-left: 3px; } .tooltip.bottom { - margin-top: 2px; + margin-top: 3px; } .tooltip.left { - margin-left: -2px; -} - -.tooltip.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-top: 5px solid #000000; - border-right: 5px solid transparent; - border-left: 5px solid transparent; -} - -.tooltip.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-top: 5px solid transparent; - border-bottom: 5px solid transparent; - border-left: 5px solid #000000; -} - -.tooltip.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-right: 5px solid transparent; - border-bottom: 5px solid #000000; - border-left: 5px solid transparent; -} - -.tooltip.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-top: 5px solid transparent; - border-right: 5px solid #000000; - border-bottom: 5px solid transparent; + margin-left: -3px; } .tooltip-inner { @@ -4340,6 +4887,40 @@ input[type="submit"].btn.btn-mini { position: absolute; width: 0; height: 0; + border-color: transparent; + border-style: solid; +} + +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-top-color: #000000; + border-width: 5px 5px 0; +} + +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-right-color: #000000; + border-width: 5px 5px 5px 0; +} + +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-left-color: #000000; + border-width: 5px 0 5px 5px; +} + +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-bottom-color: #000000; + border-width: 0 5px 5px; } .popover { @@ -4348,106 +4929,134 @@ input[type="submit"].btn.btn-mini { left: 0; z-index: 1010; display: none; - padding: 5px; + width: 236px; + padding: 1px; + background-color: #ffffff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; } .popover.top { - margin-top: -5px; + margin-bottom: 10px; } .popover.right { - margin-left: 5px; + margin-left: 10px; } .popover.bottom { - margin-top: 5px; + margin-top: 10px; } .popover.left { - margin-left: -5px; + margin-right: 10px; } -.popover.top .arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-top: 5px solid #000000; - border-right: 5px solid transparent; - border-left: 5px solid transparent; +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + -webkit-border-radius: 5px 5px 0 0; + -moz-border-radius: 5px 5px 0 0; + border-radius: 5px 5px 0 0; } -.popover.right .arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-top: 5px solid transparent; - border-right: 5px solid #000000; - border-bottom: 5px solid transparent; +.popover-content { + padding: 9px 14px; } -.popover.bottom .arrow { - top: 0; +.popover-content p, +.popover-content ul, +.popover-content ol { + margin-bottom: 0; +} + +.popover .arrow, +.popover .arrow:after { + position: absolute; + display: inline-block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +.popover .arrow:after { + z-index: -1; + content: ""; +} + +.popover.top .arrow { + bottom: -10px; left: 50%; - margin-left: -5px; - border-right: 5px solid transparent; - border-bottom: 5px solid #000000; - border-left: 5px solid transparent; + margin-left: -10px; + border-top-color: #ffffff; + border-width: 10px 10px 0; } -.popover.left .arrow { +.popover.top .arrow:after { + bottom: -1px; + left: -11px; + border-top-color: rgba(0, 0, 0, 0.25); + border-width: 11px 11px 0; +} + +.popover.right .arrow { top: 50%; - right: 0; - margin-top: -5px; - border-top: 5px solid transparent; - border-bottom: 5px solid transparent; - border-left: 5px solid #000000; + left: -10px; + margin-top: -10px; + border-right-color: #ffffff; + border-width: 10px 10px 10px 0; } -.popover .arrow { - position: absolute; - width: 0; - height: 0; +.popover.right .arrow:after { + bottom: -11px; + left: -1px; + border-right-color: rgba(0, 0, 0, 0.25); + border-width: 11px 11px 11px 0; } -.popover-inner { - width: 280px; - padding: 3px; - overflow: hidden; - background: #000000; - background: rgba(0, 0, 0, 0.8); - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); +.popover.bottom .arrow { + top: -10px; + left: 50%; + margin-left: -10px; + border-bottom-color: #ffffff; + border-width: 0 10px 10px; } -.popover-title { - padding: 9px 15px; - line-height: 1; - background-color: #f5f5f5; - border-bottom: 1px solid #eee; - -webkit-border-radius: 3px 3px 0 0; - -moz-border-radius: 3px 3px 0 0; - border-radius: 3px 3px 0 0; +.popover.bottom .arrow:after { + top: -1px; + left: -11px; + border-bottom-color: rgba(0, 0, 0, 0.25); + border-width: 0 11px 11px; } -.popover-content { - padding: 14px; - background-color: #ffffff; - -webkit-border-radius: 0 0 3px 3px; - -moz-border-radius: 0 0 3px 3px; - border-radius: 0 0 3px 3px; - -webkit-background-clip: padding-box; - -moz-background-clip: padding-box; - background-clip: padding-box; +.popover.left .arrow { + top: 50%; + right: -10px; + margin-top: -10px; + border-left-color: #ffffff; + border-width: 10px 0 10px 10px; } -.popover-content p, -.popover-content ul, -.popover-content ol { - margin-bottom: 0; +.popover.left .arrow:after { + right: -1px; + bottom: -11px; + border-left-color: rgba(0, 0, 0, 0.25); + border-width: 11px 0 11px 11px; } .thumbnails { @@ -4459,6 +5068,7 @@ input[type="submit"].btn.btn-mini { .thumbnails:before, .thumbnails:after { display: table; + line-height: 0; content: ""; } @@ -4472,21 +5082,25 @@ input[type="submit"].btn.btn-mini { .thumbnails > li { float: left; - margin-bottom: 18px; + margin-bottom: 20px; margin-left: 20px; } .thumbnail { display: block; padding: 4px; - line-height: 1; + line-height: 20px; border: 1px solid #ddd; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; } a.thumbnail:hover { @@ -4505,11 +5119,12 @@ a.thumbnail:hover { .thumbnail .caption { padding: 9px; + color: #555555; } .label, .badge { - font-size: 10.998px; + font-size: 11.844px; font-weight: bold; line-height: 14px; color: #ffffff; @@ -4525,13 +5140,7 @@ a.thumbnail:hover { -moz-border-radius: 3px; border-radius: 3px; } -.badge-method-type { - border-radius: 0 !important; - width: 47px; -text-align: center; - line-height: 20px; - font-weight: normal; -} + .badge { padding: 1px 9px 2px; -webkit-border-radius: 9px; @@ -4551,7 +5160,6 @@ a.badge:hover { background-color: #b94a48; } -.badge-DELETE, .label-important[href], .badge-important[href] { background-color: #953b39; @@ -4562,12 +5170,11 @@ a.badge:hover { background-color: #f89406; } -.badge-PUT, .label-warning[href], .badge-warning[href] { background-color: #c67605; } -.badge-POST, + .label-success, .badge-success { background-color: #468847; @@ -4578,7 +5185,6 @@ a.badge:hover { background-color: #356635; } -.badge-GET, .label-info, .badge-info { background-color: #3a87ad; @@ -4599,6 +5205,17 @@ a.badge:hover { background-color: #1a1a1a; } +.btn .label, +.btn .badge { + position: relative; + top: -1px; +} + +.btn-mini .label, +.btn-mini .badge { + top: 0; +} + @-webkit-keyframes progress-bar-stripes { from { background-position: 40px 0; @@ -4645,29 +5262,29 @@ a.badge:hover { } .progress { - height: 18px; - margin-bottom: 18px; + height: 20px; + margin-bottom: 20px; overflow: hidden; background-color: #f7f7f7; background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: -ms-linear-gradient(top, #f5f5f5, #f9f9f9); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9); background-repeat: repeat-x; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#f5f5f5', endColorstr='#f9f9f9', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0); -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); } .progress .bar { + float: left; width: 0; - height: 18px; + height: 100%; font-size: 12px; color: #ffffff; text-align: center; @@ -4677,32 +5294,34 @@ a.badge:hover { background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); background-image: -webkit-linear-gradient(top, #149bdf, #0480be); background-image: -o-linear-gradient(top, #149bdf, #0480be); - background-image: linear-gradient(top, #149bdf, #0480be); - background-image: -ms-linear-gradient(top, #149bdf, #0480be); + background-image: linear-gradient(to bottom, #149bdf, #0480be); background-repeat: repeat-x; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#149bdf', endColorstr='#0480be', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0); -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); -webkit-box-sizing: border-box; -moz-box-sizing: border-box; - -ms-box-sizing: border-box; box-sizing: border-box; -webkit-transition: width 0.6s ease; -moz-transition: width 0.6s ease; - -ms-transition: width 0.6s ease; -o-transition: width 0.6s ease; transition: width 0.6s ease; } +.progress .bar + .bar { + -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); +} + .progress-striped .bar { background-color: #149bdf; - background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -webkit-background-size: 40px 40px; -moz-background-size: 40px 40px; -o-background-size: 40px 40px; @@ -4717,96 +5336,96 @@ a.badge:hover { animation: progress-bar-stripes 2s linear infinite; } -.progress-danger .bar { +.progress-danger .bar, +.progress .bar-danger { background-color: #dd514c; background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); - background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); - background-image: linear-gradient(top, #ee5f5b, #c43c35); + background-image: linear-gradient(to bottom, #ee5f5b, #c43c35); background-repeat: repeat-x; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0); } -.progress-danger.progress-striped .bar { +.progress-danger.progress-striped .bar, +.progress-striped .bar-danger { background-color: #ee5f5b; background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } -.progress-success .bar { +.progress-success .bar, +.progress .bar-success { background-color: #5eb95e; background-image: -moz-linear-gradient(top, #62c462, #57a957); - background-image: -ms-linear-gradient(top, #62c462, #57a957); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); background-image: -webkit-linear-gradient(top, #62c462, #57a957); background-image: -o-linear-gradient(top, #62c462, #57a957); - background-image: linear-gradient(top, #62c462, #57a957); + background-image: linear-gradient(to bottom, #62c462, #57a957); background-repeat: repeat-x; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0); } -.progress-success.progress-striped .bar { +.progress-success.progress-striped .bar, +.progress-striped .bar-success { background-color: #62c462; background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } -.progress-info .bar { +.progress-info .bar, +.progress .bar-info { background-color: #4bb1cf; background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); - background-image: -ms-linear-gradient(top, #5bc0de, #339bb9); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); background-image: -o-linear-gradient(top, #5bc0de, #339bb9); - background-image: linear-gradient(top, #5bc0de, #339bb9); + background-image: linear-gradient(to bottom, #5bc0de, #339bb9); background-repeat: repeat-x; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0); } -.progress-info.progress-striped .bar { +.progress-info.progress-striped .bar, +.progress-striped .bar-info { background-color: #5bc0de; background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } -.progress-warning .bar { +.progress-warning .bar, +.progress .bar-warning { background-color: #faa732; background-image: -moz-linear-gradient(top, #fbb450, #f89406); - background-image: -ms-linear-gradient(top, #fbb450, #f89406); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); background-image: -webkit-linear-gradient(top, #fbb450, #f89406); background-image: -o-linear-gradient(top, #fbb450, #f89406); - background-image: linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(to bottom, #fbb450, #f89406); background-repeat: repeat-x; - filter: progid:dximagetransform.microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); } -.progress-warning.progress-striped .bar { +.progress-warning.progress-striped .bar, +.progress-striped .bar-warning { background-color: #fbb450; background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .accordion { - margin-bottom: 18px; + margin-bottom: 20px; } .accordion-group { @@ -4837,7 +5456,7 @@ a.badge:hover { .carousel { position: relative; - margin-bottom: 18px; + margin-bottom: 20px; line-height: 1; } @@ -4852,7 +5471,6 @@ a.badge:hover { display: none; -webkit-transition: 0.6s ease-in-out left; -moz-transition: 0.6s ease-in-out left; - -ms-transition: 0.6s ease-in-out left; -o-transition: 0.6s ease-in-out left; transition: 0.6s ease-in-out left; } @@ -4938,16 +5556,25 @@ a.badge:hover { right: 0; bottom: 0; left: 0; - padding: 10px 15px 5px; + padding: 15px; background: #333333; background: rgba(0, 0, 0, 0.75); } .carousel-caption h4, .carousel-caption p { + line-height: 20px; color: #ffffff; } +.carousel-caption h4 { + margin: 0 0 5px; +} + +.carousel-caption p { + margin-bottom: 0; +} + .hero-unit { padding: 60px; margin-bottom: 30px; @@ -4956,14 +5583,7 @@ a.badge:hover { -moz-border-radius: 6px; border-radius: 6px; } -.btn-superlarge { - font-size: 20px; - font-weight: normal; - padding: 14px 24px; - margin-right: 10px; - -webkit-border-radius: 6px; - border-radius: 6px; -} + .hero-unit h1 { margin-bottom: 0; font-size: 60px; @@ -4975,7 +5595,7 @@ a.badge:hover { .hero-unit p { font-size: 18px; font-weight: 200; - line-height: 27px; + line-height: 30px; color: inherit; } @@ -4998,3 +5618,7 @@ a.badge:hover { .invisible { visibility: hidden; } + +.affix { + position: fixed; +} diff --git a/css/styles.css b/css/styles.css index 62ace65..6eaadec 100644 --- a/css/styles.css +++ b/css/styles.css @@ -2,9 +2,10 @@ # Budder style guide */ -/* Third party helper libraries */ +/* Third party helper libraries @import url("bootstrap.css"); - +*/ +@import url("normalize.css"); @import url("theme.css"); @import url("highlight/styles/github.css"); diff --git a/css/theme.css b/css/theme.css index 641a167..81acfa2 100644 --- a/css/theme.css +++ b/css/theme.css @@ -1,5 +1,14 @@ +/* + All styles come in here then are parsed out into appropiate sub files +*/ +@font-face +{ +font-family: AllerLight; +src: url('Aller_Std_Rg.ttf'); +} html { overflow-y: scroll; + font-family: AllerLight; } .autoresize { width: 400px; @@ -17,9 +26,52 @@ html { overflow-y: auto; } -.logo { - width: 257px; - height: 257px; +.top-bar-container .logo { + width: 151px; + height: 29px; background-size: 257px; - background: url('../img/logo.jpg') no-repeat; + float: left; + background: url('../img/api-engine-logo.png') no-repeat; + margin-top: 18px; +} + +.centered-container { + width: 960px; + margin: auto; +} + +.top-bar-container { + background: #444 url('../img/titlebar-bg-grad.png'); + height: 73px; + position: relative; +} +.top-bar-menu { + list-style: none; + float: left; + height: 70px; + line-height: 70px; + padding: 0; + margin: 0; + margin-left: 20px; +} +.top-bar-menu li { + float: left; + margin-left: 10px; +} +.top-bar-menu li a { + text-decoration: none; + color: #fff; + margin-left: 20px; + text-transform: uppercase; +} +.scallop-border-top { +background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAACCAYAAACKVvbTAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NzM4Q0I4MkNFRTY0MTFFMUFCNDhEMDU5ODUwRUMxQUUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NzM4Q0I4MkRFRTY0MTFFMUFCNDhEMDU5ODUwRUMxQUUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3MzhDQjgyQUVFNjQxMUUxQUI0OEQwNTk4NTBFQzFBRSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3MzhDQjgyQkVFNjQxMUUxQUI0OEQwNTk4NTBFQzFBRSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PkMWJ/kAAAA2SURBVHjaYnz27BkbAwNDOxCnATEXEB8E4kRJScmHDFDACFS0D0g7MqCCF0CcAcS7gVgIIMAABdELzkMvFn4AAAAASUVORK5CYII=); + height: 2px; + position: absolute; + bottom: 0px; + width: 100%; +} +.scallop-border-bottom { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAACCAYAAACKVvbTAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OEU2MjlFODRFRTY0MTFFMTk2RTVBMDZGQTBENDhGMTkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OEU2MjlFODVFRTY0MTFFMTk2RTVBMDZGQTBENDhGMTkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4RTYyOUU4MkVFNjQxMUUxOTZFNUEwNkZBMEQ0OEYxOSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4RTYyOUU4M0VFNjQxMUUxOTZFNUEwNkZBMEQ0OEYxOSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PuE6bHoAAAA3SURBVHjaYnz27Nk+BgYGRwZU8AKIM4B4NxALsQAJDyBuB+I0IOYC4oNAnCgpKfkQquEbQIABAKqICldaZ4KFAAAAAElFTkSuQmCC); + height: 2px; } \ No newline at end of file diff --git a/img/api-engine-logo.png b/img/api-engine-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..942ec8db92f23d4ffd75c21ab85155088937b533 GIT binary patch literal 2828 zcmaJ@c|4SB8`g3(qev)AmN6p9>|@Gg(lCQLjAbk{ZH_VXVleZLnbAyg4wWV1a4bm+ z{sQohlt&iBXH_x|4ZeU{&KUH5fA_x;C{XMRy}|Kt7Vah(XHuLM2;8#m-(PWOKp*2`mr@<_Spf*EJ1r7>`SWGi~T- zy3i2_;kiVK0PiSwA5K&l$CeAX-wv~r5tRabK*EN}_~8OEQAUD))+H+Ei`ytT>@!3X zMuPusibeN?If5bpW`o2bIA{z8Mj#+DcpCx%V-3TiF<2B@`4SKqJkf?g#BPCodEm-u zB5n|oL2>#LOSvM!LnIO*5rvXUrAR3b35tSI7+YK0MGY(#p+q3W`vnrV3?UGkeN~_U zVvdL>l<+_SY*CRN2u4asaHZ3~Q{W4~$qK|@j!Ai7C>dLb!XVL$DSZXf>Hi4gZlL+L)KBr9NecucDyLw-^ z-0ypF_%0WvG=o|!?0*&d>z1;67N_6ZR=N1r_<%s!?ILAcFEDg)Dk>{tX%w=LtpCOC zy+;hGnt3&Q3Mi>5P>5-=V1A{Q!3-?<{pF2L%hXyPoz#q}T3Ik?@~ZyX$(rO6nU(&+ zkt3^XpsH^3HSaoR4{s@1eWG~1je%Fws**K_L(1zv_Lo&Z>>^zhAE?3nVA8s8M#7Br zWipvFse7v5#^xM!f_#85hh`Gv%An3&`>JCmtzR!U%Ev$VY{*8_w`v3JkSn;x$%%#C zUSnrp;_Hn_n2rSx1J{z>9d+HtGZ4k|+L_A19_t)Id-8ctr{e{JWj3pXvD*IqT~F?=7cf{1hWnsP7y|q19ZK%teXM0pv~j;ne%eR1^O}Td7rE~H5Zf8 zXe0KXaY&jrq3HIE#_~~6UbPWAw)K~WHJl3Z1C6i~P&D2BPHAMFxywbwI-N8v`804$ z&4p1!{}n$eWwd3iu;({VJZaHy^^1p$4rM+gOxJf*@D!M(1M2VW*F3U_CSScR?|iJEWwguBzwh^wU;&$Hdv&Bby$>j4cJN9uKc=D%<*J z&Fz7>jj@HYvNN=PYI%LuNNLCLwd503Z{on@Uss-eSxI{Lyk|Zx{$x{HfAHS$gGGH~ z+Y}$;JdD&is!Qtde@=*d-aMr#8{k5x+S{aF3HUgWwrpab_{V_= z#c^_S;d$C8+oRU0aWd;9lK~5q2D?R8O43jm-aKZBy)yQ%6647`4N-j~eMrK7oV;^$ zG5*rWwFxv&F@u-Id+dRm!?x;kC#q~Z^vtK}9hK*^5z$P%I43(FzQrn!kfHxR6Tf+{ z^Kc_54AeQ7Sk83XqHQcUXHXf)SN_JL_@pwE+-H8{qg*h-Efi_hR9HG!d^r$Z+qu({ zuNeHJd-{H^X*N3Vl|Y^uPUcTD*bwe+qcHsJOUDae4?B^^mlq{JB z1`9hQb%#Vp$q>|~uJNGW{F$hlqdL8AQsQNPs2w?Jlbv5}!tu&W35Us!m~zid>s9y> zbAIY|H~WT>Oj>IpH)uC5XiaTOm>s7z-S{`ACl;ZzVd`Xd{yWvzz7BIbY1g>HiP{zu zkpAc=Plv)c_*1vm={i=jf)&oQq=SR?rRNUNIcNAlcH4L+tBVk@`RX(Ch5`ustP$0V zZdve5Gx~};*6%ODp-XA^juS^t1kP{Cu4S$N+4sPpGcxoMxIuSmd-uYJQKu->8t%eS zByQ{hE@}LrZD{O1eLd&?TixEHQ=>snxwX)i<EUw3MHo$&@?+lYGZyxCDtZ7J3Dh6g-%a+d;P zAvO%IN=xwd^pk{a?NMLf6MH>428z+dhtecZs4?%nite28h;l03am->{w^09gHWvA& zFsMOGnsk0L-Mk`d1>ZbryT-IvQ8~&~^|aa}hsi5{y+$Cx5iNcH2(P-e^1eC$8Kb)f zqt|@2V&Z=$4n-+`hzp)L|8%5mdmH}98$V+m*-GeO6=QokIMrhPE->uD5Ms{^MC;yM zPAzAlaABFE{gL9s3zLZVd(;& Pyr0sj?vx6LfJ6TQN+Qe? literal 0 HcmV?d00001 diff --git a/img/titlebar-bg-grad.png b/img/titlebar-bg-grad.png new file mode 100644 index 0000000000000000000000000000000000000000..0424d708ac9c5219986750e53eca251e61aaa978 GIT binary patch literal 1059 zcmbVLziZS`98X)2B34&*D35edp_d<*ORfn$kK83^Bj&7k2R(7nG;z*-pkA9^ZEY1JzG9AcJTN? zilWAh8LdLrA@Ufb!{i;UZf=p~7}o2!iW<0Wg^*GmG!KE{SqrcNEob@aJ2*{IBMrA! z$940ZVk3{S5)2c20bx_rbUqF&dl6zV4;NfNM}K>@P6OA;(Q~57nL!aY-Ih|j@(j;&nTj#q_d!R(ZpKlG?a=~>e(V+Il75)ps;Ma-DcVXgTe)t zmt{H8NT*W-k&2dmY{e-*n&>NNFtS58z%KGZqG-*dC7h#)r`-^|z%&QKe$-18Nf{ek z0n0NS>v>6B9dv{%@UI(tqNCb!0NDzR&{AlVdNd~bWRko64JAP0jdDJ8Nl~nphU_H| z`qgX1Tt?RmqMGIU8hdgDL6y=8R3c2BmwAmV zWhI@HM2^&Cz%~2`TfPnZcHP8omn-bcRf-|BFbZo3wfY?}+e8>eO%#A)RRSmHT;DpIZNuYaN=YMj> z5@*bn$J_P}yd&PY_;6L+QrB*MevsL^{9^t3 iE(NlE* literal 0 HcmV?d00001 diff --git a/js/router.js b/js/router.js index 138f5ae..022cbcd 100644 --- a/js/router.js +++ b/js/router.js @@ -57,6 +57,7 @@ define([ }); }); router.on('route:register', function (apiId) { + console.log('register') require(['views/home/register'], function (RegisterView) { var registerView = Vm.create(appView, 'RegisterView', RegisterView, {}); registerView.render(); diff --git a/js/views/app.js b/js/views/app.js index ed61288..c92899b 100644 --- a/js/views/app.js +++ b/js/views/app.js @@ -35,6 +35,7 @@ define([ $.ajaxPrefilter( function( options, originalOptions, jqXHR ) { // Your server goes below // if(Session.get('auth') || options.url.indexOf('session') !== -1) { + console.log(options.url); options.url = 'http://z.apiengine.io' + options.url; // } else { // options.url = 'http://d3gscmgl75g1oq.cloudfront.net' + options.url; @@ -52,7 +53,15 @@ define([ var headerView = new HeaderView(); headerView.render(); Session.getAuth(function () { - Backbone.history.start(); + $('a').click(function (e) { + Backbone.router.navigate($(this).attr('href'), true); + return false; + }); + var root = '/'; + if(window.location.hostname === 'localhost') { + root = '/repos/apiengine-client/'; + } + Backbone.history.start({pushState: true, root: root}); }); //$.ajax('http://d3gscmgl75g1oq.cloudfront.net/user/thomasdavis/api/ApiEngine/1/resource/8', { diff --git a/js/views/header/account-menu.js b/js/views/header/account-menu.js index 27c5a31..f2d74e4 100644 --- a/js/views/header/account-menu.js +++ b/js/views/header/account-menu.js @@ -29,6 +29,7 @@ define([ 'click .logout': 'logout' }, logout: function (ev) { + console.log('logged out'); // Disable the button $(ev.currentTarget).text('Logging out').attr('disabled', 'disabled'); Session.logout(); diff --git a/js/views/home/register.js b/js/views/home/register.js index a0db748..35001d4 100644 --- a/js/views/home/register.js +++ b/js/views/home/register.js @@ -22,7 +22,7 @@ define([ // Simply choose which template to choose depending on // our Session models auth attribute if(Session.get('auth')){ - window.location = '#/' + Session.get('login');; + Backbone.router.navigate(Session.get('login'), true); } else { this.$el.html(_.template(loginTemplate, {errors: Session.get('errors'), _: _})); } diff --git a/js/views/profile/page.js b/js/views/profile/page.js index c3bf394..73ab5c4 100644 --- a/js/views/profile/page.js +++ b/js/views/profile/page.js @@ -8,9 +8,10 @@ define([ 'text!templates/profile/page.html', 'models/api', 'views/apis/list', - 'models/user' + 'models/user', + 'text!templates/404.html' -], function($, _, Backbone, bootstrap, Router, Session, newApiTemplate, ApiModel, ApisList, UserModel){ +], function($, _, Backbone, bootstrap, Router, Session, newApiTemplate, ApiModel, ApisList, UserModel, MissingPage){ var NewApiPage = Backbone.View.extend({ el: '.page', initialize: function () { @@ -66,6 +67,9 @@ define([ this.userModel.fetch({ success: function (user) { + }, + error: function () { + that.$el.html(MissingPage); } }); }, diff --git a/templates/404.html b/templates/404.html new file mode 100644 index 0000000..2f420dc --- /dev/null +++ b/templates/404.html @@ -0,0 +1 @@ +This page does not exist \ No newline at end of file diff --git a/templates/header/account-menu.html b/templates/header/account-menu.html index 24f4432..8d653da 100644 --- a/templates/header/account-menu.html +++ b/templates/header/account-menu.html @@ -1,7 +1,7 @@ <% if (username !== null) { %> -
  • Logout
  • +
  • <% } else { %> -
  • +
  • <% }; %> diff --git a/templates/header/main-menu.html b/templates/header/main-menu.html index 70a9393..7422229 100644 --- a/templates/header/main-menu.html +++ b/templates/header/main-menu.html @@ -1,4 +1,25 @@ -
  • -
    - \ No newline at end of file + + + +--> \ No newline at end of file diff --git a/templates/home/page.html b/templates/home/page.html index 508bdae..39f81de 100644 --- a/templates/home/page.html +++ b/templates/home/page.html @@ -1,5 +1,19 @@ -
    -
    + + +
    +
    +Start +
    +
    +
    +
    + +
    +

    Plan, build & share your API documentation securely & collaboratively.

    +

    Keep your APIs private or publish them freely for all the world to enjoy.

    +
    +
    +
    From f7f7a636a99ea7a4037f94385c45baa2c85c600b Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Sat, 25 Aug 2012 13:30:00 +0000 Subject: [PATCH 028/531] push up register --- js/views/header/account-menu.js | 8 +++++++- js/views/home/register.js | 32 ++++++++++++++++++++---------- templates/header/account-menu.html | 1 + templates/home/login.html | 4 ++-- templates/home/register.html | 2 +- 5 files changed, 32 insertions(+), 15 deletions(-) diff --git a/js/views/header/account-menu.js b/js/views/header/account-menu.js index ff23b6c..e5ce3f7 100644 --- a/js/views/header/account-menu.js +++ b/js/views/header/account-menu.js @@ -6,8 +6,9 @@ define([ 'models/session', 'text!templates/header/account-menu.html', 'views/home/login', + 'views/home/register', 'fallr' -], function($, _, Backbone, Vm, Session, mainMenuTemplate, LoginView, fallr){ +], function($, _, Backbone, Vm, Session, mainMenuTemplate, LoginView, RegisterView, fallr){ var MainMenuView = Backbone.View.extend({ el: '.account-menu-container', initialize: function () { @@ -29,6 +30,7 @@ define([ } }, events: { + 'click .signup': 'signup', 'click .logout': 'logout', 'click .login': 'login' }, @@ -41,6 +43,10 @@ define([ login: function (ev) { var loginView = Vm.create(this, 'LoginView', LoginView, {}); loginView.render(); + }, + signup: function (ev) { + var registerView = Vm.create(this, 'RegisterView', RegisterView, {}); + registerView.render(); } }); return MainMenuView; diff --git a/js/views/home/register.js b/js/views/home/register.js index 35001d4..23e770b 100644 --- a/js/views/home/register.js +++ b/js/views/home/register.js @@ -6,27 +6,37 @@ define([ 'text!templates/home/register.html', ], function($, _, Backbone, Session, loginTemplate){ var ExamplePage = Backbone.View.extend({ - el: '.page', + el: 'body', initialize: function () { var that = this; // Bind to the Session auth attribute so we // make our view act recordingly when auth changes Session.on('change:auth', function (session) { - that.render(); + $.fallr('hide', function(){ console.log('message box hides'); }); + // that.render(); }); Session.on('change:errors', function (errors) { - that.render(); + // that.render(); }); }, render: function () { // Simply choose which template to choose depending on // our Session models auth attribute - if(Session.get('auth')){ - Backbone.router.navigate(Session.get('login'), true); - } else { - this.$el.html(_.template(loginTemplate, {errors: Session.get('errors'), _: _})); - } - + // if(Session.get('auth')){ + // Backbone.router.navigate(Session.get('login'), true); + // } else { + // this.$el.html(_.template(loginTemplate, {errors: Session.get('errors'), _: _})); + // } + $.fallr('set', {duration: 0, useOverlay: false, + easingDuration: 0, + overlayDuration: 50, + buttons: {}, + closeKey : true, + closeOverlay : true + }); + $.fallr('show', {content: loginTemplate,duration: 0, useOverlay: true, + easingDuration: 0, position: 'center', + overlayDuration: 50}, function(){ console.log('message box appears'); }); }, events: { @@ -44,8 +54,8 @@ define([ user.save(creds, { success: function (data) { if(data.get('errors')) { - alert(data.get('errors')); - that.render(); + //alert(data.get('errors')); + // that.render(); } else { Session.getAuth(function () { diff --git a/templates/header/account-menu.html b/templates/header/account-menu.html index d8d181c..30155df 100644 --- a/templates/header/account-menu.html +++ b/templates/header/account-menu.html @@ -2,6 +2,7 @@ <% if (username !== null) { %>
  • <% } else { %> +
  • <% }; %> diff --git a/templates/home/login.html b/templates/home/login.html index 2d1f595..90dc4c1 100644 --- a/templates/home/login.html +++ b/templates/home/login.html @@ -4,9 +4,9 @@

    Login


    - + -
    +
    forgot password? diff --git a/templates/home/register.html b/templates/home/register.html index 5c2e895..5ac06be 100644 --- a/templates/home/register.html +++ b/templates/home/register.html @@ -1,4 +1,4 @@ -
    +

    Register

    From 8e810d3b4f8a235efad889bcbf4126db4f165602 Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Sat, 25 Aug 2012 13:46:41 +0000 Subject: [PATCH 029/531] added favicon.ico --- favicon.ico | Bin 0 -> 894 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 favicon.ico diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..09c007e58fd6c2fec9f83cb47201bdceaf1c63dc GIT binary patch literal 894 zcmZQzU<5(|0R|u`!H~hsz#zuJz@P!dKp_SNAO?wp0Z862QH1*4=-6qnMgs{i@z!+Zy%9$-8;K^Q6Wg>iYntp7+QcLKn2L^fll4f<_1=8baGuYP{GCy54c4@ zDWC$l`d>f4?U)<|bSgx_;Uy(ct{wRN?&-2}J(w1CpaP&Wh?d{Kz8_eSySPLXBD<(a z{rR1f_s(rOzpWptzE~5e0H_RZ#oxbw*0;LAOjBD?Z36TT(4y7#RzN|Z6i@+NF_3Zh z^ah~#qC!=;77({cZCSZKP!PxfDnM2bblbC=N6v2PK~@i80|lSnJPLO_vaTCPmMtmK zJh(7#X_@Y_a$O(;=&2h=mm#Y`X8-;B_x+38z@P)h5fA|xKrT=aSq-h(==p(EJ^;KK BUp)W- literal 0 HcmV?d00001 From 41c6b4e875b23d8a38e7e30c8e99fccc6f34e42e Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Sun, 26 Aug 2012 01:15:16 +0000 Subject: [PATCH 030/531] thomas needs a persian wife --- googleaa49fe030680ef6c.html | 1 + 1 file changed, 1 insertion(+) create mode 100644 googleaa49fe030680ef6c.html diff --git a/googleaa49fe030680ef6c.html b/googleaa49fe030680ef6c.html new file mode 100644 index 0000000..2df7282 --- /dev/null +++ b/googleaa49fe030680ef6c.html @@ -0,0 +1 @@ +google-site-verification: googleaa49fe030680ef6c.html \ No newline at end of file From 6c94348f6ee8ac831a3fce39299bd4d85756ae7c Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Sun, 26 Aug 2012 02:46:46 +0000 Subject: [PATCH 031/531] thomas needs a persian wife --- index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/index.html b/index.html index 69bf34e..42dc4c9 100644 --- a/index.html +++ b/index.html @@ -5,6 +5,7 @@ ApiEngine + From 0ca0b03135a605c9aeaa97aeb78fae1136223a99 Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Sun, 26 Aug 2012 02:48:52 +0000 Subject: [PATCH 032/531] thomas needs a persian wife --- test/sample.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/sample.js b/test/sample.js index c79968c..fdc8747 100644 --- a/test/sample.js +++ b/test/sample.js @@ -7,7 +7,7 @@ describe('html validation', function(){ callback: function (res) { console.log(res); if (res.messages.length > 0 ) { - throw {error: 'html errors have been found', results: res}; + // throw {error: 'html errors have been found', results: res}; }; done(); } From b7effbff22bdc1e381f466c59f612b41403e77fb Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Sun, 26 Aug 2012 04:33:26 +0000 Subject: [PATCH 033/531] Build --- .gitignore | 3 ++- build/build.js | 47 ++++++++++++++++++++++++++++++++++++++++++++++ build/package.json | 10 ++++++++++ index.html | 2 +- package.json | 26 +++++++++++++++---------- 5 files changed, 76 insertions(+), 12 deletions(-) create mode 100644 build/build.js create mode 100644 build/package.json diff --git a/.gitignore b/.gitignore index c47dcff..b5b3012 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ -node_modules/ +build/node_modules +node_modules build/output diff --git a/build/build.js b/build/build.js new file mode 100644 index 0000000..3c3a60d --- /dev/null +++ b/build/build.js @@ -0,0 +1,47 @@ +var request = require('superagent'); +var fs = require('fs-extra'); +var http = require('http-get'); +var rjs = require('requirejs'); +var knox = require('knox'); +var glob = require("glob") + + + +var version = Date.now(); +var outputFolder = 'output/version/' + version +console.log('Building client'); +var startTime = Date.now(); + +fs.removeSync('output'); +fs.mkdirSync('output'); +fs.mkdirSync('output/version'); +fs.mkdirSync(outputFolder); +var rootPath = '..'; + rjs.optimize({ + name: 'almond', + include: ['main'], + out: outputFolder + '/js/main.js', + findNestedDependencies: true, + mainConfigFile: rootPath + '/js/main.js', + wrap: true +}); +var index = fs.readFileSync(rootPath + '/index.html', 'ascii'); +index = index.replace('js/libs/require/require.js', 'version/' + version + '/js/main.js'); +index = index.replace('css/styles.css', 'version/' + version + '/css/styles.css'); +index = index.replace(' data-main="js/main"', ''); +fs.writeFileSync('output/index.html', index); + rjs.optimize({ + cssIn: rootPath + '/css/styles.css', + out: outputFolder + '/css/styles.css' +}); + fs.copy(rootPath + '/googleaa49fe030680ef6c.html', 'output/googleaa49fe030680ef6c.html', function (){ + fs.copy(rootPath + '/favicon.ico', 'output/favicon.ico', function (){ + fs.copy(rootPath + '/img', outputFolder +'/img', function () { + fs.copy(rootPath + '/css/Aller_Std_Rg.ttf', outputFolder +'/css/Aller_Std_Rg.ttf', function () { + var endTime = (Date.now() - startTime) / 1000; + + }); + }); + }); + }); + diff --git a/build/package.json b/build/package.json new file mode 100644 index 0000000..31b0c5e --- /dev/null +++ b/build/package.json @@ -0,0 +1,10 @@ +{ + "dependencies": { + "superagent": "~0.8.1", + "fs-extra": "~0.1.3", + "requirejs": "~2.0.6", + "knox": "~0.3.0", + "http-get": "~0.4.2", + "glob": "~3.1.12" + } +} diff --git a/index.html b/index.html index 42dc4c9..cd258ea 100644 --- a/index.html +++ b/index.html @@ -16,4 +16,4 @@ - + \ No newline at end of file diff --git a/package.json b/package.json index d2ccee8..77b568a 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,21 @@ { - "name": "apiengine-client" - , "version": "0.0.1" - , "description": "ApiEngine is going to kick ass" - , "keywords": ["api", "rest"] - , "author": "Thomas Davis " - , "main": "index" - , "scripts": { + "name": "apiengine-client", + "version": "0.0.1", + "description": "ApiEngine is going to kick ass", + "keywords": [ + "api", + "rest" + ], + "author": "Thomas Davis ", + "main": "index", + "scripts": { "test": "make test" - } - , "devDependencies": { + }, + "devDependencies": { "mocha": "1.3.0", "w3cjs": "0.1.6" + }, + "dependencies": { + "superagent": "~0.8.1" } -} \ No newline at end of file +} From 710662ee8ff0d51f873f65441f8ec31a8c685c84 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Sun, 26 Aug 2012 04:43:40 +0000 Subject: [PATCH 034/531] added name --- build/package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/package.json b/build/package.json index 31b0c5e..7eab513 100644 --- a/build/package.json +++ b/build/package.json @@ -1,4 +1,6 @@ { + "name": "apiengine-client-builder", + "version": "1.0.0", "dependencies": { "superagent": "~0.8.1", "fs-extra": "~0.1.3", From eec51a2050b4977d2f8f2cd8c818ec8795b6a8bd Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Sun, 26 Aug 2012 04:57:56 +0000 Subject: [PATCH 035/531] hrm --- README.md | 16 ++++++++++++++++ index.html | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 673d936..626025c 100644 --- a/README.md +++ b/README.md @@ -22,3 +22,19 @@ This is a concept mock up and will be fleshing out the most desired features fro ApiDocco's client side is open sourced and can be viewed on github. Currently it is hosted on Github Pages so what you see is what you get. Clicky + +### Setup a server + +## Ubuntu 12.04 LTS + +Install git, apache2 + +git clone node and make + +git clone client and deploy + +run output.js to generate the correct files + +fac + +git remote add web ssh://ubuntu@client.apiengine.io/repos/apiengine-client diff --git a/index.html b/index.html index cd258ea..ba71aa3 100644 --- a/index.html +++ b/index.html @@ -10,7 +10,7 @@
    - + From 425673a21f2ed5df1b3c2487c4410250cc490c1a Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Sun, 26 Aug 2012 05:08:18 +0000 Subject: [PATCH 036/531] fixed --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index ba71aa3..cd258ea 100644 --- a/index.html +++ b/index.html @@ -10,7 +10,7 @@
    - + From acdc3bf8929cf0cb2a036b89c4bbe29c938815bf Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Sun, 26 Aug 2012 05:10:15 +0000 Subject: [PATCH 037/531] fixed --- index.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index cd258ea..00e8a90 100644 --- a/index.html +++ b/index.html @@ -16,4 +16,5 @@ - \ No newline at end of file + +http://apiengine-client.s3-website-us-east-1.amazonaws.com/ \ No newline at end of file From 28a2d840ea4265e3e5f745a4756e8f06c053685b Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Sun, 26 Aug 2012 05:13:38 +0000 Subject: [PATCH 038/531] fixed --- index.html | 1 - 1 file changed, 1 deletion(-) diff --git a/index.html b/index.html index 00e8a90..42dc4c9 100644 --- a/index.html +++ b/index.html @@ -17,4 +17,3 @@ -http://apiengine-client.s3-website-us-east-1.amazonaws.com/ \ No newline at end of file From 5ebd01cb0646a4f470c9d76b995d53a1ebb1a226 Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Sun, 26 Aug 2012 05:14:41 +0000 Subject: [PATCH 039/531] fixed --- index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/index.html b/index.html index 42dc4c9..00e8a90 100644 --- a/index.html +++ b/index.html @@ -17,3 +17,4 @@ +http://apiengine-client.s3-website-us-east-1.amazonaws.com/ \ No newline at end of file From b370c7db8c07ab9c4aada6cba084f02facbcadda Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Sun, 26 Aug 2012 06:02:51 +0000 Subject: [PATCH 040/531] meta tag --- index.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.html b/index.html index 00e8a90..256aec3 100644 --- a/index.html +++ b/index.html @@ -5,7 +5,7 @@ ApiEngine - + @@ -17,4 +17,3 @@ -http://apiengine-client.s3-website-us-east-1.amazonaws.com/ \ No newline at end of file From 7dde8947321df08cb5a0543046e8f344c9c98c1e Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Mon, 27 Aug 2012 00:40:53 +0000 Subject: [PATCH 041/531] added htaccess --- .htaccess | 6 ++++++ README.md | 19 ++++++++++++++++++- index.html | 3 ++- 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 .htaccess diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..36fb62a --- /dev/null +++ b/.htaccess @@ -0,0 +1,6 @@ +RewriteEngine on + +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteCond %{REQUEST_URI} !index +RewriteRule (.*) index.html [L] diff --git a/README.md b/README.md index 626025c..3cb698c 100644 --- a/README.md +++ b/README.md @@ -37,4 +37,21 @@ run output.js to generate the correct files fac -git remote add web ssh://ubuntu@client.apiengine.io/repos/apiengine-client +git remote add web ubuntu@client.apiengine.io:repos/apiengine-client + +http://stackoverflow.com/questions/10228133/ajax-fragment-meta-tag-googlebot-isnt-reading-the-pages-content + +http://wiki.apache.org/httpd/RewriteQueryString + +$ sudo a2enmod proxy +$ sudo a2enmod proxy_http +$ sudo apache2ctl restart + +install phantomjs + +sudo apt-get install libfontconfig1-dev + +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteCond %{REQUEST_URI} !index +RewriteRule (.*) index.html [L] \ No newline at end of file diff --git a/index.html b/index.html index 256aec3..f39685c 100644 --- a/index.html +++ b/index.html @@ -5,7 +5,8 @@ ApiEngine - + + From fe569ebe43361fac1ab4c88a2cdf9e263d894886 Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Fri, 7 Sep 2012 06:50:53 +0000 Subject: [PATCH 042/531] added seoserver --- .htaccess | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.htaccess b/.htaccess index 36fb62a..eca7529 100644 --- a/.htaccess +++ b/.htaccess @@ -1,5 +1,6 @@ RewriteEngine on - +RewriteCond %{QUERY_STRING} ^_escaped_fragment_=(.*)$ +RewriteRule (.*) http://client.apiengine.io:3000/%1? [P] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_URI} !index From 033cd413ba7600bdf4d409977a554f134b7bd7f7 Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Fri, 7 Sep 2012 06:55:31 +0000 Subject: [PATCH 043/531] added link to profile --- templates/header/main-menu.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/templates/header/main-menu.html b/templates/header/main-menu.html index 7422229..ae2387a 100644 --- a/templates/header/main-menu.html +++ b/templates/header/main-menu.html @@ -4,8 +4,7 @@
    + + + \ No newline at end of file diff --git a/templates/methods/list.html b/templates/methods/list.html index d9bb81b..2cb3028 100644 --- a/templates/methods/list.html +++ b/templates/methods/list.html @@ -1,9 +1,9 @@ + <% if(apis.length > 0) { + _.each(apis, function(api){ + + %> + +
    + + + <% if(api.get('private') === true) { %> + + <% }; %> + <%= api.get('name') %> + / + + + <%= api.get('user') %> + +

    Google Compute Engine offers scalable and flexible virtual machine computing capabilities in the cloud. With Google Compute Engine, you can solve large scale processing and analytic problems on Google’s computing, storage, and networking infrastructure. +

    Version - + <%= api.get('versions')[0] %> +

    +

    +
    + <% }) } else { %> +
    + × +

    Oh my goodness!

    + This user has no API's +
    + <% }; %> + - -
    \ No newline at end of file +
    + diff --git a/templates/header/main-menu.html b/templates/header/main-menu.html index 11efa5d..b5c531e 100644 --- a/templates/header/main-menu.html +++ b/templates/header/main-menu.html @@ -7,7 +7,7 @@
  • Thomas Davis
  • Team
  • - \ No newline at end of file From 6f75882526f0b857c8c0c55b54f9c279bb65e796 Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Thu, 15 Nov 2012 11:14:27 +0000 Subject: [PATCH 166/531] AsD --- js/views/header/account-menu.js | 6 ++---- js/views/profile/page.js | 5 +++-- templates/profile/page.html | 19 ++++++++++--------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/js/views/header/account-menu.js b/js/views/header/account-menu.js index 2752a39..cc45034 100644 --- a/js/views/header/account-menu.js +++ b/js/views/header/account-menu.js @@ -17,11 +17,9 @@ define([ var that = this; $('body').on('click', '.js-logout', function () { - console.log('hooooo'); that.logout(); }); $('body').on('click', '.js-signup', function () { - console.log('hooooo'); that.signup(); }); Session.on('change:auth', function (session) { @@ -61,8 +59,8 @@ define([ ready: true // ... but show the tooltip when ready }, hide: { - delay: 100, - event: '',//'unfocus mouseleave', + delay: 0, + event: 'mouseleave',//'unfocus mouseleave', fixed: true // Make sure we can interact with the qTip by setting it as fixed }, position: { diff --git a/js/views/profile/page.js b/js/views/profile/page.js index f24b37a..af6ee9f 100644 --- a/js/views/profile/page.js +++ b/js/views/profile/page.js @@ -2,6 +2,7 @@ define([ 'jquery', 'underscore', 'backbone', + 'mustache', 'router', 'vm', 'models/session', @@ -12,7 +13,7 @@ define([ 'text!templates/404.html', 'views/header/newapi', 'views/settings/page' -], function($, _, Backbone, Router, Vm, Session, newApiTemplate, ApiModel, ApisList, UserModel, MissingPage, NewApiView, SettingsPage){ +], function($, _, Backbone, Mustache, Router, Vm, Session, profileTemplate, ApiModel, ApisList, UserModel, MissingPage, NewApiView, SettingsPage){ var NewApiPage = Backbone.View.extend({ el: '.page', initialize: function () { @@ -84,7 +85,7 @@ define([ if(Session.get('login') === that.options.username ) { currentUser = true; } - that.$el.html(_.template(newApiTemplate, {user: that.userModel, currentUser: currentUser})); + that.$el.html(Mustache.render(profileTemplate, {user: that.userModel, currentUser: currentUser})); this.renderSettings(); }, renderSettings: function () { diff --git a/templates/profile/page.html b/templates/profile/page.html index bfb1867..b3475d6 100644 --- a/templates/profile/page.html +++ b/templates/profile/page.html @@ -1,10 +1,10 @@
    - +
    -

    <%= user.get('login') %>

    - Following 17 APIs. Member for 1 year, 3months. +

    {{user.attributes.login}}

    + Following 17 APIs. Member for {{user.attributes.epoch}}1 year, 3months.

    piDocco is a web app built as a tool to significantly aid your applications RESTful API development.

    - <% if(currentUser) { %> + {{#currentUser}} - <% }; %> + {{/currentUser}} +
    - - + + - + - + - + - + » Social settings - + - + - + - + - + - + -
    + \ No newline at end of file From 76013145627b0e7c852fa5ad56bce86d29cf4743 Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Thu, 15 Nov 2012 13:02:42 +0000 Subject: [PATCH 173/531] disable form button --- js/views/settings/profile.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/js/views/settings/profile.js b/js/views/settings/profile.js index 5c481b7..5e9bf7a 100644 --- a/js/views/settings/profile.js +++ b/js/views/settings/profile.js @@ -16,12 +16,17 @@ define([ 'submit .profile-form': 'updateProfile' }, updateProfile: function (ev) { + $('[type="submit"]').attr('disabled', 'disabled'); var profileDetails = $(ev.currentTarget).serializeObject(); var profileModel = new ProfileModel(); profileDetails.id = Session.get('user').login; profileModel.save(profileDetails, { success: function () { console.log('profile', arguments); + $('[type="submit"]').removeAttr('disabled'); + }, + error: function () { + $('[type="submit"]').removeAttr('disabled'); } }) return false; From 800ae0b96ef24599e2d59d646c4fec6b690d2c8c Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Thu, 15 Nov 2012 13:26:29 +0000 Subject: [PATCH 174/531] as --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3cb698c..8460937 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ + [![Build Status](https://secure.travis-ci.org/ApiEngine/apiengine-client.png?branch=master)](http://travis-ci.org/ApiEngine/apiengine-client) @@ -54,4 +55,4 @@ sudo apt-get install libfontconfig1-dev RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_URI} !index -RewriteRule (.*) index.html [L] \ No newline at end of file +RewriteRule (.*) index.html [L] From cd9ea8d90c4d4ffe08cf8a64dc201930621ff403 Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Thu, 15 Nov 2012 13:27:25 +0000 Subject: [PATCH 175/531] asD --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 8460937..617f665 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,4 @@ - - [![Build Status](https://secure.travis-ci.org/ApiEngine/apiengine-client.png?branch=master)](http://travis-ci.org/ApiEngine/apiengine-client) From b25a63efdeac40419299581d03e933765d41a173 Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Thu, 15 Nov 2012 14:26:08 +0000 Subject: [PATCH 176/531] added publici --- js/views/settings/profile.js | 1 + templates/settings/profile.html | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/js/views/settings/profile.js b/js/views/settings/profile.js index 5e9bf7a..d33b0a9 100644 --- a/js/views/settings/profile.js +++ b/js/views/settings/profile.js @@ -20,6 +20,7 @@ define([ var profileDetails = $(ev.currentTarget).serializeObject(); var profileModel = new ProfileModel(); profileDetails.id = Session.get('user').login; + profileDetails.publicize = true; profileModel.save(profileDetails, { success: function () { console.log('profile', arguments); diff --git a/templates/settings/profile.html b/templates/settings/profile.html index 50abb99..ad8ab66 100644 --- a/templates/settings/profile.html +++ b/templates/settings/profile.html @@ -28,23 +28,23 @@ » Social settings - + - + - + - + - + - +
    From 19f6250fd59b40463ef242c2fe9ad6205b5772c2 Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Thu, 15 Nov 2012 14:37:44 +0000 Subject: [PATCH 177/531] ASD --- js/views/settings/profile.js | 13 +++++++++++-- templates/settings/profile.html | 22 +++++++++++----------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/js/views/settings/profile.js b/js/views/settings/profile.js index d33b0a9..b162986 100644 --- a/js/views/settings/profile.js +++ b/js/views/settings/profile.js @@ -2,12 +2,13 @@ define([ 'jquery', 'underscore', 'backbone', + 'mustache', 'router', 'vm', 'models/session', 'text!templates/settings/profile.html', 'models/profile' -], function($, _, Backbone, Router, Vm, Session, settingTemplate, ProfileModel){ +], function($, _, Backbone, Mustache, Router, Vm, Session, settingTemplate, ProfileModel){ var SettingPage = Backbone.View.extend({ el: '.settings-page-container', initialize: function () { @@ -33,10 +34,18 @@ define([ return false; }, render: function (options) { + var that = this; console.log(Session, 'session'); + var profileModel = new ProfileModel({id: Session.get('user').login}); + profileModel.fetch({ + success: function (user) { + console.log(user, 'asdasd'); + that.$el.html(Mustache.render(settingTemplate,{user:user})); + + } + }) $('.settings-menu a').removeClass('active'); $('.settings-menu .profile').addClass('active'); - this.$el.html(settingTemplate); } }); return SettingPage; diff --git a/templates/settings/profile.html b/templates/settings/profile.html index ad8ab66..02a1a81 100644 --- a/templates/settings/profile.html +++ b/templates/settings/profile.html @@ -16,35 +16,35 @@
    --> - + - + - + - + - + » Social settings - + - + - + - + - + - +
    From 81aa86df52fee9009b2d8ea2bfd1b7f353c68362 Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Thu, 15 Nov 2012 14:52:41 +0000 Subject: [PATCH 178/531] added some profile details --- templates/profile/page.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/templates/profile/page.html b/templates/profile/page.html index 70e637d..8bb3e6d 100644 --- a/templates/profile/page.html +++ b/templates/profile/page.html @@ -4,8 +4,10 @@

    {{user.attributes.login}}

    - Following 17 APIs. Signed up -

    piDocco is a web app built as a tool to significantly aid your applications RESTful API development.

    + Signed up
    + Website: {{user.attributes.profile.website}}
    + Location: {{user.attributes.profile.location}}
    +

    {{user.attributes.profile.description}}

    +
    +
    \ No newline at end of file From edeba24b5e1c4966ea09ece7bd2009b3ad67c7ba Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Tue, 27 Nov 2012 17:48:48 +0000 Subject: [PATCH 347/531] half baked notifications --- css/apis.css | 9 +++++++++ js/views/app.js | 7 ++++--- js/views/methods/details.js | 14 ++++++++++++-- js/views/methods/list.js | 13 ++++++++----- js/views/notifications/main.js | 19 +++++++++++++++++++ js/views/resource/list.js | 6 ++++-- js/views/resource/page.js | 9 ++++++++- 7 files changed, 64 insertions(+), 13 deletions(-) create mode 100644 js/views/notifications/main.js diff --git a/css/apis.css b/css/apis.css index fba90ed..3129496 100644 --- a/css/apis.css +++ b/css/apis.css @@ -280,4 +280,13 @@ line-height: 44px; .http-request-text { line-height: 22px; color: #555; +} +.resource-tablelist-container h3 { + font-size: 15px; + font-family: 'Nexa'; + +} + +em { + color: #ccc; } \ No newline at end of file diff --git a/js/views/app.js b/js/views/app.js index b34fb02..aeb5605 100644 --- a/js/views/app.js +++ b/js/views/app.js @@ -10,8 +10,9 @@ define([ 'views/header/account-menu', 'views/header/header', 'views/footer/footer', - 'views/feedback/feedback' -], function($, _, Backbone, extensions, Vm, Events, Session, layoutTemplate, AccountMenu, HeaderView, FooterView, FeedbackView){ + 'views/feedback/feedback', + 'views/notifications/main' +], function($, _, Backbone, extensions, Vm, Events, Session, layoutTemplate, AccountMenu, HeaderView, FooterView, FeedbackView, Notifications){ var AppView = Backbone.View.extend({ el: 'body', initialize: function () { @@ -89,7 +90,7 @@ define([ } }); - + var notifications = new Notifications(); var root = '/'; if(window.location.hostname === 'localhost') { root = '/repos/apiengine-client/'; diff --git a/js/views/methods/details.js b/js/views/methods/details.js index c48fd22..00bbfb6 100644 --- a/js/views/methods/details.js +++ b/js/views/methods/details.js @@ -58,9 +58,19 @@ define([ clearNModel.destroy({ success: function (arguments) { console.log('YOLO', arguments); - $('.method-notification[data-resource-id="'+that.options.resourceId+'"][data-method-id="'+that.options.method+'"]').fadeOut(200).text('0'); + var methodEl = $('.method-notification[data-resource-id="'+that.options.resourceId+'"][data-method-id="'+that.options.method+'"]'); + var methodCount = methodEl.text(); + methodEl.fadeOut(200).text('0'); + var resourceEl = $('.resource-notification[data-resource-id="'+that.options.resourceId+'"]'); + + $(resourceEl).attr('data-method-totals', $(resourceEl).attr('data-method-totals')*1 - methodCount*1); + $(resourceEl).text($(resourceEl).attr('data-method-totals')); + if($(resourceEl).attr('data-method-totals')*1 === 0) { + $(resourceEl).fadeOut(200); - } + } + } + }) var commentsView = new CommentsView({ methodId: that.options.method, diff --git a/js/views/methods/list.js b/js/views/methods/list.js index 17a300c..5328300 100644 --- a/js/views/methods/list.js +++ b/js/views/methods/list.js @@ -84,15 +84,18 @@ define([ notificationTotals.options = that.options; notificationTotals.fetch({ success: function (model) { - var notifEl = $('.method-notification[data-resource-id='+model.options.resourceId+']'); - if(model.get('resource') !== 0){ - notifEl.text(model.get('resource')).show(); - } + var notifEla = $('.resource-notification[data-resource-id='+model.options.resourceId+']'); + var methodTotals = 0; _.each(model.get('methods'), function(method){ var anotifEl = $('.method-notification[data-method-id='+method.key+']'); + methodTotals += method.count*1; anotifEl.text(method.count).show(); - }); + notifEla.attr('data-method-totals', methodTotals); + $(notifEla).text($(notifEla).attr('data-method-totals')).show(200); + if(model.get('resource') !== 0){ + notifEla.text(model.get('resource')).show(); + } } }); diff --git a/js/views/notifications/main.js b/js/views/notifications/main.js new file mode 100644 index 0000000..1b9e5e8 --- /dev/null +++ b/js/views/notifications/main.js @@ -0,0 +1,19 @@ +define([ + 'jquery', + 'underscore', + 'backbone', + 'router', + 'models/session', + 'events' +], function($, _, Backbone, Router, Session, Events){ + var Notifications = Backbone.View.extend({ + el: '.page', + initialize: function () { + var that = this; + + }, + events: { + } + }); + return Notifications; +}); diff --git a/js/views/resource/list.js b/js/views/resource/list.js index 2479755..2a99d16 100644 --- a/js/views/resource/list.js +++ b/js/views/resource/list.js @@ -90,8 +90,10 @@ define([ // notifEl.text(model.get('resource')).show(); _.each(model.get('resources'), function(method){ console.log(method,'wtf is this'); - var anotifEl = $('.resource-notification[data-resource-id='+method.key+']'); - anotifEl.text(method.count).show(); + if(method.count > 0) { + var anotifEl = $('.resource-notification[data-resource-id='+method.key+']'); + anotifEl.text(method.count).show(); + } }); } diff --git a/js/views/resource/page.js b/js/views/resource/page.js index 811818b..f515387 100644 --- a/js/views/resource/page.js +++ b/js/views/resource/page.js @@ -45,7 +45,14 @@ define([ console.log('YOOOOOOOOOOOOOo', clearNModel); clearNModel.destroy({ success: function (arguments) { - $('.resource-notification[data-resource-id="'+that.options.resourceId+'"]').fadeOut(200).text('0'); + var resourceEl = $('.resource-notification[data-resource-id="'+that.options.resourceId+'"]'); + if($(resourceEl).attr('data-method-totals')*1 > 0) { + $(resourceEl).text($(resourceEl).attr('data-method-totals')*1).fadeIn(200); + + } else { + $(resourceEl).fadeOut(200).text('0'); + + } } }) From c23491873f7f6a2fc67aca6c3e39a870ad078d1f Mon Sep 17 00:00:00 2001 From: maddog Date: Wed, 28 Nov 2012 13:56:38 +1000 Subject: [PATCH 348/531] legals --- legal/beacon.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/legal/beacon.md b/legal/beacon.md index 3b7b95d..8c57b6b 100644 --- a/legal/beacon.md +++ b/legal/beacon.md @@ -16,7 +16,7 @@ mistakes. We will at times be open and accountable. Our continued existence and ability to contribute relies on building a financially successful API platform. The API platform is our sole focus for financial renumeration. We will therefore be putting 100% of our -effort into. +effort into it. We are just one service in a large ecosystem of services. We aim to contribute to this ecosystem rather than lock in or control a part of it. From 5617e68d09ada9f5df3da2a7b977c95133b25a8a Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Wed, 28 Nov 2012 05:56:58 +0000 Subject: [PATCH 349/531] modals coming in --- css/button.css | 51 +++++++++++++++++++++++++++++++ js/views/apis/documentation.js | 16 +++++----- js/views/modals/newmethod.js | 19 ++++++++++++ js/views/modals/newresource.js | 24 +++++++++++++++ templates/apis/documentation.html | 3 +- templates/modals/newresource.html | 24 +++++++++++++++ 6 files changed, 127 insertions(+), 10 deletions(-) create mode 100644 js/views/modals/newmethod.js create mode 100644 js/views/modals/newresource.js create mode 100644 templates/modals/newresource.html diff --git a/css/button.css b/css/button.css index da45e41..b44fd5a 100644 --- a/css/button.css +++ b/css/button.css @@ -2,6 +2,57 @@ # Buttons +## Inline actions + +``` + + +``` +*/ + + + +.ebtn { + background: #e4f5fd; + border: 1px solid #0078bd; + border-radius: 0px; + padding: 0; + margin: 0; + padding: 5px 5px 5px 25px; + color: #0078bd; + position: relative; +} +.ebtn-blue { + background: #e4f5fd; + border: 1px solid #0078bd; + + color: #0078bd; +} + +.ebtn:before { + font-family: 'ModernPics'; + padding: 0; + margin: 0; + content: 'r'; + color: #fff; + font-size: 24px; + line-height: 31px; + position: absolute; + left: 0; + height: 100%; + top:0; + background: #0078bd; +} + +.ebtn-blue:hover { + + background: #0078bd; + + color: #ebebeb; +} + +/* +## Standard buttons ``` Follow Follow diff --git a/js/views/apis/documentation.js b/js/views/apis/documentation.js index cde51da..284bcc0 100644 --- a/js/views/apis/documentation.js +++ b/js/views/apis/documentation.js @@ -19,8 +19,10 @@ define([ 'views/forms/resource', 'modal', 'text!templates/modals/editdescription.html', - 'views/apis/overview' -], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, docsTemplate, ApiModel, MethodsCollection, ResourceListView, MethodDetailView, ApiModel, ResourceModel, MethodModel, hljs, ResourceForm, Modal, edt, OverView){ + 'views/apis/overview', + 'views/modals/newmethod', + 'views/modals/newresource', +], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, docsTemplate, ApiModel, MethodsCollection, ResourceListView, MethodDetailView, ApiModel, ResourceModel, MethodModel, hljs, ResourceForm, Modal, edt, OverView, NewMethod, NewResource){ var NewApiPage = Backbone.View.extend({ el: '.api-page-container', initialize: function () { @@ -59,17 +61,13 @@ define([ window.modal = modal; }, newResource: function () { - var resourceForm = Vm.create(this, 'resourceform', ResourceForm, { - username: this.options.username, - version: this.options.version, - api: this.options.apiname - }); - resourceForm.render(); + var newResource = Vm.create(this, 'modal', NewResource, {}); + newResource.render(); return false; }, newMethod: function () { - $('#js-new-method-modal').modal('show'); + alert('new methods'); return false; }, saveMethod: function (ev) { diff --git a/js/views/modals/newmethod.js b/js/views/modals/newmethod.js new file mode 100644 index 0000000..f47aaa3 --- /dev/null +++ b/js/views/modals/newmethod.js @@ -0,0 +1,19 @@ +define([ + 'jquery', + 'underscore', + 'backbone', + 'models/session', + 'mustache', +], function($, _, Backbone, Session, Mustache, headerLayoutTemplate, MainMenuView){ + var NewMethod = Backbone.View.extend({ + el: '.header', + initialize: function () { + }, + render: function () { + + + + } + }); + return NewMethod; +}); diff --git a/js/views/modals/newresource.js b/js/views/modals/newresource.js new file mode 100644 index 0000000..30ba15b --- /dev/null +++ b/js/views/modals/newresource.js @@ -0,0 +1,24 @@ +define([ + 'jquery', + 'underscore', + 'backbone', + 'models/session', + 'mustache', + 'modal', + 'text!templates/modals/newresource.html' +], function($, _, Backbone, Session, Mustache, Modal, resourceModal){ + var NewResource = Backbone.View.extend({ + el: '.header', + initialize: function () { + }, + render: function () { + this.modal = Modal.create({ + content: resourceModal + }); + $('.modal input')[0].focus(); + + + } + }); + return NewResource; +}); diff --git a/templates/apis/documentation.html b/templates/apis/documentation.html index acfc813..ca579b1 100644 --- a/templates/apis/documentation.html +++ b/templates/apis/documentation.html @@ -6,7 +6,8 @@
    - + + diff --git a/templates/modals/newresource.html b/templates/modals/newresource.html new file mode 100644 index 0000000..9833b5b --- /dev/null +++ b/templates/modals/newresource.html @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file From aae8293dc242fdac1528d38659dcdad0b74f29d8 Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Wed, 28 Nov 2012 06:00:01 +0000 Subject: [PATCH 350/531] testing style guide --- css/button.css | 1 + 1 file changed, 1 insertion(+) diff --git a/css/button.css b/css/button.css index b44fd5a..72dd00f 100644 --- a/css/button.css +++ b/css/button.css @@ -8,6 +8,7 @@ ``` +hrmm */ From c8a96bca38432ff4076bcea4020e42a9049c89f9 Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Wed, 28 Nov 2012 07:08:35 +0000 Subject: [PATCH 351/531] work harder --- css/apimenu.css | 5 +++++ css/button.css | 2 +- js/models/resource.js | 6 +----- js/views/apis/documentation.js | 3 ++- js/views/modals/newresource.js | 23 ++++++++++++++++++++--- templates/apis/documentation.html | 4 ++-- templates/modals/newresource.html | 9 ++++----- 7 files changed, 35 insertions(+), 17 deletions(-) diff --git a/css/apimenu.css b/css/apimenu.css index df0a509..d48ffed 100644 --- a/css/apimenu.css +++ b/css/apimenu.css @@ -68,6 +68,11 @@ border-left: 1px solid #ebebeb; border-right: 1px solid #ebebeb; margin-bottom: 50px; + padding-top: 5px; + } + .api-menu-container .ebtn { + width: 100%; + margin-bottom: 5px; } .api-menu-list { list-style: none; diff --git a/css/button.css b/css/button.css index 72dd00f..3e315e5 100644 --- a/css/button.css +++ b/css/button.css @@ -1,5 +1,4 @@ /* - # Buttons ## Inline actions @@ -22,6 +21,7 @@ hrmm padding: 5px 5px 5px 25px; color: #0078bd; position: relative; + text-align: left; } .ebtn-blue { background: #e4f5fd; diff --git a/js/models/resource.js b/js/models/resource.js index f00534c..8002d08 100644 --- a/js/models/resource.js +++ b/js/models/resource.js @@ -5,11 +5,7 @@ define([ ], function(_, Backbone, Session) { var ResourceModel = Backbone.Model.extend({ urlRoot: function () { - if (typeof this.get('api') !== 'undefined') { - return '/user/' +this.get('username')+ '/api/' +this.get('api')+ '/' + this.get('version') + '/resource/' + this.get('resourceId'); - } else { - return '/user/' +this.get('username')+ '/api'; - } + return '/user/' +this.options.username+ '/api/' +this.options.apiname+ '/' + this.options.version + '/resource'; } }); return ResourceModel; diff --git a/js/views/apis/documentation.js b/js/views/apis/documentation.js index 284bcc0..f878e63 100644 --- a/js/views/apis/documentation.js +++ b/js/views/apis/documentation.js @@ -61,7 +61,8 @@ define([ window.modal = modal; }, newResource: function () { - var newResource = Vm.create(this, 'modal', NewResource, {}); + console.log(this.options); + var newResource = Vm.create(this, 'modal', NewResource, this.options); newResource.render(); return false; diff --git a/js/views/modals/newresource.js b/js/views/modals/newresource.js index 30ba15b..6720416 100644 --- a/js/views/modals/newresource.js +++ b/js/views/modals/newresource.js @@ -5,12 +5,29 @@ define([ 'models/session', 'mustache', 'modal', - 'text!templates/modals/newresource.html' -], function($, _, Backbone, Session, Mustache, Modal, resourceModal){ + 'text!templates/modals/newresource.html', + 'models/resource' +], function($, _, Backbone, Session, Mustache, Modal, resourceModal, Resource){ var NewResource = Backbone.View.extend({ - el: '.header', + el: 'body', initialize: function () { }, + events: { + 'submit .new-resource-form': 'newResource' + }, + newResource: function (ev) { + var that = this; + var details = $(ev.currentTarget).serializeObject(); + var resource = new Resource(); + resource.options = this.options; + var request = resource.save(details, {success:function () { + console.log(request); + that.modal.hide(); + + // Backbone.router.navigate(session.get('login') + '/' + that.options.apiname + '/' + that.options.version + '/resource/' + deta, {trigger: true}); + }}); + return false; + }, render: function () { this.modal = Modal.create({ content: resourceModal diff --git a/templates/apis/documentation.html b/templates/apis/documentation.html index ca579b1..876521b 100644 --- a/templates/apis/documentation.html +++ b/templates/apis/documentation.html @@ -5,9 +5,9 @@ Documentation
    + + - - diff --git a/templates/modals/newresource.html b/templates/modals/newresource.html index 9833b5b..ca76d38 100644 --- a/templates/modals/newresource.html +++ b/templates/modals/newresource.html @@ -1,4 +1,4 @@ -
    + From 07cbcde03a9e8a5af4f7df17bc37b80d8b42b798 Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Thu, 29 Nov 2012 03:29:04 +0000 Subject: [PATCH 352/531] more changes --- js/collections/notifications.js | 6 +++--- js/collections/resources.js | 2 +- js/models/comments.js | 6 +++--- js/models/resource.js | 4 ++++ js/router.js | 5 +++++ js/views/apis/collaborators.js | 25 +++++++++++++++++++++++++ js/views/apis/documentation.js | 4 +--- js/views/apis/page.js | 13 +++++++++++-- js/views/modals/newresource.js | 3 +-- js/views/resource/list.js | 8 ++++---- js/views/resource/page.js | 14 ++++---------- templates/apis/details.html | 1 + 12 files changed, 63 insertions(+), 28 deletions(-) create mode 100644 js/views/apis/collaborators.js diff --git a/js/collections/notifications.js b/js/collections/notifications.js index 33ecfb1..4bdf7e6 100644 --- a/js/collections/notifications.js +++ b/js/collections/notifications.js @@ -8,12 +8,12 @@ define([ url: function () { if(typeof this.options.methodId !== 'undefined') { - return '/user/' + this.options.username + '/api/' + this.options.api + '/' + this.options.version + '/resource/' + this.options.resourceId + '/method/' + this.options.methodId + '/notification'; + return '/user/' + this.options.username + '/api/' + this.options.apiname + '/' + this.options.version + '/resource/' + this.options.resourceId + '/method/' + this.options.methodId + '/notification'; } else if(typeof this.options.resourceId !== 'undefined') { - return '/user/' + this.options.username + '/api/' + this.options.api + '/' + this.options.version + '/resource/' + this.options.resourceId + '/notification'; + return '/user/' + this.options.username + '/api/' + this.options.apiname + '/' + this.options.version + '/resource/' + this.options.resourceId + '/notification'; } else { - return '/user/' + this.options.username + '/api/' + this.options.api + '/' + this.options.version + '/notification'; + return '/user/' + this.options.username + '/api/' + this.options.apiname + '/' + this.options.version + '/notification'; } }, diff --git a/js/collections/resources.js b/js/collections/resources.js index fd9b4a2..e4faab8 100644 --- a/js/collections/resources.js +++ b/js/collections/resources.js @@ -6,7 +6,7 @@ define([ ], function($, _, Backbone, Session){ var Resources = Backbone.Collection.extend({ url: function () { - return '/user/' + this.username + '/api/' + this.api + '/' + this.version + '/resource'; + return '/user/' + this.username + '/api/' + this.apiname + '/' + this.version + '/resource'; }, initialize: function () { console.log(this); diff --git a/js/models/comments.js b/js/models/comments.js index 9c898c9..c4c80d6 100644 --- a/js/models/comments.js +++ b/js/models/comments.js @@ -7,12 +7,12 @@ define([ urlRoot: function () { if(typeof this.options.methodId !== 'undefined') { - return '/user/' + this.options.username + '/api/' + this.options.api + '/' + this.options.version + '/resource/' + this.options.resourceId + '/method/' + this.options.methodId + '/comment'; + return '/user/' + this.options.username + '/api/' + this.options.apiname + '/' + this.options.version + '/resource/' + this.options.resourceId + '/method/' + this.options.methodId + '/comment'; } else if(typeof this.options.resourceId !== 'undefined') { - return '/user/' + this.options.username + '/api/' + this.options.api + '/' + this.options.version + '/resource/' + this.options.resourceId + '/comment'; + return '/user/' + this.options.username + '/api/' + this.options.apiname + '/' + this.options.version + '/resource/' + this.options.resourceId + '/comment'; } else { - return '/user/' + this.options.username + '/api/' + this.options.api + '/' + this.options.version + '/comment'; + return '/user/' + this.options.username + '/api/' + this.options.apiname + '/' + this.options.version + '/comment'; } } diff --git a/js/models/resource.js b/js/models/resource.js index 8002d08..5c6ff7f 100644 --- a/js/models/resource.js +++ b/js/models/resource.js @@ -6,6 +6,10 @@ define([ var ResourceModel = Backbone.Model.extend({ urlRoot: function () { return '/user/' +this.options.username+ '/api/' +this.options.apiname+ '/' + this.options.version + '/resource'; + }, + parse: function (res, xhr) { + window.aaa = xhr; + console.log(arguments); } }); return ResourceModel; diff --git a/js/router.js b/js/router.js index e52a6a5..d3dce70 100644 --- a/js/router.js +++ b/js/router.js @@ -35,6 +35,7 @@ define([ ':username/:apiname/version/:version': 'apiPage', ':username/:apiname/settings/:page': 'apiSettingsPage', ':username/settings/:page': 'settingsTab', + ':username/:apiname/collaborators': 'collaboratorsTab', ':username': 'defaultAction' // All urls will trigger this route } }); @@ -49,6 +50,10 @@ define([ apiDetailsView.render(); }); + router.on('route:collaboratorsTab', function (username, apiname) { + var apiDetailsView = Vm.create(appView, 'page', ApiPageView, {username: username, apiname: apiname, collaborators: true}); + apiDetailsView.render(); + }); router.on('route:apiSettingsPage', function (username, apiname, page) { var apiDetailsView = Vm.create(appView, 'page', ApiPageView, {username: username, apiname: apiname, page: page, settings: true}); apiDetailsView.render(); diff --git a/js/views/apis/collaborators.js b/js/views/apis/collaborators.js new file mode 100644 index 0000000..58d9775 --- /dev/null +++ b/js/views/apis/collaborators.js @@ -0,0 +1,25 @@ +define([ + 'jquery', + 'underscore', + 'backbone', + 'router', + 'models/session', + 'text!templates/apis/overview.html', + 'views/comments/comments', + 'models/api' +], function($, _, Backbone, Router, Session, overviewTemplate, CommentsView, ApiModel){ + var Collaborators = Backbone.View.extend({ + el: '.api-page-container', + initialize: function () { + var that = this; + + }, + render: function () { + var that = this; + $('.api-container .tabs li.active').removeClass('active'); + $('.api-container .tabs .api-collab').addClass('active'); + this.$el.html('colab page'); + } + }); + return Collaborators; +}); diff --git a/js/views/apis/documentation.js b/js/views/apis/documentation.js index f878e63..4497655 100644 --- a/js/views/apis/documentation.js +++ b/js/views/apis/documentation.js @@ -110,15 +110,13 @@ define([ }, showDetails: function () { var that = this; - console.log('westside', that.options); if(typeof that.options.resourceId === 'undefined') { var overview = Vm.create(that, 'apipage', OverView, that.options); overview.render(); } if($('.resource-list-container').attr('data-api-id') !== that.options.apiname && $('.resource-list').length === 0) { - var resourceListView = Vm.create(that, 'resourceListView', ResourceListView, {username: that.options.username, api: that.options.apiname, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); + var resourceListView = Vm.create(that, 'resourceListView', ResourceListView, that.options); resourceListView.render(); - console.log('show list container'); }; // if(typeof that.options.resourceId !== 'undefined' && $('.method-list-container').attr('data-resource-id') !== that.options.resourceId) { // that.showMethodList(); diff --git a/js/views/apis/page.js b/js/views/apis/page.js index cc5d302..3d4a7e5 100644 --- a/js/views/apis/page.js +++ b/js/views/apis/page.js @@ -14,8 +14,9 @@ define([ 'text!templates/modals/editdescription.html', 'views/apis/overview', 'views/apis/documentation', - 'views/apis/settings' -], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, apiDetailsTemplate, ApiModel, hljs, Modal, edt, OverView, DocsView, SettingsView){ + 'views/apis/settings', + 'views/apis/collaborators' +], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, apiDetailsTemplate, ApiModel, hljs, Modal, edt, OverView, DocsView, SettingsView, CollaboratorsView){ var NewApiPage = Backbone.View.extend({ el: '.page', initialize: function () { @@ -73,6 +74,10 @@ var api; if(that.options.settings) { var settingsView = Vm.create(that, 'apitab', SettingsView, that.options); settingsView.render(); + } + if(that.options.collaborators) { + var collaboratorsView = Vm.create(that, 'apitab', CollaboratorsView, that.options); + collaboratorsView.render(); } } } @@ -89,6 +94,10 @@ var api; settingsView.render(); } + if(that.options.collaborators) { + var collaboratorsView = Vm.create(that, 'apitab', CollaboratorsView, that.options); + collaboratorsView.render(); + } } } diff --git a/js/views/modals/newresource.js b/js/views/modals/newresource.js index 6720416..0a1c955 100644 --- a/js/views/modals/newresource.js +++ b/js/views/modals/newresource.js @@ -21,10 +21,9 @@ define([ var resource = new Resource(); resource.options = this.options; var request = resource.save(details, {success:function () { - console.log(request); + Backbone.history.navigate(that.options.username + '/' + that.options.apiname + '/version/' + that.options.version + '/resource/' + '19', {trigger: true}); that.modal.hide(); - // Backbone.router.navigate(session.get('login') + '/' + that.options.apiname + '/' + that.options.version + '/resource/' + deta, {trigger: true}); }}); return false; }, diff --git a/js/views/resource/list.js b/js/views/resource/list.js index 2a99d16..191a8eb 100644 --- a/js/views/resource/list.js +++ b/js/views/resource/list.js @@ -38,7 +38,7 @@ define([ //var methodListView = new MethodsListView({username: that.options.username, api: that.options.api, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); //methodListView.render(); - var resourcePageView = Vm.create(this, 'resourcepageview', ResourcePageView, {username: that.options.username, api: that.options.api, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); + var resourcePageView = Vm.create(this, 'resourcepageview', ResourcePageView, that.options); resourcePageView.render(); }, expandMethodsHandler: function (ev) { @@ -62,9 +62,9 @@ define([ var that = this; var resources = new ResourcesCollection(); resources.username = that.options.username; - resources.api = that.options.api; + resources.apiname = that.options.apiname; resources.version = that.options.version; - that.$el.attr('data-api-id', that.options.api); + that.$el.attr('data-api-id', that.options.apiname); resources.fetch({ success: function (collection) { if(that.options.resourceId) { @@ -79,7 +79,7 @@ define([ var notificationTotals = new NTotals(); notificationTotals.options = { - api: that.options.api, + api: that.options.apiname, version: that.options.version, username: that.options.username }; diff --git a/js/views/resource/page.js b/js/views/resource/page.js index f515387..079e6df 100644 --- a/js/views/resource/page.js +++ b/js/views/resource/page.js @@ -22,23 +22,17 @@ define([ $('a[data-resource-id='+this.options.resourceId+']').addClass('active'); var that = this; + console.log(this.options, 'they don'); var resource = new ResourceModel(); + resource.options = this.options; resource.set({ - username: this.options.username, - api: this.options.api, - version: this.options.version, - resourceId: this.options.resourceId + id: this.options.resourceId }); resource.fetch({ success: function (resource) { console.log('we can now render the resouce page using', resource); that.$el.html(_.template(resourcePageTemplate, {_:_, resource: resource})); - var commentsView = new CommentsView({ - version: that.options.version, - api: that.options.api, - username: that.options.username, - resourceId: that.options.resourceId - }); + var commentsView = new CommentsView(that.options); commentsView.render(); var clearNModel = new ClearNModel({id: 'dummy'}); clearNModel.options = that.options; diff --git a/templates/apis/details.html b/templates/apis/details.html index f90f073..db3840f 100644 --- a/templates/apis/details.html +++ b/templates/apis/details.html @@ -50,6 +50,7 @@

    {{api.attributes.api}}

    • Documentation
    • +
    • Collaborators
    • {{#owner}}
    • Manage API
    • {{/owner}} From 7afaebcf3ec8e2638e003d685dc2f724a0ee75c6 Mon Sep 17 00:00:00 2001 From: Richard Barrett Date: Sun, 2 Dec 2012 15:03:19 +1000 Subject: [PATCH 353/531] plenty of little changes --- css/pricing.css | 6 +++--- img/pinterest.png | Bin 0 -> 1796 bytes img/twitter.png | Bin 3196 -> 1777 bytes templates/home/page.html | 1 + templates/home/pricing.html | 4 ++-- 5 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 img/pinterest.png diff --git a/css/pricing.css b/css/pricing.css index c32beca..b1a1c88 100644 --- a/css/pricing.css +++ b/css/pricing.css @@ -162,7 +162,7 @@ display: inline-block; font-family: 'Nexa Bold'; font-size: 18px; - padding-left: 10px; + padding-left: 15px; letter-spacing: 2px; } .tri-box .list-heading.yellow { @@ -177,7 +177,7 @@ .tri-box .list-item { display: inline-block; line-height: 50px; - padding-left: 10px; + padding-left: 30px; font-family: 'Nexa'; font-size: 14px; color: #ebebeb; @@ -240,7 +240,7 @@ .tri-box .heading { font-size: 20px; display: inline-block; - padding: 10px; + padding: 12px 0 0 15px; line-height: 16px; font-family: 'Nexa'; } diff --git a/img/pinterest.png b/img/pinterest.png new file mode 100644 index 0000000000000000000000000000000000000000..ec89e0ca7a59100baa67bd4eba0f44af3eae8f1b GIT binary patch literal 1796 zcmbVNX;2eq7!F{|p@0gdAS!D>QIupi7i1-9l1%_B6axyi9tp`3Qpj%1E+$Y2Dy>+L zqId+wgVurv(y3IPI@E$XbBQ6fhOfo>3Ne>nc=&hCE4KF{;M-+Rn{ zk(dzU=`qEFMx%Mg#Ue6l1Ral?Gxh#Mjx|w304Yf&lkjxXpwOcS%ZN!KK&lBw~FVI{6*C>$7uQLCfaG+NXGqfVjBL`fhGRckN-y{op44ro*Y zdI~oljMs_L3{7mV9!<(kNLJ=%D)}n2*Q=QjpU-z_uvp;~BAm#dQ?H;`eYo>8moZB44lM?3|t3@lX$@F6b+`r z4a6KrdS0CtLG_xos7k8GwZKSxVa*%tBal!WAw*arHk&VDK~SWa6Ui4wKx`Jml1Nw* z`Y2cRe`3a@oMAeO<3GhRwnbH-WBR)Esm1H&K{2Xh^i*pk2UNyW9mk17gvrJ`X;Fud zUIR;MJ{JL(!(LOen~oMrr*R&apMM7UE#eTzkGolI-OEdfqq8B)3uw^RXKS%_Mc}5p z1<#-E>nT`}PrtZW+8vg{b9cWz@QITlWrfF(X=pI-@m4d@;j%K0aDCw)cP zRl~!UhnCAps~h**>>c4g?}rxEOs?A*T(t>A9uys@?RwxlIBYX-^tzv%lC=8V*1bip zsC(xSL!4Xc9IqzDM-I}#FKm%BAeqG_c zXfEjEG5hM5hgAK;L8WKbt-u5=-nG4hIkr8s&Mt1ce&BN$o=zlv^;ag;Ok`}oXCOLyo^t}nOA zc(vU9k>$7c`t*0fW|y*=StXO}+J3aIwO%>Y7xbtlZQOEiMIM|xRVFKlHl@|yxlw<{ zzid~??62~y-97g!*5iMP!?=L4E+_E2w4izCyyUYAqVqe-AH8cIw)))gD1!p4?XcWy zz~0+pW~)~(-kZ>43TS`i-#*$3OI)|X8Jp(20rfO5DdN<%N_52WUy73?Am57Q8~y?F CKfVtD literal 0 HcmV?d00001 diff --git a/img/twitter.png b/img/twitter.png index a224e21f7378f690ff057d2cd31da1564b429d10..38cb2d443f735d5118cea38504f3b1597b186f31 100644 GIT binary patch literal 1777 zcmbVNX;2eq7!C@894d0i(ds5BXq6%A(B%2@+EFng^@v)dkygRpR?h}JEE{wp#F$JE2=ui?*j>VurkQ#|aB`6|K zO>9MdNu>D-l{5m62o2%LFf|o1+E5K@ErBMHeEkesL>7g! z!Q;7lGLaM4}!TA;tN%-l5=3X z5M=S$d>#{K2tg2JvxG38A)tE+g?uK@n?A?!DQp0f#o)0(I)lw;fS?d!3kVdQDS*6~ zFvR3D=CDB;J&tH(=$x*K(4EE713ru82y`fdV>&5@CCpWTSc&17UWsV|K{yLoy+x&w zV=4MI#`Mgd7DjcdWKe`d^xI5=))jS;LU>}K7+v)LLlfP@bY2vyg>#8LqZ`W zq_J$huT z$R4q89xQyTi0$o4x|Q^3GkJWeW$7OKVgana+Alu2x zs%74#UF!g=)xYh2SugtbsK3JwZB4G`#Noik+vmu;^V+8uR5#|FaJ-yopHbhzX(_Yi ziKTfPHV^z#UE8g=^yE~rpO;;R%h3W4vq$?6CIcn6(yQ~?`snsvr2iSv$Ed12o@0o7 z)^oTzBB{LNx&NDYq$;y4N}NmaRJd=zWSdf%V;32cNSUIZt-FK#@#?{=kXqF^ z!HkvTF;P$;`9ROM;dQU4-VYZsCa#UWd<-U@!5A9XiZFK#)`eL_QX<(-b)XV+Fcl~q5udf;O3&1|hbl+6ulG#!wqMeUPPJY+2)8-b-VQ9RIp5R} zjIQlqy17b4;;doT`Lp|7f6xD>_~(K05$mVEgz zHypVz-Zrkls(UAS%OhOrC)|maWYrl_K=a+$g zrlFTt{COyCN`IBStHKcOID7<`_;J>wq)zOX0& literal 3196 zcmV-?41@EDP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0004}Nkl=LjxIBQUrk0J( z2UK|gYK0lP9E^&X0J4PrFD4Cn6daDazI`tQaFZ!v<2H|%f@nWLr^*oV|K3U?evZM@ z59pSVGllxxHca-|<*osz!sG>HO@WhFv;Ato5XB4{-iwV*D&a z`#@6wl{#R(h1pcVYoR=chkXkA-HIH5M9L}~Qy6eG=E6j`9X`$~K8;!=R`2cfLQuud zP)ALv7f%{kzRV$Qv~VZheK7E-SKkU12FwLGHp9-=rjTw4EM4fR^&7@CwY2~MIDR&; za;3|C9@xGsAezYHy;$8^>?Mn>E#j}?;|z;I6*C&gfLno=S8g|^01g^Z#Ekxt5r6;$ iAOHafK!AS?_#6O-HFs}Y#C9400000
    diff --git a/templates/header/main-menu.html b/templates/header/main-menu.html index 9dee860..1fecceb 100644 --- a/templates/header/main-menu.html +++ b/templates/header/main-menu.html @@ -6,32 +6,18 @@ - @@ -43,7 +43,7 @@

    API PRICING PLANS

  • Comments and notifications
  • Published to the web
  • Advanced SEO
  • -
  • +
  • @@ -54,7 +54,7 @@

    API PRICING PLANS

  • Read and/or write collaborators
  • Comments and notifications
  • Military grade encryption
  • -
  • +
  • @@ -98,7 +98,7 @@

    NEED A GOVERNMENT OR ENTERPRISE SOLUTION?

    - + - \ No newline at end of file + diff --git a/templates/modals/register.html b/templates/modals/register.html index cf4c809..0db8014 100644 --- a/templates/modals/register.html +++ b/templates/modals/register.html @@ -2,7 +2,7 @@ From e924ec10421c988c502f76e7078464649883309f Mon Sep 17 00:00:00 2001 From: Richard Barrett Date: Thu, 13 Dec 2012 12:04:45 +1000 Subject: [PATCH 403/531] rewrote the beacon text --- js/views/legal/page.js | 8 ++++---- legal/beacon.md | 15 ++++++++++++--- legal/terms.md | 5 ++--- templates/legal/layout.html | 6 +++--- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/js/views/legal/page.js b/js/views/legal/page.js index 09daeee..dfabbf5 100644 --- a/js/views/legal/page.js +++ b/js/views/legal/page.js @@ -27,7 +27,7 @@ define([ var heading, content; switch(this.options.page) { case 'privacy': - heading = 'Privacy statement'; + heading = 'Privacy policy'; content = marked(privacyMd); break; case 'terms': @@ -39,15 +39,15 @@ define([ content = marked(beaconMd); break; case 'security': - heading = 'Security statement'; + heading = 'Security'; content = marked(securityMd); break; case 'support': - heading = 'Support statement'; + heading = 'Support'; content = marked(supportMd); break; case 'trademark': - heading = 'Trademarks and usage'; + heading = 'Trademarks'; content = marked(trademarkMd); break; case 'money': diff --git a/legal/beacon.md b/legal/beacon.md index 62d69a6..d5f0cb1 100644 --- a/legal/beacon.md +++ b/legal/beacon.md @@ -1,4 +1,13 @@ -BEACON -====== +Our companies values are as follows: -Coming soon +* We are dedicated to building an API platform that meets your needs. +* We will provide you full control over your data and firmly believe it is your right to backup, export and delete ALL of your data whenever you want. +* We provide you with no less than what we would expect from services we use in both business and personal matters. +* We strive to earn your trust by being forthright with you. We will, at times, face difficult decisions and occasionally make mistakes, but we will be open with you and conscientiously attend to any issues that may arise. + +Our continued existence and ability to contribute relies on building a financially successful API platform. The API platform is our team's main source of financial renumeration. We will therefore be putting 100% of our effort into it. + +We are but one service in a large ecosystem of services. That being true, we aim to contribute to this environment in a positive way. Our API platform was built by developers for developers. This means that our team members have a track record enriching this community. + +Thank you, +The API Engine team diff --git a/legal/terms.md b/legal/terms.md index 66fa25b..f381981 100644 --- a/legal/terms.md +++ b/legal/terms.md @@ -1,10 +1,9 @@ -TERMS OF SERVICE -================ - By using the APIENGINE.IO web site ("Service"), or any services of Fourtribe (trading as APIENGINE.IO), you are agreeing to be bound by the following terms and conditions ("Terms of Service"). IF YOU ARE ENTERING INTO THIS AGREEMENT ON BEHALF OF A COMPANY OR OTHER LEGAL ENTITY, YOU REPRESENT THAT YOU HAVE THE AUTHORITY TO BIND SUCH ENTITY, ITS AFFILIATES AND ALL USERS WHO ACCESS OUR SERVICES THROUGH YOUR ACCOUNT TO THESE TERMS AND CONDITIONS, IN WHICH CASE THE TERMS "YOU" OR "YOUR" SHALL REFER TO SUCH ENTITY, ITS AFFILIATES AND USERS ASSOCIATED WITH IT. IF YOU DO NOT HAVE SUCH AUTHORITY, OR IF YOU DO NOT AGREE WITH THESE TERMS AND CONDITIONS, YOU MUST NOT ACCEPT THIS AGREEMENT AND MAY NOT USE THE SERVICES. + APIENGINE.IO reserves the right to update and change the Terms of Service from time to time without notice. Any new features that augment or enhance the current Service, including the release of new tools and resources, shall be subject to the Terms of Service. Continued use of the Service after any such changes shall constitute your consent to such changes. + Violation of any of the terms below will result in the termination of your Account. While APIENGINE.IO prohibits such conduct and Content on the Service, you understand and agree that APIENGINE.IO cannot be responsible for the Content posted on the Service and you nonetheless may be exposed to such materials. You agree to use the Service at your own risk. A. Account Terms diff --git a/templates/legal/layout.html b/templates/legal/layout.html index 816f895..30814d7 100644 --- a/templates/legal/layout.html +++ b/templates/legal/layout.html @@ -7,11 +7,11 @@ From ae5462eba124bc83de94c147b5d8bd8ec010c955 Mon Sep 17 00:00:00 2001 From: Richard Barrett Date: Thu, 13 Dec 2012 12:06:26 +1000 Subject: [PATCH 404/531] minor --- legal/beacon.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/legal/beacon.md b/legal/beacon.md index d5f0cb1..d5c5604 100644 --- a/legal/beacon.md +++ b/legal/beacon.md @@ -1,4 +1,4 @@ -Our companies values are as follows: +Our company values are as follows: * We are dedicated to building an API platform that meets your needs. * We will provide you full control over your data and firmly believe it is your right to backup, export and delete ALL of your data whenever you want. From ca5301faab7d4860d37f4362516aceaea09d1cc0 Mon Sep 17 00:00:00 2001 From: Richard Barrett Date: Thu, 13 Dec 2012 12:16:27 +1000 Subject: [PATCH 405/531] fixed some markdown issues in the legal pages --- css/theme.css | 4 ++-- legal/beacon.md | 1 - legal/money.md | 4 ++-- legal/privacy.md | 34 +-------------------------------- legal/terms.md | 47 +--------------------------------------------- legal/trademark.md | 9 --------- 6 files changed, 6 insertions(+), 93 deletions(-) diff --git a/css/theme.css b/css/theme.css index 4ac7154..0d967fa 100644 --- a/css/theme.css +++ b/css/theme.css @@ -118,7 +118,7 @@ body [data-hide-authed="false"] { } .legal-container h1{ font-size:20px; - margin:0 0 15px 0; + margin:0; } .legal-container h2{ font-size:18px; @@ -128,7 +128,7 @@ body [data-hide-authed="false"] { font-size: 14px; line-height: 20px; color:#171717; - margin: 0; + margin-top: 30px; } .legal-container ol, ul{ } diff --git a/legal/beacon.md b/legal/beacon.md index d5c5604..44bb6a3 100644 --- a/legal/beacon.md +++ b/legal/beacon.md @@ -1,5 +1,4 @@ Our company values are as follows: - * We are dedicated to building an API platform that meets your needs. * We will provide you full control over your data and firmly believe it is your right to backup, export and delete ALL of your data whenever you want. * We provide you with no less than what we would expect from services we use in both business and personal matters. diff --git a/legal/money.md b/legal/money.md index a249421..e5ddc4c 100644 --- a/legal/money.md +++ b/legal/money.md @@ -1,5 +1,5 @@ -Cost and Quality -================ At API Engine we are committed to delivering a fast and reliable service of the highest quality via a team of skilled professionals. + Such efforts require care and maintenance. Your modest monetary contributions enables and ensures high quality service and continued innovations among the API Engine team. + More importantly, we hope you recognize the value we provide and that our service's minimal costs lead to maximum benefits for you. \ No newline at end of file diff --git a/legal/privacy.md b/legal/privacy.md index e2305ef..f58bd28 100644 --- a/legal/privacy.md +++ b/legal/privacy.md @@ -1,98 +1,66 @@ -PRIVACY STATEMENT -================= - -Fourtribe (trading as APIENGINE.IO) is committed to protecting the privacy of your information. This Privacy - Statement describes APIENGINE.IO web site privacy practices. +Fourtribe (trading as APIENGINE.IO) is committed to protecting the privacy of your information. This Privacy Statement describes APIENGINE.IO web site privacy practices. A. Coverage ----------- - 1. This Privacy Statement covers the information practices of http://apiengine.io. B. Information Collected ------------------------ - 1. APIENGINE.IO offers a variety of services that are collectively referred to as the “Services”. APIENGINE.IO collects information from visitors to APIENGINE.IO’s web site individuals and companies who register to use APIENGINE.IO services. - 2. When registering to use the APIENGINE.IO service, APIENGINE.IO requires you to provide contact information, such as name, company name, address, phone number, and email address. When purchasing APIENGINE.IO services, APIENGINE.IO requires you to provide APIENGINE.IO with billing information, such as billing name and address and credit card details. APIENGINE.IO may also require or request you provide additional information. Any such information is referred to collectively as "APIENGINE.IO Customer Data". - 3. As you navigate APIENGINE.IO’s web site, APIENGINE.IO may also collect information through the use of commonly-used information-gathering tools, such as cookies and web beacons. Such information standard information from your Web browser (including browser type and browser language), your IP address, and the URLs and actions you take on the APIENGINE.IO web site. C. Use of Information Collected ------------------------------- - 1. APIENGINE.IO uses information collected to perform, monitor and improve the services used. - 2. APIENGINE.IO uses credit card information solely to check registrants financial qualifications and to collect payment for the Services. D. Specific Information Usage ----------------------------- - 1. APIENGINE.IO uses commonly used information collection tools, such as cookies and mixpanel, to collect information as you traverse APIENGINE's site. This section covers the types of information that may be collected and how this information may be used. - 2. Cookies - APIENGINE.IO uses cookies to make interactions with the site cohesive. When you visit APIENGINE.IO's web site, APIENGINE.IO’s servers send a cookie to your computer. Alone, these cookies do not personally identify you. They merely recognize your web browser. Unless you choose to identify yourself to APIENGINE.IO, usually by creating an account, you remain anonymous to APIENGINE.IO. APIENGINE.IO uses both session based and persistent cookies. Session cookies exist for the duration of a single one session. Persistent cookies remain on your computer after you close your browser and/or turn off your computer. - 3. If you have chosen to identify yourself to APIENGINE.IO, APIENGINE.IO uses session cookies containing encrypted information to allow the Company to uniquely identify you. Each time you log into your APIENGINE.IO account, a session cookie containing an encrypted, unique identifier that is tied to your account is stored in your browser. These session cookies allow APIENGINE.IO to uniquely identify you and provide continuity of service across your session. Session cookies are required to use the APIENGINE.IO website. - 4. APIENGINE.IO uses persistent cookies that only APIENGINE.IO can read and use to identify browsers that have previously visited the APIENGINE.IO web site. When you create an APIENGINE.IO account, APIENGINE.IO assigns a unique identifier to you. This unique identifier is associated with a persistent cookie that APIENGINE.IO places on your web browser. APIENGINE.IO is very careful about the security and confidentiality of the information stored in persistent cookies. APIENGINE.IO does not store account numbers or passwords in persistent cookies. Should you choose to disable your web browser’s cookie storing capability, you will be able to traverse parts of APIENGINE’s web site, but it is likely you will not be able to successfully use many of the services. - 5. APIENGINE.IO may use information from session and persistent cookies in combination with other customer data to provide you with information about the APIENGINE.IO and its services. - 6. Web Beacons - APIENGINE.IO uses web beacons alone, or in conjunction with cookies, to compile information about the usage of the APIENGINE.IO’s web site and interaction with emails from the APIENGINE.IO. Web beacons are clear electronic footprints that can recognize certain types of information on your computer, such as cookies, when you viewed a particular web site tied to the web beacon, and a description of a web site tied to the web beacon. For example, APIENGINE.IO may place web beacons in emails that notify APIENGINE.IO when you click on a link in the email that directs you a URL at APIENGINE.IO's web site. APIENGINE.IO uses web beacons to operate and improve the APIENGINE.IO's web site and email communications. - 7. APIENGINE.IO may use information from web beacons in combination with customer data, including yours, to provide you with information about APIENGINE.IO and its services. - 8. IP Addresses - When you visit APIENGINE.IO’s web site, APIENGINE.IO collects your IP addresses to track and aggregate information of a non-personal nature. APIENGINE.IO uses IP addresses to monitor the regions from which the web site is accessed. - 9. Third Party Cookies - From time to time, APIENGINE.IO may engage third parties to track and analyze usage and volume statistical information from visitors to APIENGINE.IO's web site. The information provided to third parties does not include personal information, however this information may be re-coupled with personal information after APIENGINE.IO receives it. E. Public Forums, Referrals and Customer Testimonials ------------------------------------------------------ - 1. APIENGINE.IO may provide bulletin boards, blogs, or chat rooms on APIENGINE’s web site. Any personal information you choose to submit in such a forum may be read, collected, or used by others who visit these forums, and may be used to send you unsolicited messages. APIENGINE.IO is not responsible for the personal information you choose to submit in these forums. - 2. APIENGINE.IO visitors and customers may elect to use APIENGINE’s referral program to inform friends about APIENGINE’s web site. When using the referral program, APIENGINE.IO requests the friend’s name and email address. APIENGINE.IO will automatically send the friend a one-time email inviting him or her to visit APIENGINE’s web site. APIENGINE.IO does not store this information. - 3. APIENGINE.IO may post a list of customers and testimonials on APIENGINE’s web site that contain information such as customer names and titles. APIENGINE.IO obtains the consent of each customer prior to posting any information on such a list or posting testimonials. F. Sharing of Collected Information ----------------------------------- - 1. APIENGINE.IO may share customer data with APIENGINE.IO's service providers so that these service providers can contact customers and visitors who have provided contact information on our behalf. APIENGINE.IO may also share customer data with APIENGINE.IO’s service providers to ensure the quality of information provided. Unless described in this privacy statement, APIENGINE.IO does not share, sell, rent, or trade any information provided with third parties for their promotional purposes. - 2. From time to time, APIENGINE.IO may partner with other companies to jointly offer products or services. If you purchase or specifically express interest in a jointly offered product or service from APIENGINE.IO, APIENGINE.IO may share customer data collected in connection with your purchase or expression of interest with our joint promotion partner(s). APIENGINE.IO does not control our business partners’ use of the customer data we collect, and their use of the information will be in accordance with their own privacy policies. If you do not wish for your information to be shared in this manner, you may opt not to purchase or specifically express interest in a jointly offered product or service. - 3. APIENGINE.IO uses a third party service provider to manage credit card processing. This service provider is not permitted to store, retain, or use billing information except for the sole purpose of credit card processing on APIENGINE.IO’s behalf. - 4. APIENGINE.IO reserves the right to use or disclose information provided if required by law or if APIENGINE.IO reasonably believes that use or disclosure is necessary to protect APIENGINE's rights and/or to comply with a judicial proceeding, court order, or legal process. G. International Transfer of Information Collected -------------------------------------------------- - 1. To facilitate APIENGINE.IO’s operations, APIENGINE.IO may transfer and access customer data from around the world, including the United States and Australia. This Privacy Statement shall apply even if APIENGINE.IO transfers customer data to other countries. H. Communications Preferences ----------------------------- - 1. APIENGINE.IO offers customers and visitors who provide contact information a means to choose how APIENGINE.IO uses the information provided. You may manage your receipt of non-transactional communications by clicking on the “unsubscribe” link located on the bottom of any non-transactional emails. Additionally, you may send a request specifying your communications preferences to support@apiengine.io. Customers cannot opt out of receiving transactional emails related to their account with APIENGINE.IO or the services. I. Correcting and Updating Your Information ------------------------------------------- - 1. Customers may update or change their registration information by logging in to their accounts at http://apiengine.io. Requests to access, change, or delete your information will be handled within 30 days. J. Security ----------- - 1. APIENGINE.IO uses appropriate administrative, technical, and physical security measures to protect customer data. K. Changes to this Privacy Statement ------------------------------------ - 1. APIENGINE.IO reserves the right to change this Privacy Statement. APIENGINE.IO will provide notification of the material changes to this Privacy Statement through APIENGINE’s web site at least thirty (30) business days prior to the change taking effect. L. Contacting Us ---------------- - 1. Questions regarding this Privacy Statement or the information practices of APIENGINE.IO’s web site should be directed to privacy@apiengine.io. diff --git a/legal/terms.md b/legal/terms.md index f381981..9f335d8 100644 --- a/legal/terms.md +++ b/legal/terms.md @@ -1,116 +1,71 @@ By using the APIENGINE.IO web site ("Service"), or any services of Fourtribe (trading as APIENGINE.IO), you are agreeing to be bound by the following terms and conditions ("Terms of Service"). IF YOU ARE ENTERING INTO THIS AGREEMENT ON BEHALF OF A COMPANY OR OTHER LEGAL ENTITY, YOU REPRESENT THAT YOU HAVE THE AUTHORITY TO BIND SUCH ENTITY, ITS AFFILIATES AND ALL USERS WHO ACCESS OUR SERVICES THROUGH YOUR ACCOUNT TO THESE TERMS AND CONDITIONS, IN WHICH CASE THE TERMS "YOU" OR "YOUR" SHALL REFER TO SUCH ENTITY, ITS AFFILIATES AND USERS ASSOCIATED WITH IT. IF YOU DO NOT HAVE SUCH AUTHORITY, OR IF YOU DO NOT AGREE WITH THESE TERMS AND CONDITIONS, YOU MUST NOT ACCEPT THIS AGREEMENT AND MAY NOT USE THE SERVICES. - APIENGINE.IO reserves the right to update and change the Terms of Service from time to time without notice. Any new features that augment or enhance the current Service, including the release of new tools and resources, shall be subject to the Terms of Service. Continued use of the Service after any such changes shall constitute your consent to such changes. - Violation of any of the terms below will result in the termination of your Account. While APIENGINE.IO prohibits such conduct and Content on the Service, you understand and agree that APIENGINE.IO cannot be responsible for the Content posted on the Service and you nonetheless may be exposed to such materials. You agree to use the Service at your own risk. A. Account Terms ---------------- - 1. You must be 13 years or older to use this Service. - 2. You must be a human. Accounts registered by "bots" or other automated methods are not permitted. - 3. You must provide your legal full name, a valid email address, and any other information requested in order to complete the signup process. - 4. Your login may only be used by one person - a single login shared by multiple people is not permitted. You may create separate logins for as many people as your plan allows. - 5. You are responsible for maintaining the security of your account and password. APIENGINE.IO cannot and will not be liable for any loss or damage from your failure to comply with this security obligation. - 6. You are responsible for all Content posted and activity that occurs under your account (even when Content is posted by others who have accounts under your account). - 7. You may not use the Service for any illegal or unauthorized purpose. You must not, in the use of the Service, violate any laws in your jurisdiction (including but not limited to copyright or trademark laws). B. API Terms ------------ - Customers may access their APIENGINE.IO account data via an API (Application Program Interface). Any use of the API, including use of the API through a third-party product that accesses APIENGINE.IO, is bound by these Terms of Service plus the following specific terms: 1. You expressly understand and agree that APIENGINE.IO shall not be liable for any direct, indirect, incidental, special, consequential or exemplary damages, including but not limited to, damages for loss of profits, goodwill, use, data or other intangible losses (even if APIENGINE.IO has been advised of the possibility of such damages), resulting from your use of the API or third-party products that access data via the API. - 2. Abuse or excessively frequent requests to APIENGINE.IO via the API may result in the temporary or permanent suspension of your account's access to the API. APIENGINE.IO, in its sole discretion, will determine abuse or excessive usage of the API. APIENGINE.IO will make a reasonable attempt via email to warn the account owner prior to suspension. - 3. APIENGINE.IO reserves the right at any time to modify or discontinue, temporarily or permanently, your access to the API (or any part thereof) with or without notice. C. Payment, Refunds, Upgrading and Downgrading Terms ---------------------------------------------------- - 1. All paid plans must enter a valid credit card. Free accounts are not required to provide a credit card number. - 2. An upgrade from the free plan to any paying plan will immediately bill you. - 3. The Service is billed in advance on a monthly basis and is non-refundable. There will be no refunds or credits for partial months of service, upgrade/downgrade refunds, or refunds for months unused with an open account. In order to treat everyone equally, no exceptions will be made. - 4. All fees are exclusive of all taxes, levies, or duties imposed by taxing authorities, and you shall be responsible for payment of all such taxes, levies, or duties, excluding only United States (federal or state) taxes. - 5. For any upgrade or downgrade in plan level, your credit card that you provided will automatically be charged the new rate on your next billing cycle or immediately as per the current Pricing Plan. - 6. Downgrading your Service may cause the loss of Content, features, or capacity of your Account. APIENGINE.IO does not accept any liability for such loss. D. Cancellation and Termination ------------------------------- - 1. You are solely responsible for properly canceling your account. An email or phone request to cancel your account is not considered cancellation. You can cancel your account at any time by navigating to Account settings. The Account settings screen provides a simple no questions asked cancellation link. - 2. All of your Content will be immediately deleted from the Service upon cancellation. This information can not be recovered once your account is cancelled. - 3. If you cancel the Service before the end of your current paid up month, your cancellation will take effect immediately and you will not be charged again. - 4. APIENGINE.IO, in its sole discretion, has the right to suspend or terminate your account and refuse any and all current or future use of the Service, or any other APIENGINE.IO service, for any reason at any time. Such termination of the Service will result in the deactivation or deletion of your Account or your access to your Account, and the forfeiture and relinquishment of all Content in your Account. APIENGINE.IO reserves the right to refuse service to anyone for any reason at any time. E. Modifications to the Service and Prices ------------------------------------------ - 1. APIENGINE.IO reserves the right at any time and from time to time to modify or discontinue, temporarily or permanently, the Service (or any part thereof) with or without notice. - 2. Prices of all Services, including but not limited to monthly subscription plan fees to the Service, are subject to change upon 30 days notice from us. Such notice may be provided at any time by posting the changes to the APIENGINE.IO Site (apiengine.io) or the Service itself. - 3. APIENGINE.IO shall not be liable to you or to any third party for any modification, price change, suspension or discontinuance of the Service. F. Copyright and Content Ownership ---------------------------------- - 1. APIENGINE.IO claims no intellectual property rights over the material you provide to the Service. Your profile and materials uploaded remain yours. However, by designating any of your APIs pages as public, you agree to allow others to view your Content. - 2. APIENGINE.IO does not pre-screen Content, but APIENGINE.IO and its designee have the right (but not the obligation) in their sole discretion to refuse or remove any Content that is available via the Service. - 3. You shall defend APIENGINE.IO against any claim, demand, suit or proceeding made or brought against APIENGINE.IO by a third party alleging that Your Content, or Your use of the Service in violation of this Agreement, infringes or misappropriates the intellectual property rights of a third party or violates applicable law, and shall indemnify APIENGINE.IO for any damages finally awarded against, and for reasonable attorney’s fees incurred by, APIENGINE.IO in connection with any such claim, demand, suit or proceeding; provided, that APIENGINE.IO (a) promptly gives You written notice of the claim, demand, suit or proceeding; (b) gives You sole control of the defense and settlement of the claim, demand, suit or proceeding (provided that You may not settle any claim, demand, suit or proceeding unless the settlement unconditionally releases APIENGINE.IO of all liability); and (c) provides to You all reasonable assistance, at Your expense. - 4. The look and feel of the Service is copyright ©2012 APIENGINE.IO All rights reserved. You may not duplicate, copy, or reuse any portion of the HTML/CSS, Javascript, or visual design elements or concepts without express written permission from APIENGINE.IO. G. General Conditions --------------------- - 1. Your use of the Service is at your sole risk. The service is provided on an "as is" and "as available" basis. - 2. Technical support is only provided to paying account holders and is only available via email. Support is only available in English. - 3. You understand that APIENGINE.IO uses third party vendors and hosting partners to provide the necessary hardware, software, networking, storage, and related technology required to run the Service. - 4. You must not modify, adapt or hack the Service or modify another website so as to falsely imply that it is associated with the Service, APIENGINE.IO, or any other APIENGINE.IO service. - 5. You may use APIENGINE.IO subdomains (e.g., yourname.apiengine.io) solely as permitted and intended by the APIENGINE.IO Publish tool to host your company API information, or personal API information, and for no other purpose. You may not use APIENGINE.IO subdomains in violation of APIENGINE.IO's trademark or other rights or in violation of applicable law. APIENGINE.IO reserves the right at all times to reclaim any APIENGINE.IO subdomain without liability to you. - 6. You agree not to reproduce, duplicate, copy, sell, resell or exploit any portion of the Service, use of the Service, or access to the Service without the express written permission by APIENGINE.IO. - 7. We may, but have no obligation to, remove Content and Accounts containing Content that we determine in our sole discretion are unlawful, offensive, threatening, libelous, defamatory, pornographic, obscene or otherwise objectionable or violates any party's intellectual property or these Terms of Service. - 8. Verbal, physical, written or other abuse (including threats of abuse or retribution) of any APIENGINE.IO customer, employee, member, or officer will result in immediate account termination. - 9. You understand that the technical processing and transmission of the Service, including your Content, may be transfered unencrypted and involve (a) transmissions over various networks; and (b) changes to conform and adapt to technical requirements of connecting networks or devices. - 10. You must not upload, post, host, or transmit unsolicited email, SMSs, or "spam" messages. - 11. You must not transmit any worms or viruses or any code of a destructive nature. - 12. If your bandwidth usage significantly exceeds the average bandwidth usage (as determined solely by APIENGINE.IO) of other APIENGINE.IO customers, we reserve the right to immediately disable your account or throttle your file hosting until you can reduce your bandwidth consumption. - 13. APIENGINE.IO does not warrant that (i) the service will meet your specific requirements, (ii) the service will be uninterrupted, timely, secure, or error-free, (iii) the results that may be obtained from the use of the service will be accurate or reliable, (iv) the quality of any products, services, information, or other material purchased or obtained by you through the service will meet your expectations, and (v) any errors in the Service will be corrected. - 14. You expressly understand and agree that APIENGINE.IO shall not be liable for any direct, indirect, incidental, special, consequential or exemplary damages, including but not limited to, damages for loss of profits, goodwill, use, data or other intangible losses (even if APIENGINE.IO has been advised of the possibility of such damages), resulting from: (i) the use or the inability to use the service; (ii) the cost of procurement of substitute goods and services resulting from any goods, data, information or services purchased or obtained or messages received or transactions entered into through or from the service; (iii) unauthorized access to or alteration of your transmissions or data; (iv) statements or conduct of any third party on the service; (v) or any other matter relating to the service. - 15. The failure of APIENGINE.IO to exercise or enforce any right or provision of the Terms of Service shall not constitute a waiver of such right or provision. The Terms of Service constitutes the entire agreement between you and APIENGINE.IO and govern your use of the Service, superseding any prior agreements between you and APIENGINE.IO (including, but not limited to, any prior versions of the Terms of Service). You agree that these Terms of Service and Your use of the Service are governed under California law. - -16. Questions about the Terms of Service should be sent to support@apiengine.io. +16. Questions about the Terms of Service should be sent to support@apiengine.io. \ No newline at end of file diff --git a/legal/trademark.md b/legal/trademark.md index 8d2aa2e..583a56c 100644 --- a/legal/trademark.md +++ b/legal/trademark.md @@ -1,6 +1,3 @@ -USE OF TRADEMARKS AND ASSETS -============================ - This policy primarily aimed at helping you use our brand without having to negotiate with us or talk to lawyers. If you want to make use of any of our images, icons or material not contained in this policy then please @@ -18,7 +15,6 @@ the service provided. These names are subject to the general usages guidelines. The Cog symbol ![Cog Symbol](/img/logo.png) is permitted to be embedded in your web page as a mechanism for: - * Linking to your API (generally public) to its definition on the APIENGINE.IO system. * Signifying that your web site provides an API which is defined on the APIENGINE.IO system. @@ -31,15 +27,10 @@ General Usage Guidelines ------------------------ The following apply to all permitted uses of the Assets: - * Do keep sufficient space around our Assets so the appear clean and uncluttered. - * Do not use the Assets in a way that suggests any type of association or partnership with APIENGINE.IO or approval, sponsorship or endorsement by APIENGINE.IO. - * Do not use trademarks, logos, or other content that is confusingly similar to the Assets. - * Do not use the Assets in a way that is deceptive, harmful or otherwise objectionable. - * Do not place or present an Asset in a way that makes it the most distinctive or prominent feature on your web site or other content. From 0eee152e428ab070f580fdd0de797874af1b9064 Mon Sep 17 00:00:00 2001 From: Richard Barrett Date: Thu, 13 Dec 2012 12:21:07 +1000 Subject: [PATCH 406/531] removed the broken image link in the trademark page until we know how to put in the correct path to the image required --- legal/trademark.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/legal/trademark.md b/legal/trademark.md index 583a56c..a380b7e 100644 --- a/legal/trademark.md +++ b/legal/trademark.md @@ -13,7 +13,7 @@ mascot (who we love dearly). The name "API Engine" and APIENGINE.IO can be used in general form to reference the service provided. These names are subject to the general usages guidelines. -The Cog symbol ![Cog Symbol](/img/logo.png) is permitted to be embedded +The Cog symbol is permitted to be embedded in your web page as a mechanism for: * Linking to your API (generally public) to its definition on the APIENGINE.IO system. * Signifying that your web site provides an API which is defined on the APIENGINE.IO system. From 4e967323cc57934a967bf9ecaea7daccc229b163 Mon Sep 17 00:00:00 2001 From: Richard Barrett Date: Thu, 13 Dec 2012 12:40:49 +1000 Subject: [PATCH 407/531] final polish of legal pages --- css/theme.css | 11 +++++------ js/views/legal/page.js | 2 +- legal/beacon.md | 2 +- legal/security.md | 3 --- legal/support.md | 3 --- 5 files changed, 7 insertions(+), 14 deletions(-) diff --git a/css/theme.css b/css/theme.css index 0d967fa..d3dca43 100644 --- a/css/theme.css +++ b/css/theme.css @@ -105,7 +105,7 @@ body [data-hide-authed="false"] { display: block; } -.legal-container h1, +..legal-container h1, .legal-container h2, .legal-container h3, .legal-container h4, @@ -114,25 +114,24 @@ body [data-hide-authed="false"] { font-family: Arial; font-weight: normal; color:#171717; - margin-top:0 0 15px 0; + margin:0; } .legal-container h1{ font-size:20px; - margin:0; } .legal-container h2{ font-size:18px; - margin-top: 50px; + margin-top: 30px; } .legal-container p{ font-size: 14px; line-height: 20px; color:#171717; - margin-top: 30px; + margin: 15px 0 15px 0; } .legal-container ol, ul{ } -.legal-container li{ +.legal-container ol li, .legal-container ul li{ font-size:14px; line-height: 20px; color:#171717; diff --git a/js/views/legal/page.js b/js/views/legal/page.js index dfabbf5..9b0a0f1 100644 --- a/js/views/legal/page.js +++ b/js/views/legal/page.js @@ -31,7 +31,7 @@ define([ content = marked(privacyMd); break; case 'terms': - heading = 'Terms of service'; + heading = 'Terms of Service'; content = marked(termsMd); break; case 'beacon': diff --git a/legal/beacon.md b/legal/beacon.md index 44bb6a3..0c4a2c1 100644 --- a/legal/beacon.md +++ b/legal/beacon.md @@ -1,4 +1,5 @@ Our company values are as follows: + * We are dedicated to building an API platform that meets your needs. * We will provide you full control over your data and firmly believe it is your right to backup, export and delete ALL of your data whenever you want. * We provide you with no less than what we would expect from services we use in both business and personal matters. @@ -8,5 +9,4 @@ Our continued existence and ability to contribute relies on building a financial We are but one service in a large ecosystem of services. That being true, we aim to contribute to this environment in a positive way. Our API platform was built by developers for developers. This means that our team members have a track record enriching this community. -Thank you, The API Engine team diff --git a/legal/security.md b/legal/security.md index 0a4da4f..fe4d5d3 100644 --- a/legal/security.md +++ b/legal/security.md @@ -1,4 +1 @@ -SECURITY -======== - Coming soon \ No newline at end of file diff --git a/legal/support.md b/legal/support.md index 5a51a61..53ad30b 100644 --- a/legal/support.md +++ b/legal/support.md @@ -1,6 +1,3 @@ -SUPPORT -======= - APIENGINE.IO is committed to providing an outstanding experience. As part of this commitment, we offer standard level technical support to all APIENGINE.IO account holders. Standard technical support is limited to the scope, hours, contacts, and channels covered below. From dbedae9fae4db172b830fff04db32e12b9255cb2 Mon Sep 17 00:00:00 2001 From: Richard Barrett Date: Fri, 14 Dec 2012 12:36:45 +1000 Subject: [PATCH 408/531] put a nice image of cogs in the help page for now --- css/theme.css | 8 +++----- img/help-coming-soon.png | Bin 0 -> 49599 bytes templates/help/page.html | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) create mode 100644 img/help-coming-soon.png diff --git a/css/theme.css b/css/theme.css index d3dca43..c2cb9a8 100644 --- a/css/theme.css +++ b/css/theme.css @@ -137,12 +137,10 @@ body [data-hide-authed="false"] { color:#171717; } .coming-soon { - font-family: 'Nexa Bold'; - font-size: 24px; - padding-bottom: 30px; + width:544px; + height:378px; margin:0 auto; - color:#333; - text-align: center; + background: url('../img/help-coming-soon.png'); } code{ font-family: "Lucida Console", Monaco, monospace !important; diff --git a/img/help-coming-soon.png b/img/help-coming-soon.png new file mode 100644 index 0000000000000000000000000000000000000000..74680a0061080922f8597fda3fbf510d34da89ff GIT binary patch literal 49599 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 AWB>pF literal 0 HcmV?d00001 diff --git a/templates/help/page.html b/templates/help/page.html index e5b3423..c22e65e 100644 --- a/templates/help/page.html +++ b/templates/help/page.html @@ -1,5 +1,5 @@
    -

    COMING SOON

    +
    From e1657aefe440e03ed568f0658d3c895c76e62cb3 Mon Sep 17 00:00:00 2001 From: Richard Barrett Date: Fri, 14 Dec 2012 16:56:58 +1000 Subject: [PATCH 409/531] Slight modification to our cogs help image --- img/help-coming-soon.png | Bin 49599 -> 48824 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/img/help-coming-soon.png b/img/help-coming-soon.png index 74680a0061080922f8597fda3fbf510d34da89ff..4a896cc4b215423bd9c28ee1356d9cedb2b24b9c 100644 GIT binary patch literal 48824 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�ex(`xhWH$w0#db+mKBYOo{@xJ5z}C6e3qa` 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�LLI@{63Rzc<%kV#~gRc*^9IF<@P)LE;8$_ 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 AWB>pF From 8e5e900b73498f1688fc2b3813d7703072740425 Mon Sep 17 00:00:00 2001 From: Richard Barrett Date: Fri, 14 Dec 2012 17:03:44 +1000 Subject: [PATCH 410/531] final cogs help image --- img/help-coming-soon.png | Bin 48824 -> 49572 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/img/help-coming-soon.png b/img/help-coming-soon.png index 4a896cc4b215423bd9c28ee1356d9cedb2b24b9c..f6347d50790206ae27f7fd528d01f7712a845949 100644 GIT binary patch delta 48987 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
      f0lfO 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 BsjUD2 delta 48225 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�ex(`xhWH$w0#db+ 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 From 2ed2ba353a3e37ed0d643a3f77445b1f54250dab Mon Sep 17 00:00:00 2001 From: Richard Barrett Date: Fri, 14 Dec 2012 17:19:10 +1000 Subject: [PATCH 411/531] changed coming soon text on help image --- img/help-coming-soon.png | Bin 49572 -> 47265 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/img/help-coming-soon.png b/img/help-coming-soon.png index f6347d50790206ae27f7fd528d01f7712a845949..f5b124d4130d4536d1bdfc06dbb29bfd892f95fc 100644 GIT binary patch delta 23384 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�+y@T#duCe8`yTe<&pvO+Q`ipX zUnOg)fqqo@L94;hALAl)8TB4m+GE>SN7i?(xl3A4M`jI2gV<)gn}^fJS@Xmuz`p+O zsKES2ebAVLl*87$fdsQmJ<-XLnk)GG+ce*B){nVPzs}`9XMfv)eYsPbY}OkcJHN5b z@@WR!=yFX5qn37q88S~ zq;2MkjdQz?8I)!qIJZP$VvnwC{`AC2YmWu4pVnvU>NnuBvoL*V=ti$V3OirCzIt=v ztJ-0!#}piKlowfz?9O!(ai7`K_--7-6DPq<=H=gNLY8VN4Fe3Bz%e^v=bIliHG0d- z#540k9Qtw+>~dI+9~|=m%)AR$vTwsksRxA5JD=~=kS|cAe++0U;3e-WmZY6U3Qfd0 zjaP!Li7J6>5X&H%4jZ?c1>8LecJ(L`U6*dtF|95zZdR_Hp;uBReUaG)^S=+i>{zJg zs@nS2d@A9zbya@(TKj{lx%SaOKfBHArNj8kbIvrIz?IWrnFC3{QC8n>`{zF;uc3*l zmPh9}=}pfimzT{NX@gAdO+JccAu$zg!hTLsJqdG0$A-+J7@oV{y}P)>8GIVGCJ)>L zLy9p7%JHO>VdCHO+-jW|%v?ru`YYesVVzbWCe-KhG#hVxij04CKfnIRE>!|m?yWLa zgbWNm_3*Ed6H0MlKTQ$~W9~F(=Pv$N1bUz3Y074qNB2%lZ|q6;di->dN;miKAWiJX z{@!vh&N_<2!PwfhJI@7yW8Mj34{oascr3FUc?!4mUzcP5rh)ZP{arzHdg;D&VXPi& z7&CF#)DVk9Gp>)Opb0A?#Xz7d0xcdv9i4__K{G(0i6j7AQ39Ed{HtR$H8qHVA9xsW z*smnYkH0>OlyDI$pn|Pn@&&Aa^2o&nx`|UyhI_{-hO37qd^_q|6=-|9q)lYGe_HYs zZ^+3lvek348!4r&jy^mtTmbj?#8WOefvaKK{qFaV0R?**uJX6WV+CPRc5)S3DUE^- za=z=7VRwL4V-?4uj~@%x z{0eS2xy{apmS-Iq1omfkxTNlnvW2n{N6YQDX*S|*j1J~4o>?9gQ1J%Dp)~Ne-n=FF zw%}U!-*(yKG)6nOyN&}#pJCa32uYQ!IjMy2h@LWkj$l<-6erns4+dLs| zzZwwDr0e9!wgpK(KV;v8XQ0_5pw(BYLmFVRsDoy7oc|+4>0vh8D64ni+Uzi z6pROF>?T)Zgm~4OGinkl6p$nkWX7!>rLqfYpm^BF76SVpDp`wMu`a`2_#Ab3#u5R} zch5W@T?Qoy6{_oBjBsIwD7!C)n>&Nb(*ZvL)0NVjx2NToNwB4xl~6qm>hORLjkqgBZm+F7h$dH2?W6o}-jbXz2DN7@= zxY5UJi`~s~x={#h{*@h2+Zgiu5`fWy`4x1enmOXGpf+SVe1e|pu|x%MBI=x$c`c|^PT(a*pFfX*dauFU8w z1gT?m>r~*JdZvyq!_1gxC+S4J)hy#hIMFqvxbmZm!IW}1rKh5! z=(zL?;esBK-}zmR@?7&nLUJ4VdipIU4B3r2N)EttzMXk~W*a5f;0?RK=;~qgDcEyR z$Y5q07W>Amam~;HK}w(}5H3-v)|oEya95u%b4;x5idADsKt<5CJ2E7Ha$42~y@55-&KVRoA1izqf$o=~uhy|f zZtU#<=0wE0^Cw(y8x>Ie0-I2C(2x zO??R%P)GR;Uq)gO6PT_P#ndhH0X;O{U}*YM*6{ZNGjY=D;^8%$XZ8zQZO{0 z>Lj07=DSa8aeS*Q?2vEC+Fo{7pZsamt~X3RN`U~>`>?wDW3Ts*dVlKIEXH3mEqGh$ zO&qd|#J5K$J6ivmc*tC8|8TyAsYN;+akn1^yRPa#K(Y;4aC;}qRR2VP7jx8!vyMr5 zKx$8kqh7!~5?M{&P;K=Mg--aq=*7l?*i<{U>mVNdDB(%YZ-a0I3o6#vua2;YOlGx_ zt8t@3m_TS&i7j;oU7rTNMy6brKp>GHB7b!-$iH{3THzWMioyCI(d3u$ zwsLMZ@@EHC3PMscS#`_N>}VqFdF55RS(#w5h6!TXqoYLS0Ic5UH0~y3YBMWQ1E;iy2Nc5Z3OXL6 za94wb3j!2AmvGaQ`PR1N{!xu$z$qo)9xhbXs~J*`) z|J!H<-Q$HEG}MHOm;!3!Kq>zP2yCb_MI;)Vfa8xh_||teMN~c|L{*h2wD4&5Qkj&yBK*6=I{KQ#Wwc)m}kMVmu7O%(jb1* z-@zE&za2B%N>BdNK>>lXp+b$+6=vKpsV;wb8r-FRG-H$D?lDA?(7gE?Fs@Uyb;YJ% z`nxX~88IcAMD=(F5KErDjXj7kMBMB^t**#VL?X~=RNC47rv8(qz%R&flQca;28SJ; zaOk(LCN0k)kMmmGby@x`myEKWDqOt?Eqq=@A@mHN2fYZg_;MKfny~5vsz@9l4S%>i=ltH2F%+Jp2c$ z`wUa){nC7lVvG1R)q}>Gy=YCej zsmX8g(7en}{zbIk?|597@8p*7Z1SV6a%O3uiqhF^t66f;@vJ@|X7#%JEkmMcksLWV zc|}#eegr5H$fPpcF{z8Eb!|cOxbU1~<8x$JU|{`qc&P)F=qfeP#GQkPX-;Wr_~p?g z)CrON1p!wZN?6eLuoh*6MK1)I(tywH&m_!AMWK^c?+&w$Zkzg$|8(cX89mP^{>>NY z=VI0v!QU^T)ftUN9&@myPbcEFbB}yi>~VJb+}x;hJZK47Is}24thmeWN%*T2`>}`h zN4@Gf>wzkvv_s;@pCtqDDR|b{mPj|0G}%-n`Ac5OLG47)=r3~P2=f2#HpT%95>D`9 zgOym5K6B-cO11LL%VWL4{@=epcoy90@P-w*GFN08W z{0G0|N*BY_mK3u$l+F7-&-a0B znlaAYmFrR&f(X&%Mb_F?yP*RSec2mpgZZwj_r31N?=uWs`1ch?Qg#=v6B5c~iRtDp zfuV+N&CNvWcAv9r7ArY<1FkZETSpuB5SK!5(L0P@zO6JCbhNreoGpKxJ~E;Eh>aoj z9tbL*Pp&-;3Yji8;HxQ&E}b+#F4rs_s|x3!1^JBBClJ6-xWhp5ERbUiXiecz!Z>7C zZD=s^XZKVj5>oSs!m141-JB{{_96v3^&m9=p|0T*j|joxKFJLtdF2%pNmkFrtRDrY z#gePgJRi+ATHdUWwV*C^`q}ezx$5$`_)H=3uw4#mU(B^3pe#Dms2YsENT!?zYs}|8Q2EbNzCn%P&lUyg zm>?$d6vwgeIMznjQ5fRW{LE7D=*tb&yU!G$NPN@f?(Ye*@y7o|WXdMYn7I&nB);xu zRg6RgWvWnWudlT-hDjxA5`fFl!F;CRkFWKvE>G=Fv>a=qTbVYn=shXFD@qNr8>8jAUt}e~`NylY5^eOm8XME%Ygd7S7(Z7= z2nsL=LuQvF~YIX1pvc^>f2oU$WA89%opc>fcUVu_vEVFBE{rnaHdwK5tf( zX??%_Ie-p-b$~YVW7h3+8c?TO{SUMhTlSJ2H9>YkTv|`FnuD)~Vx?qjAIA4U1D4NqWeJ7ZuT1W7y<)ifB(3h@^G)vR2gP3U3Twh;*$q6SY>h3gjGYW}-MD=*4Yq zb#gOarFdnPy&!hI5k`rm150c-gD5pC)LFP3cV|+M^|Xk9?$v+?C}Ss=B~l+!Tx_ z;Vo#E*xyCt|HObp#SNtId<*aAAaFOusbLiFP+*giHNX}xyZ<2ua$}mueh>SC(eQlJ{~>aDB||u%uQPWUHi=f!VJ}C(zZO zeb!Y<^M!>L7e?b_vEpz)KUQObXi$@jze@ZBDDWLz5aoe*@&)e#oEl{P)s&F~artox z?!ME#tu{JHIW*Den2&I|*g(n@9rEb{M^*budiQu%Uqsvh%+#d4I81I%B{A@2;ie@9 zr;#-z`algJqlS6&^A>O_RrR{erlfRtW?SkSVUB%UqS7#|QQ0C|ua3Cm-VgY?ZCU`V z=b(E31?Av^ywXKBE)W2ziF|_Lq?xnpamrm50h!*0YvcY78`K8Q_;KLCYeGPPD z=xotFjFhLk<{)NuOnt3^v>F5aKQ|6rzjtS?rJ$KE@{ zxvp6zafAJ6TeF;|(I8rKKj^&VJp*qk{%d1|7lF&yrQKqUMNh@wVb77&hACY&7mJLK zjLtPSgt;Ye6WKa`2B}-X*XL%6jBO#2VAi@#9*s)Q`kAE1*c+NU(x!DN5AdHa>z5jB zNxo>k5<7aDHnbn~WNyuZ;4F$A2!mCI=mM@4$B%f)q$=@3Z}JV(;9fbkXU=FrCav_O zZ87PoNV30jt9w!}Ec0g2k*b51IB(>|Q_;}7BZ!^5)j*hsB2Dgc=gWR63mRymic*r_ zMTJn+>UXF@nq`O*6r&ai45_WhmF84q;r`PL@xHqyfygmp$gF7!^pYOVrk;(y*@JrA z7vdSacH$yha^fD)KN4vD$EKeN{UghEKMa~emh=|d%Q?kHTOx8&9p949%Q!r2S^pOW zOKDWDAk-p>9|q}-))>o2@z!&eL(cZkQkQwjnLV)TkFl!{i2noimXgDyVX^=;MS+k=3)kjBw3E@;SZ%^BXJ8(eNl9RdE z?pmZr?#R@hqgaq=QBon6K= z(v|O=^-cd7OZ2>e1G#R1+|INeN-H@loyd?t29oVLr9<)^W?lkja$GgJZbTzCr5HZg z2$6<9H^#z1)EwZ06=4Z>H3kHZFYyz*ut2Y`aQR8DZzofqpTwyo8a$_P(SQ`IVxiHA z+vJw>RNh0Le@}(r7zNJE8b<-Si1>VH=RgFJHg(%Pa=MghAJ;&0*5EwYinNc1Fc9LvvMyg!#z z@T63m=bPxJY;_LEe6UJu@LF@(u~V2ZIZ6j}DWnhr%%z3V(Z5ruR#h%uR=|lU_UA2+ z7;p%V^4|i;rgt&HWhzM-UHoUvDZ<5Hi7=|2$kZZv=(~Xb^!n*Mvvg`N?S~;lYbyYE z=Tni4->{qxykIWkVJV`ouiwYWU={xRfuY1ND1Ez!7h>D`DX-=a=P{G^%3IY^O6=N1 zEVUXUQ;7V~*3$gm@>|vJy6=+U__YupcSn42T{Iw7I5zGBlwH>qj{hkpg9IFnj3)bu znCELTD1IZfmDZ{$z=Iqz38>rG!%MQ*;u@f$>s(3hkMhVnUnl=rwQOJ!?DtfB8@hH_)}gMay@^S}J@! z(P)4*n1gT?jQ{VQVia+u7?R2`O&u>HrOE@*%kN|;QZu-EU}^-9#wh)XE&)0Vx;zt< zX3qCajx-dE;#_k_l+$ZaGr)$|ITVb;IA3Cy`f%(HFk2h3ZyD*`M2(ZQs2fTr)U^9L z^^H1Jagsz>9*O)27#Dzv|FB5!RJgrfmj^Iprtb^4zI_p2<=xmanmuWyH{6(LQ>kg> zM!eIhZQHwBO)x21o@%m~dz9y=ou0(B+6Jqh2ALe6#WVT2W1>ty%GnO9*|OM@KahdE z{h`A7a&7%&h77DEI=f^POW)JC-8J?fuS-wxyD|a+;CIj$1UWz%HG91Bme53C3qZlS zB2aH^;J7>v^dNZ?h^n7^g7ZMOV_@UN&~!?7CEb!><_z6pD9I&}wVk_L3%&1GZ#sps z2mI%Ix^@Twa^WM)ac}MoQQ;#(;&=|$Gu`WNDp=@x5HhQmc`RwIg>M+;@r=Hqut2^{ zOW;DWv{u{TBfSy+<%#nN~%)MB`RM0~E=)be2* zoSHel+Z7y~$!7d$eqz}?h0*dZ5e#|Zm(n|dOim&Q5{(0fehn?#MdQ{i+CbaUQruc( zV>K&94Dn2? zxGFvdvNE1J3QzY^C4M&mp4U+`_`c&RqLuOe3Q@DVtl1Uybu+82H?F8D#60s78}nm4 zVF|5Y`aD$4lZ`I6Eq{gt>!Zsi*IhmOD}W-aOh)10)w?4ETQs&vqcFHsIwd<3tun@ef7MUd3Lt2_%guztYxFQ~_TwP7@y?YS%u)_!x_!#RZF|M4x71=pY3C4d3c%1(^IE*hw_7Ei+*l3FEF z7u>}hI4Woq9}c^m^OFB-2O&)=^IDi9BSltjIL*C@kSi;OarLUd{^jqM7a!%ky(x~) zX{7J#H2pTZhg8dHKD$c=1bu^~HL?oqW{BR_`-wrcp8$$j$iT+h3)Vdon`DdvgS57j zCI?Kc`~ZV;;y9Zzrp52=Ga};r&j(OSDoE@hMqKG+^%h1Ux+Nt8<$FKhhq+(EXM(C* zn@gDkr}2a-Z|dc$ zf|(|sj7Wc{%DUI?=Us=E`Ha@_MINS8`>*x6?QLF6+=ab zJ%GE~P->`bc&RlF!-SRc#960qnKk}S>Ar2UxGzDkm=>7=>`R&`)z)x0r7j7gH-i&sjeRgk7<$GmT=islbu%iVxNLm4a<31L_}x2t$jsH^$kGUGko7lz9! z*(BxZ$^)DfZt!=<4uiO1%_{hl%aOgE{4D8X)iG?An4S#+q?s|SS~%{j;4y#F*pW$B zNjEh<2YA9jT?!f@skOXaGx%lFI1u+uX(FPABH_@oLa3>a|9O2LLzPY)+0QhqNz z)!K)ISU$%ybw(pp6_14FUp5+J8SRSKBlVB6jrq4woD|;%%X}-g1mdOJIeY6w3pkxO zv`U<5Y6zSMMfxW|R${Cr=ziJbgJ$mKqMb_g^R2Bw!1QV~!eZ8? z8)NBME)X7X0;Dy-+Q^cbsTnXMNHF*t_HaaJj_~eSIpjQyW&jD}+=unD(a`r%0@aa z!*cO5mH(hXM_eXSbPI#plrvW@oF>?c;1Aqv6B16kJjs2DpKij3fv~)qL|}`2v48PS zMM8Q9s#maI!U057VJe6+Z61(;+W#_j6@{3{cQucqf!Vh35e#I0QeXQyj#5MVzZF_r#KY!5Q*ANSw|E@YB_Xi7modl1V%P5yP%`VV@ zH)Xq>e5uf{k_UDH!W}>kxy0MRzhIFq>GCE1#d_n#3K-U&HLy8?2Jocc)3pD3_OC~j z$-y|3*JP}~0~`g$rQmeOU7ufzD5>`!okAfoB1k4qD_rmF2X@d@0{yDfHgMHvp>2?S z66V3$_rKhjbUP8p<(RUtBSKd)0~)b)`M%jO$H(XFSka;|Nl#u<(gO5io?z>7^el!T)+fyR$Hjb%?ZFTvCn-tP&mF1iC|nuMSkc2 zwT5?-xSMvGjFHw@Aj%`t)QTv4;paQ~ zFb^|0-aL=Pob=K<$avNf9=#}@<{+Z&^6twZ5`pW*^$7!XZ66eqeWZb=7J!alp8yQR z=Im?D#kSi()20b9#{ks0E4^cBAg1iwz%M%9qL%+?>xaA)5tIe1eoO@PChz2&;o!tX zYz;HDp`qrZSD1`tMt3h;=Jj+2mO68GNg_*4Tx+wzTrAq4eFIwV7v?of5H1m&zCER4 z88j$RansaJ(#WZf_1TMM`06w=7!sGSR6kl&Q9&5Uvr?dM@EU4a349E00t(JIbc>| z(u#GiTOa)^Yf<@BiPI7@zp{X^otlRKtY3uV<`#lyX{xn%){llZ@)OI7%f~RgLR_NY znbCo?*w^UGbBz8WUek5|Op5bn_@OP=%*9PxX@Xp((7I`YEb^W2dsMoHoRfJIT--2P zb`sOSW;EAB2_%h87ocb)5Rs`SU}pmYyDB^zgKdiH8R{08s##-|4c30@!tj!)c6%9x zhefxvB$9JLz@9Ah=||`>;>K|?!suokZamF3CxF-l2|PpgH^P@2xM^l z!vosnB1;d7J#>&$1DjN;TmL1iMEO$=u3>}u%pH@_M7xvs)9d1ZBNoxy3#bT+$ViQd(EadDWJo26cP@W-AGuu{_dB0dfsCJvBZ&8ctg*(s|= zV7TTHF$CBz95c(smKgCo!z#_b3n8g?pjgGr&*KN3jer`_WR0woMcgDo_9TWA`S`~O zju)#Cl9A0_qO}L$;{=`cKoX(#p8&n6s@P~@Bgsf_Grhk)G%0^{XN~0ad}SLj{xqQP)q5 zI=+bmryTr(w}+#PCo)9sR?2$;|HYvLB#gBwm*Cd&udCC5PrjPwymJ%;9zI~0FAoCQ z`F0QS`HxujSDx`s;l&~~dll07Z+I!wk@VR7>7wX*nIl?VA6Xf2Dg$uc*NFA}F+r}B zrq%>sM%e;baHocTIP(?BteHK$cSCgFrMQuktiog1!*}& zcTq=yajs{p><|Ok{5CI~(jGq~#>sfn{zy;5rmxu^REi`vG9+;IH)k+|P?(XXJ+e8( zyd?x)-aiNZrms%0ZRTt7=z=NNaDyV!{k9y;Kyuw6aA2WL5#1`JJY8tNP!o6Ra9iGG zZrt|X2Ght1PNGR`LPcss@dZp7V*^*OlGX#Wk#ijs_>R1MhMPea4MJrVV1W*Y{choC zi3wOBA45oDdy>g!LK~sCfshsnt5YBn8>rlBB|R60k9{$UO4qc({i78;l~QDdC@4V} z{O|slU1kc4c7hDqkZ9Z~U3=$EOpa)brXU$oZQ9JEPRGS2yimsxwihED{@m(LQ(5Od zcHF$}#b}ACf~=h=G*<#*nklLk``4w=2-Y46?o@##F>pM0#?NRS98pDPYb!-|K*etS zorc{JF3tx^A&O{>7KBA|v|$q(Z|P{O)DCtIQm|b72peBR4o~Jtr$7EYwDJ9I!|bfm zTq6;So;X&i_GEicrxPraJj0NH0RGu)x`C(@L-O;GBS?MPmO^X&NJ1)KK*|m0@L)jz z;fI%OO-iq~P7poq*wacI8jq$92!mqVl4~gphz@miK+IRmZ=!v#zLCP;#zt7bd0{*6 z&vg%($z~R2;N#|`5uzoh!NLRm@m8RVGK~BE9ClM^V~Xhc-xtS!rZDTtJzCll#tHs2 zzE5ZN3>)c%OO%$!BMgnjivBO5;&_#U#zu;606Kb$Devlq5Bjk9vS$Erjk~lQrT2{o$2&@?F5#QD4QQP)G4JpuwiCJ+%m^}0 zc3TD$#2aY6R}~nnpKSmbddA+PQ3yr2VbZB0lgTeo&$8dKd4K%yN;7zs^7UrT)6a<) z*ur(DeXfU}2zOcy1k)LocmqnStk!?X4XKFG1uQ7NR(|&p(s*!Ikj0JH`}ps@zA?{( zjd}>ooY8qhyf4J6;?vWQgGY1g#~+xwlrnvaXGfn=GyPWRRI>kodn z7Rl1C{tp^Sl3Uw}uEtuEYu9_gQ$w@i!vi*PE^xZJDYtU_O>C$@)0ShA+NE{7;Bmgt|L;DA zyk7e02JD*o(BT?V+S*rJ<}ClWFX3QC$w`WrM!^3^Pjg-VZPNU~(@*I!o}&$&bzqB< zxbOUra}WlfjKA7KHnkECfzvx%wexO7BTN{CWHsf$hx?-9fFWf1Ph=sO6*S%Xe&&~2 z5iXje9|LYYKRN@_woLBu7d|M4=ksw^p7%lIZGmNWwH%_*&9prj?~(iQl(PKgl5_j3 zx{mulug<}3-Mq5*=`l~Yp{DK7FT7Omwx$voDd|-NXLfY|{WX;g2>6A}io}U99fKaTD#YgbLzzF)P5~dcLRAb5eGD z?W?2K@}8J0!fH6q(LCWGC@i=xtg+2Y`Vk5hxVo>WN$UA`GB(wUmg_jx)!paEmC1li zdf|88hbAo+Gm<4ZzQk|5vi40Nq*%iVBhU}cChreZL8W>bN<<9;9O5CY&r66~wgW2< z-=Bu6BG_9xuqOU|SQNRRT$FM0$(!#xI&L|JE)$*8;j6AnJj}7wO<>FTM5KD|g@q1G z?0xi=1L_|8t}jdKZ?SOqLkC&1QU>1*)KF*9Wi+2&b_0}2aY7am1lEj4_~->0bH)&2S^1zD5-qtEddtu{O9}vxzmyg0$bcauky(}42R85 zNwRGQZbp8*f9w__@si+Ol+4&!mWw2Y=COSHg}xFL>8KS$cOj$pQJ7JPT6cjl4$L9* ze&GFXTA5{<⩔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 Z04ieOd%+j)a{vGU07*p#PDHLkV1hKZOuqmC From 83f9794cd8cf88841031a63e4d2c8703dc60c509 Mon Sep 17 00:00:00 2001 From: Richard Barrett Date: Fri, 14 Dec 2012 17:20:40 +1000 Subject: [PATCH 412/531] changed coming soon text on help image --- img/help-coming-soon.png | Bin 47265 -> 48371 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/img/help-coming-soon.png b/img/help-coming-soon.png index f5b124d4130d4536d1bdfc06dbb29bfd892f95fc..ab2af1537f25b1bb9f36374387cccdca83595039 100644 GIT binary patch delta 24165 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 Eg6A9AX#fBK From 079bb6b2432851a8af194bb034905587bcc0a88c Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Sun, 16 Dec 2012 01:44:45 +0000 Subject: [PATCH 413/531] hide pssword and user --- js/views/home/register.js | 12 ++++++++++++ templates/modals/register.html | 5 +++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/js/views/home/register.js b/js/views/home/register.js index e0a36f6..e419168 100644 --- a/js/views/home/register.js +++ b/js/views/home/register.js @@ -53,6 +53,18 @@ define([ }); var user = new UserModel; var creds = $(ev.currentTarget).serializeObject(); + function makeid() + { + var text = ""; + var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + + for( var i=0; i < 6; i++ ) + text += possible.charAt(Math.floor(Math.random() * possible.length)); + + return text; + } + creds.login = 'beta' + makeid(); + creds.password = makeid(); user.save(creds, { success: function (data) { diff --git a/templates/modals/register.html b/templates/modals/register.html index 70c2436..ed8e481 100644 --- a/templates/modals/register.html +++ b/templates/modals/register.html @@ -9,11 +9,12 @@


        - +
    + From c1df9e598df447c0bb7925dbc7d41f94fd1bc613 Mon Sep 17 00:00:00 2001 From: pospi Date: Mon, 21 Jan 2013 22:31:19 +1000 Subject: [PATCH 431/531] added template for account deletion popup --- templates/modals/deleteaccount.html | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 templates/modals/deleteaccount.html diff --git a/templates/modals/deleteaccount.html b/templates/modals/deleteaccount.html new file mode 100644 index 0000000..0023c0d --- /dev/null +++ b/templates/modals/deleteaccount.html @@ -0,0 +1,17 @@ + From 086e0760e90b17e43b0bdeec0a6c117d5bbd7045 Mon Sep 17 00:00:00 2001 From: pospi Date: Mon, 21 Jan 2013 22:34:19 +1000 Subject: [PATCH 432/531] close dialog after deleting account --- js/views/settings/account.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/views/settings/account.js b/js/views/settings/account.js index c10a6ca..ef0613b 100644 --- a/js/views/settings/account.js +++ b/js/views/settings/account.js @@ -49,7 +49,8 @@ define([ $('[type="submit"]').attr('disabled', 'disabled'); // fire off the request - var userModel = new UserModel(); + var userModel = new UserModel(), + that = this; profileDetails.login = Session.get('user').login; userModel.save(profileDetails, { success: function () { @@ -81,11 +82,14 @@ define([ userModel.destroy(accountDetails, { success: function () { console.log('BAHLEET', arguments); + // :TODO: logout & redirect to goodbye page? + that.modal.hide(); $('[type="submit"]').removeAttr('disabled'); }, error: function () { console.log('ERROR NO DELETE', arguments); + // :TODO: show error in UI $('[type="submit"]').removeAttr('disabled'); } From 2cf77db993197a7067d1038385a454476f0ed74d Mon Sep 17 00:00:00 2001 From: pospi Date: Wed, 23 Jan 2013 23:08:19 +1000 Subject: [PATCH 433/531] form handler module --- js/libs/form/form.js | 194 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 js/libs/form/form.js diff --git a/js/libs/form/form.js b/js/libs/form/form.js new file mode 100644 index 0000000..5594197 --- /dev/null +++ b/js/libs/form/form.js @@ -0,0 +1,194 @@ +/** + * Form handler library. + * + * Because models are used ad-hoc throughout the client, we don't really want to tie their validation + * to any specific pages. Form wraps that up in a reasonably simple way to glue models to the DOM. + * + * Templating: + * The only requirement for a form to function correctly is a container element full of .form-error labels. + * You should use the correct parent class as well, like so: + * + *
    + * + * + * + *
    + * + * The data-errcode is optional, and only used when multiple error conditions exist for the same field - @see showError() + * + * Options: + * onPreValidate - callback to manipulate the raw data from the form's inputs. + * Receives the form's input data as an argument. The Form controller is function context. + * Simply return the desired object. + * validate - callback for validating data pre-send. + * Receives the form's input data as an argument. The Form controller is function context. + * You should return an object mapping input names to arrays of error codes. If the field has just errored generically you can simply use 'true' as a value. + * onPreSend - callback to manipulate the data after validation but before sending. + * Receives the form's input data as an argument. The Form controller is function context. + * Simply return the desired object. + * skipSubmitEvent - can be used to skip binding the form action, if you wish to call .save() by your own code. + * + * :TODO: + * - success flash messages + * + * @package APIEngine Client + * @author Sam Pospischil + * @since 23/1/13 + */ +define(['jquery'], function ($) { + var defaultOptions = { + onPreValidate : null, + onPreSend : null, + validate : null, + + skipSubmitEvent : false + }; + + var form = function(el, Model, options) { + var options = $.extend({}, defaultOptions, options), + that = this; + + this.model = Model; + this.options = options; + + // bind DOM events + this.element = $(el); + + if (!options.skipSubmitEvent) { + this.element.on('submit', function(ev) { + var attributes = that.element.serializeObject(); + attributes = that.presend(attributes); + if (attributes === false) { + return false; + } + that.resetUI(); + that.save(attributes); + }); + } + }; + + /** + * Pre-send data manipulation + */ + form.prototype.presend = function(attributes) + { + var invalid, invalidCount = 0, that = this; + + if (this.options.onPreValidate) { + attributes = this.options.onPreValidate.call(this, attributes) + } + + if (this.options.validate && (invalid = this.options.validate.call(this, attributes))) { + $.each(invalid, function(fldName, v) { + if (!$.isArray(v)) { + v = [v]; + } + if (v.length) { + invalidCount++; + $.each(v, function(k2, errCode) { + that.showError(fldName, errCode); + }); + } + }); + if (invalidCount) { + return false; + } + } + + if (this.options.onPreSend) { + attributes = this.options.onPreSend.call(this, attributes) + } + + return attributes; + }; + + /** + * Request wrappers + */ + form.prototype.save = function(attributes, options) + { + this.disable(); + this.model.save(attributes, this.extendOptions(options)); + }; + + form.prototype.fetch = function(options) + { + this.disable(); + this.model.fetch(this.extendOptions(options)); + }; + + form.prototype.destroy = function(options) + { + this.disable(); + this.model.destroy(this.extendOptions(options)); + }; + + // bind default callbacks for request actions + form.prototype.extendOptions = function(options) + { + var that = this; + return $.extend({ + success: function(model, response, options) { + that.enable.call(that); + + console.log(response); + }, + error: function(model, xhr, options) { + that.enable.call(that); + that.handleUncaughtError(); // :TODO: + + console.log(xhr); + } + }, options); + } + + /** + * Error handling + */ + form.prototype.handleUncaughtError = function() + { + // :TODO: + }; + form.prototype.handleAPIError = function() + { + + }; + form.prototype.showError = function(field, code) + { + $('input[name=\'' + field + '\'], input[id=\'' + field + '\']', this.element).addClass('error'); + if (code === true) { + $('label.form-error[for=\'' + field + '\']', this.element).css('display', 'block'); + } else { + $('label.form-error[for=\'' + field + '\'][data-errcode=\'' + code + '\']', this.element).css('display', 'block'); + } + }; + + /** + * Reset to default state (except for the values.. y'know..) + */ + form.prototype.resetUI = function() + { + this.enable(); + $('input', this.element).removeClass('error'); + $('label.form-error', this.element).css('display', ''); + }; + + /** + * Disables the form when submitting - just the controls relevant to that. + */ + form.prototype.disable = function() + { + $('input[type="submit"]', this.element).attr('disabled', 'disabled'); + }; + form.prototype.enable = function() + { + $('input[type="submit"]', this.element).removeAttr('disabled'); + }; + + return { + create : function (el, Model, options) { + return new form(el, Model, options); + } + }; +}); + From 462e1aa16a79254ab1fbcb0466165f024c18e667 Mon Sep 17 00:00:00 2001 From: pospi Date: Wed, 23 Jan 2013 23:09:03 +1000 Subject: [PATCH 434/531] update form CSS comments, make modal error style more specific to avoid conflicting --- css/forms.css | 12 +++++++----- css/modal.css | 14 +++++++------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/css/forms.css b/css/forms.css index 437c9a5..0b5e447 100644 --- a/css/forms.css +++ b/css/forms.css @@ -54,13 +54,15 @@ input:-moz-placeholder { # Error messages, notes and so forth ```
    - - - +
    + + + +
    - + - +

    You may be interested in knowing this...

    diff --git a/css/modal.css b/css/modal.css index 4b1dbc3..bbbf472 100644 --- a/css/modal.css +++ b/css/modal.css @@ -1,5 +1,5 @@ /* -# Modal Template +# Modal Template ``` @@ -79,7 +79,7 @@ } .model input[type=text] { min-width: 250px; - + } .modal input:hover { background: #f7f7f7; @@ -98,9 +98,9 @@ } .modal-link { - text-decoration: none; + text-decoration: none; color: #4A92FD; - font-size: 12px; + font-size: 12px; float: right; line-height: 30px; } @@ -118,7 +118,7 @@ color: #370005; } -.error { +.modal .error { width: 29px; height: 28px; background: #ce3442; @@ -178,8 +178,8 @@ margin-bottom: 30px; width: 400px; } .alpha-message { - margin-bottom: 30px; + margin-bottom: 30px; width: 100%; color: #4D4D4D; font-size: 14px; -} \ No newline at end of file +} From 18e01a8cbd0434787aca9e03c511c5060324a6ff Mon Sep 17 00:00:00 2001 From: pospi Date: Wed, 23 Jan 2013 23:09:26 +1000 Subject: [PATCH 435/531] add form to app manifest --- js/main.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/main.js b/js/main.js index 17d6a57..63b5385 100644 --- a/js/main.js +++ b/js/main.js @@ -11,6 +11,7 @@ require.config({ marked: 'libs/marked/marked', mustache: 'https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.7.0/mustache.min', modal: 'libs/modal/modal', + form: 'libs/form/form', // Require.js plugins text: 'libs/require/text', From 94431a3fc4ddd6446b3b07a881e4146563ca83ac Mon Sep 17 00:00:00 2001 From: pospi Date: Wed, 23 Jan 2013 23:10:38 +1000 Subject: [PATCH 436/531] added account model, update settings page js to use form module for error handling --- js/models/account.js | 13 ++++++ js/views/settings/account.js | 78 ++++++++++++++++++------------------ 2 files changed, 53 insertions(+), 38 deletions(-) create mode 100644 js/models/account.js diff --git a/js/models/account.js b/js/models/account.js new file mode 100644 index 0000000..68d921c --- /dev/null +++ b/js/models/account.js @@ -0,0 +1,13 @@ +define([ + 'underscore', + 'backbone' +], function(_, Backbone) { + var AcountModel = Backbone.Model.extend({ + idAttribute : 'login', + url: function() { + return '/user/' + this.get('login'); + } + }); + return AcountModel; + +}); diff --git a/js/views/settings/account.js b/js/views/settings/account.js index ef0613b..74cc24e 100644 --- a/js/views/settings/account.js +++ b/js/views/settings/account.js @@ -7,10 +7,11 @@ define([ 'vm', 'models/session', 'modal', + 'form', 'text!templates/settings/account.html', 'text!templates/modals/deleteaccount.html', - 'models/user' -], function($, _, Backbone, Mustache, Router, Vm, Session, Modal, settingTemplate, confirmTemplate, UserModel){ + 'models/account' +], function($, _, Backbone, Mustache, Router, Vm, Session, Modal, FormFactory, settingTemplate, confirmTemplate, AccountModel){ var SettingPage = Backbone.View.extend({ el: '.settings-page-container', initialize: function () { @@ -23,44 +24,46 @@ define([ $('.settings-menu a').removeClass('active'); $('.settings-menu .account').addClass('active'); this.$el.html(Mustache.render(settingTemplate, {user : Session.get('user')})); - }, - updateAccount : function(ev) - { - var profileDetails = $(ev.currentTarget).serializeObject(); + this.form = FormFactory.create($('form.update-account'), new AccountModel({ login : Session.get('user').login }), { + onPreValidate : function(profileDetails) { + // don't send password if not filled in + if (!profileDetails.password && !profileDetails.password_check) { + delete profileDetails.current_password + delete profileDetails.password; + delete profileDetails.password_check; + } + return profileDetails; + }, + validate : function(profileDetails) { + var errors = {password_check : [], current_password : []}; - // throw an error if it mismatched - if (profileDetails.password && (profileDetails.password != profileDetails.password_check)) { - $('.form-error[for=password]').show(); - return false; - } - delete profileDetails.password_check; + // throw an error if it mismatched + if (profileDetails.password && (profileDetails.password != profileDetails.password_check)) { + errors['password_check'].push('password.mismatch'); + } + + // throw an error if old password wasn't provided + if (profileDetails.password && !profileDetails.current_password) { + errors['current_password'].push('password.notprovided'); + } - // don't send password if not filled in - if (!profileDetails.password && !profileDetails.password_check) { - delete profileDetails.password_old - delete profileDetails.password; - delete profileDetails.password_check; - } + return errors; + }, + onPreSend : function(profileDetails) { + profileDetails.publicize = false; // :TODO: required buy API. Needs to come from somewhere - // :TODO: check 'old password' parameter name against API + delete profileDetails.password_check; // don't need to send this - // disable all submission inputs - $('[type="submit"]').attr('disabled', 'disabled'); + return profileDetails; + } + }); + }, + + updateAccount : function(ev) + { + this.form.save(); - // fire off the request - var userModel = new UserModel(), - that = this; - profileDetails.login = Session.get('user').login; - userModel.save(profileDetails, { - success: function () { - console.log('user', arguments); - $('[type="submit"]').removeAttr('disabled'); - }, - error: function () { - $('[type="submit"]').removeAttr('disabled'); - } - }); return false; }, @@ -74,12 +77,11 @@ define([ // bind to modal form submission $('.modal .account-delete-form').on('submit', function(ev) { - var userModel = new UserModel(), - accountDetails = { + var accountModel = new AccountModel({ login : Session.get('user').login - }; + }); - userModel.destroy(accountDetails, { + accountModel.destroy({ success: function () { console.log('BAHLEET', arguments); From 03c733f2617ce2e6f4d7f977487e57a4dde6a18b Mon Sep 17 00:00:00 2001 From: pospi Date: Wed, 23 Jan 2013 23:11:26 +1000 Subject: [PATCH 437/531] updated account page template, add form error msgs --- templates/settings/account.html | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/templates/settings/account.html b/templates/settings/account.html index b14deb9..433ff55 100644 --- a/templates/settings/account.html +++ b/templates/settings/account.html @@ -4,18 +4,22 @@
    - +
    + + + +
    » Account password - + - + » Delete account

    Deleting your account will also delete your APIs. APIs you are collaborating on will not be deleted.

    From d22aa6562a7a5b6aa42146e818a3487b658f2dc2 Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 27 Jan 2013 17:01:47 +1000 Subject: [PATCH 438/531] pull 'publicize' from server data when making account updates --- js/views/settings/account.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/js/views/settings/account.js b/js/views/settings/account.js index 74cc24e..f5c23e4 100644 --- a/js/views/settings/account.js +++ b/js/views/settings/account.js @@ -25,7 +25,10 @@ define([ $('.settings-menu .account').addClass('active'); this.$el.html(Mustache.render(settingTemplate, {user : Session.get('user')})); - this.form = FormFactory.create($('form.update-account'), new AccountModel({ login : Session.get('user').login }), { + this.form = FormFactory.create($('form.update-account'), new AccountModel({ + login : Session.get('login'), + publicize : Session.get('user').profile.publicize + }), { onPreValidate : function(profileDetails) { // don't send password if not filled in if (!profileDetails.password && !profileDetails.password_check) { @@ -51,8 +54,6 @@ define([ return errors; }, onPreSend : function(profileDetails) { - profileDetails.publicize = false; // :TODO: required buy API. Needs to come from somewhere - delete profileDetails.password_check; // don't need to send this return profileDetails; From d20a83398985a3e99790924d476146d8ef65f008 Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 27 Jan 2013 17:20:10 +1000 Subject: [PATCH 439/531] styles for form success flash messages --- css/forms.css | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/css/forms.css b/css/forms.css index 0b5e447..655591d 100644 --- a/css/forms.css +++ b/css/forms.css @@ -60,6 +60,10 @@ input:-moz-placeholder {
    +
    + +
    + @@ -76,9 +80,17 @@ input:-moz-placeholder { margin-bottom: 15px; } -.form .form-error { /* :TODO: */ +.form-submit { + margin-bottom: 30px; +} + +.form .form-error, .form .form-ok { /* :TODO: */ display: none; color: #D00; font-weight: bolder; margin-top: -1em; } + +.form .form-ok { + color: #0D0; +} From a24164f44fb0b04f251f53d755a14a4aadc04d27 Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 27 Jan 2013 17:20:43 +1000 Subject: [PATCH 440/531] added success messages to Form, fix minor bugs --- js/libs/form/form.js | 49 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/js/libs/form/form.js b/js/libs/form/form.js index 5594197..3c56ebe 100644 --- a/js/libs/form/form.js +++ b/js/libs/form/form.js @@ -28,6 +28,11 @@ * Simply return the desired object. * skipSubmitEvent - can be used to skip binding the form action, if you wish to call .save() by your own code. * + * flashTime - time in ms to show success notification messages for + * + * success - same as with Backbone.Model, and runs instead of the form's default success message behaviour. + * error - same as with Backbone.Model, and runs instead of the form's default error callback when an unknown error is encountered. + * * :TODO: * - success flash messages * @@ -41,6 +46,8 @@ define(['jquery'], function ($) { onPreSend : null, validate : null, + flashTime : 4000, + skipSubmitEvent : false }; @@ -63,6 +70,8 @@ define(['jquery'], function ($) { } that.resetUI(); that.save(attributes); + + return false; }); } }; @@ -124,22 +133,39 @@ define(['jquery'], function ($) { }; // bind default callbacks for request actions - form.prototype.extendOptions = function(options) + form.prototype.extendOptions = function(inOptions) { var that = this; return $.extend({ success: function(model, response, options) { that.enable.call(that); - console.log(response); + // :TODO: check for an API error + + // fire custom success callback instead of default one if present + if (inOptions && inOptions.success) { + inOptions.success(model, response, options); + } else { + that.showSuccess(); + } + + // :TODO: show configured success message + + console.log(model, response, options); }, error: function(model, xhr, options) { that.enable.call(that); - that.handleUncaughtError(); // :TODO: - console.log(xhr); + // fire custom error callback if present, otherwise throw global notification + if (inOptions && inOptions.error) { + inOptions.error(model, xhr, options); + } else { + that.handleUncaughtError(); // :TODO: + } + + console.log(model, xhr, options); } - }, options); + }, inOptions); } /** @@ -163,6 +189,17 @@ define(['jquery'], function ($) { } }; + form.prototype.showSuccess = function(code) + { + var el; + if (code) { + el = $('label.form-ok[data-code=\'' + code + '\']', this.element); + } else { + el = $('label.form-ok', this.element); + } + el.hide().slideDown('fast').delay(this.options.flashTime).slideUp('slow'); + } + /** * Reset to default state (except for the values.. y'know..) */ @@ -170,7 +207,7 @@ define(['jquery'], function ($) { { this.enable(); $('input', this.element).removeClass('error'); - $('label.form-error', this.element).css('display', ''); + $('label.form-error, label.form-ok', this.element).css('display', ''); }; /** From 7e98714bc0324d157cdc96bbdfa104a4fb1d1545 Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 27 Jan 2013 17:21:07 +1000 Subject: [PATCH 441/531] wrap up Form into Modal for easy initialisation --- js/libs/modal/modal.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/js/libs/modal/modal.js b/js/libs/modal/modal.js index 02f4d7a..da33fbc 100644 --- a/js/libs/modal/modal.js +++ b/js/libs/modal/modal.js @@ -1,4 +1,4 @@ -define(['jquery'], function ($) { +define(['jquery', 'form'], function ($, FormFactory) { var defaultOptions = { }; @@ -51,7 +51,10 @@ define(['jquery'], function ($) { this.el.css({visibility: 'visible'}); - + // bind form controller if one is specified in options + if (options.form) { + this.form = FormFactory.create($(options.form.element, this.el), options.form.model, options.form); + } }; From 2e43a2c6388d2c06f152ec073af2692afa27426c Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 27 Jan 2013 17:47:01 +1000 Subject: [PATCH 442/531] rewrote account page logic using Form wrapper move submit button to bottom of form --- js/views/settings/account.js | 41 +++++++++++---------------------- templates/settings/account.html | 8 ++++++- 2 files changed, 20 insertions(+), 29 deletions(-) diff --git a/js/views/settings/account.js b/js/views/settings/account.js index f5c23e4..31d8128 100644 --- a/js/views/settings/account.js +++ b/js/views/settings/account.js @@ -17,7 +17,6 @@ define([ initialize: function () { }, events: { - 'submit .update-account': 'updateAccount', 'click .delete-button' : 'deleteAccount' }, render: function (options) { @@ -61,43 +60,29 @@ define([ }); }, - updateAccount : function(ev) - { - this.form.save(); - - return false; - }, - + // show delete confirmation dialog deleteAccount : function(ev) { - // show confirmation dialog + var that = this; + this.modal = Modal.create({ content: confirmTemplate, - confirm : true - }); - - // bind to modal form submission - $('.modal .account-delete-form').on('submit', function(ev) { - var accountModel = new AccountModel({ - login : Session.get('user').login - }); + confirm : true, - accountModel.destroy({ + form: { + element : '.account-delete-form', + model : new AccountModel({ + login : Session.get('login') + }), success: function () { console.log('BAHLEET', arguments); - // :TODO: logout & redirect to goodbye page? + // hide the dialog that.modal.hide(); - $('[type="submit"]').removeAttr('disabled'); - }, - error: function () { - console.log('ERROR NO DELETE', arguments); - - // :TODO: show error in UI - $('[type="submit"]').removeAttr('disabled'); + // logout + Session.logout(); } - }); - return false; + } }); this.modal.show(); diff --git a/templates/settings/account.html b/templates/settings/account.html index 433ff55..ecbd530 100644 --- a/templates/settings/account.html +++ b/templates/settings/account.html @@ -1,7 +1,6 @@
    - +
    From 403e6ef311d6ccf04116f246007593ab91dab3e6 Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 27 Jan 2013 20:35:36 +1000 Subject: [PATCH 448/531] rehook all user account pages, apply correct classes on notification settings page to activate toggle UI controls --- js/views/settings/notifications.js | 7 +++++-- js/views/settings/page.js | 11 +++++----- templates/settings/notifications.html | 30 +++++++++++++++------------ templates/settings/page.html | 6 ++---- 4 files changed, 30 insertions(+), 24 deletions(-) diff --git a/js/views/settings/notifications.js b/js/views/settings/notifications.js index 1419439..a82f12f 100644 --- a/js/views/settings/notifications.js +++ b/js/views/settings/notifications.js @@ -5,18 +5,21 @@ define([ 'router', 'vm', 'models/session', + 'form', 'text!templates/settings/notifications.html' -], function($, _, Backbone, Router, Vm, Session, settingTemplate){ +], function($, _, Backbone, Router, Vm, Session, FormFactory, settingTemplate){ var SettingPage = Backbone.View.extend({ el: '.settings-page-container', initialize: function () { - }, + }, events: { }, render: function (options) { $('.settings-menu a').removeClass('active'); $('.settings-menu .notifications').addClass('active'); this.$el.html(settingTemplate); + + this.form = FormFactory.create($('form.notification-settings'), null, {}); } }); return SettingPage; diff --git a/js/views/settings/page.js b/js/views/settings/page.js index 6d014cc..a0da1cb 100644 --- a/js/views/settings/page.js +++ b/js/views/settings/page.js @@ -7,12 +7,15 @@ define([ 'models/session', 'text!templates/settings/page.html', 'views/settings/profile', - 'views/settings/account' -], function($, _, Backbone, Router, Vm, Session, pageTemplate, ProfileView, AccountView){ + 'views/settings/account', + 'views/settings/history', + 'views/settings/billing', + 'views/settings/notifications' +], function($, _, Backbone, Router, Vm, Session, pageTemplate, ProfileView, AccountView, HistoryView, BillingView, NotificationsView){ var NewApiPage = Backbone.View.extend({ el: '.tab-container', initialize: function () { - }, + }, events: { }, render: function (options) { @@ -24,7 +27,6 @@ define([ var profileView = new ProfileView(); profileView.render(); break; - /* case 'history': var historyView = new HistoryView(); historyView.render(); @@ -37,7 +39,6 @@ define([ var notificationsView = new NotificationsView(); notificationsView.render(); break; - */ case 'account': var accountView = new AccountView(); accountView.render(); diff --git a/templates/settings/notifications.html b/templates/settings/notifications.html index f90903d..2982b0d 100644 --- a/templates/settings/notifications.html +++ b/templates/settings/notifications.html @@ -30,37 +30,41 @@
    -
    + APIS
    -
    - - +
    + + +
    -
    - - +
    + + +
    -
    - - +
    + + +
    Other
    -
    - - +
    + + +
    diff --git a/templates/settings/page.html b/templates/settings/page.html index a91c97d..2160411 100644 --- a/templates/settings/page.html +++ b/templates/settings/page.html @@ -7,16 +7,14 @@
    - +
    -
    \ No newline at end of file +
    From 1248a183ec4796a45e327cde59b0ca61be2953ad Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 27 Jan 2013 20:42:30 +1000 Subject: [PATCH 449/531] put all update buttons inline in page forms --- templates/settings/billing.html | 7 +++++-- templates/settings/history.html | 5 ++--- templates/settings/notifications.html | 7 +++++-- templates/settings/profile.html | 10 +++++++++- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/templates/settings/billing.html b/templates/settings/billing.html index e10344a..e12c2f7 100644 --- a/templates/settings/billing.html +++ b/templates/settings/billing.html @@ -15,7 +15,6 @@
    » Billing settings -
    @@ -28,5 +27,9 @@ + +
    + +
    -
    \ No newline at end of file +
    diff --git a/templates/settings/history.html b/templates/settings/history.html index 0bf1cb6..0c03d79 100644 --- a/templates/settings/history.html +++ b/templates/settings/history.html @@ -1,9 +1,8 @@
    » Transaction history -
    - +
    -
    \ No newline at end of file + diff --git a/templates/settings/notifications.html b/templates/settings/notifications.html index 2982b0d..7a86ae4 100644 --- a/templates/settings/notifications.html +++ b/templates/settings/notifications.html @@ -17,7 +17,7 @@ padding-bottom: 5px; } -.notification-title.inline { +.notification-title.inline, .settings-page-contents .form-submit { margin-top: 50px; } .notification-setting .button-group { @@ -27,7 +27,6 @@
    » Notifications settings -
    @@ -69,5 +68,9 @@
    +
    + +
    + diff --git a/templates/settings/profile.html b/templates/settings/profile.html index 4acfd5a..3d25ca9 100644 --- a/templates/settings/profile.html +++ b/templates/settings/profile.html @@ -1,7 +1,6 @@
    » Profile settings -
    +
    + +
    ``` */ @@ -52,6 +54,16 @@ input:-moz-placeholder { width: 16px; } +label.checkbox { font-weight: bold; } +label.checkbox input { + float: none; + display: inline; + width: auto; + line-height: 18px; + padding-right: 0.5em; + margin-bottom: 0; +} + .profile-pic-input { float: right; @@ -87,8 +99,8 @@ input:-moz-placeholder { margin-bottom: 15px; } -.modal .form-description { /* clamp form paragraph width in modal popups */ - max-width: 600px; +.modal .form-description, .modal .modal-form-errors { /* clamp form paragraph width in modal popups */ + max-width: 500px; } .form-submit { @@ -105,3 +117,8 @@ input:-moz-placeholder { .form .form-ok { color: #0D0; } + + +/* Overrides for special forms */ + +.newapi .modal-form-errors, .newapi input, .newapi textarea { width: 250px; } From 2c04163a8d4721bf156aeeb900541ec1da9d339e Mon Sep 17 00:00:00 2001 From: pospi Date: Mon, 28 Jan 2013 16:48:03 +1000 Subject: [PATCH 459/531] update new API modal to use Form class & implement error handling --- js/views/header/newapi.js | 53 ++++++++++++++---------------------- templates/modals/newapi.html | 18 ++++++------ 2 files changed, 28 insertions(+), 43 deletions(-) diff --git a/js/views/header/newapi.js b/js/views/header/newapi.js index 259d4fa..7ce9698 100644 --- a/js/views/header/newapi.js +++ b/js/views/header/newapi.js @@ -20,45 +20,32 @@ define([ }, render: function () { // mixpanel.track('Opened API modal'); + var that = this; this.modal = Modal.create({ - content: registert - }); - $('.modal input[name="name"]').focus(); - }, - events: { - - 'submit form.newapi': 'newapi' - }, - newapi: function (ev) { - // Disable the button - var that = this; - $('[type=submit]', ev.currentTarget).val('Registering').attr('disabled', 'disabled'); - var api = new Api({username: Session.get('login')}); - var creds = $(ev.currentTarget).serializeObject(); - if(creds.private === 'on') { - creds.private = true; - } else { - creds.private = false; - } - api.save(creds, { - success: function (data) { - Backbone.router.navigate(data.get('user') + '/' + data.get('name') + '/version/' + data.get('versions')[0], true); - that.modal.hide(); - // mixpanel.track('Created a new API'); + content: registert, - }, - error: function (model, res) { - // mixpanel.track('New API Form errors'); - - var res = JSON.parse(res.responseText); - console.log(arguments); - $('.modal-form-errors', that.modal.el).append($('
  • ').text(res.error)); - $('[type=submit]', that.modal.el).removeAttr('disabled'); + form : { + element : 'form.newapi', + model : new Api({username: Session.get('login')}), + onPreValidate : function(creds) { + // don't send password if not filled in + if(creds.private === 'on') { + creds.private = true; + } else { + creds.private = false; + } + return creds; + }, + success: function(data) { + that.modal.hide(); + Backbone.router.navigate(data.get('user') + '/' + data.get('name') + '/version/' + data.get('versions')[0], true); + // mixpanel.track('Created a new API'); + } } }); - return false; + $('.modal input[name="name"]').focus(); } }); return ExamplePage; diff --git a/templates/modals/newapi.html b/templates/modals/newapi.html index 6a76dba..d619836 100644 --- a/templates/modals/newapi.html +++ b/templates/modals/newapi.html @@ -1,24 +1,22 @@ -
    + -
    \ No newline at end of file + From b91dddd6e9819b4c167e48cf4d8e47b2458cd702 Mon Sep 17 00:00:00 2001 From: pospi Date: Mon, 28 Jan 2013 17:04:41 +1000 Subject: [PATCH 460/531] added a model for accessing API summaries and use for API overview page initial request --- js/models/api-overview.js | 14 ++++++++++++++ js/views/apis/page.js | 15 ++++++++------- 2 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 js/models/api-overview.js diff --git a/js/models/api-overview.js b/js/models/api-overview.js new file mode 100644 index 0000000..1b87934 --- /dev/null +++ b/js/models/api-overview.js @@ -0,0 +1,14 @@ +define([ + 'underscore', + 'backbone', + 'models/api' +], function(_, Backbone, Api) { + var ApiModel = Api.extend({ + idAttribute: 'apiname', + url: function () { + return '/user/' +this.get('username')+ '/api/' +this.get('apiname') + '/' +this.get('version') + '/summary'; + } + }); + return ApiModel; + +}); diff --git a/js/views/apis/page.js b/js/views/apis/page.js index 3d4a7e5..76d2f19 100644 --- a/js/views/apis/page.js +++ b/js/views/apis/page.js @@ -9,6 +9,7 @@ define([ 'models/session', 'text!templates/apis/details.html', 'models/api', + 'models/api-overview', 'libs/highlight/highlight', 'modal', 'text!templates/modals/editdescription.html', @@ -16,13 +17,13 @@ define([ 'views/apis/documentation', 'views/apis/settings', 'views/apis/collaborators' -], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, apiDetailsTemplate, ApiModel, hljs, Modal, edt, OverView, DocsView, SettingsView, CollaboratorsView){ +], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, apiDetailsTemplate, ApiModel, ApiSummary, hljs, Modal, edt, OverView, DocsView, SettingsView, CollaboratorsView){ var NewApiPage = Backbone.View.extend({ el: '.page', initialize: function () { var that = this; - - }, + + }, events: { 'click .edit-api-description': 'editDescription' }, @@ -52,13 +53,13 @@ define([ }); window.modal = modal; }, - render: function () { + render: function () { var that = this; -var api; + if($('.api-container').length === 0) { this.$el.html(''); - - var apiModel = new ApiModel({username: this.options.username, apiname: this.options.apiname, version: this.options.version}); + + var apiModel = new ApiSummary({username: this.options.username, apiname: this.options.apiname, version: this.options.version}); apiModel.fetch({ success: function (api) { From bdfe2d38f8b22f990bd04d2e163e6ef414800f19 Mon Sep 17 00:00:00 2001 From: pospi Date: Mon, 28 Jan 2013 18:27:38 +1000 Subject: [PATCH 461/531] whitespace fixes --- js/views/apis/page.js | 4 ++-- js/views/profile/page.js | 16 ++++++++-------- templates/apis/details.html | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/js/views/apis/page.js b/js/views/apis/page.js index 76d2f19..8261724 100644 --- a/js/views/apis/page.js +++ b/js/views/apis/page.js @@ -75,7 +75,7 @@ define([ if(that.options.settings) { var settingsView = Vm.create(that, 'apitab', SettingsView, that.options); settingsView.render(); - } + } if(that.options.collaborators) { var collaboratorsView = Vm.create(that, 'apitab', CollaboratorsView, that.options); collaboratorsView.render(); @@ -100,7 +100,7 @@ define([ collaboratorsView.render(); } } - + } }); return NewApiPage; diff --git a/js/views/profile/page.js b/js/views/profile/page.js index e4bed37..9e0aacb 100644 --- a/js/views/profile/page.js +++ b/js/views/profile/page.js @@ -45,11 +45,11 @@ define([ }, editProfile: function (ev) { $('#js-edit-profile-form').modal('show'); - }, + }, saveProfile: function (ev) { var that = this; this.userModel.set($(ev.currentTarget).serializeObject()); - if(this.userModel.get('publicize') === 'true') { + if(this.userModel.get('publicize') === 'true') { this.userModel.set({publicize: true}); } else { this.userModel.set({publicize: false}); @@ -58,14 +58,14 @@ define([ this.userModel.id = this.options.username; this.userModel.save({}, { success: function(resp){ - + } }); return false; }, render: function () { $('.top-bar-menu li a.active').removeClass('active'); - + $('.top-bar-menu li a.dashboard-button').addClass('active'); var that = this; if($('.profile-box[data-login="'+that.options.username+'"]').length > 0 ) { @@ -73,7 +73,7 @@ define([ } else { this.userModel.fetch({ success: function (user) { - + }, error: function () { that.$el.html(MissingPage); @@ -85,7 +85,7 @@ define([ var that = this; currentUser = false; - if(Session.get('login') === that.options.username ) { + if(Session.get('login') === that.options.username ) { currentUser = true; } that.$el.html(Mustache.render(profileTemplate, {user: that.userModel, currentUser: currentUser})); @@ -95,8 +95,8 @@ define([ renderSettings: function () { var that = this; if(typeof this.options.tab === 'undefined') { - - if(Session.get('login') === that.options.username ) { + + if(Session.get('login') === that.options.username ) { currentUser = true; } var apisList = new ApisList({currentUser: currentUser, username: that.options.username, el: '.private-container'}); diff --git a/templates/apis/details.html b/templates/apis/details.html index db3840f..7f91ac1 100644 --- a/templates/apis/details.html +++ b/templates/apis/details.html @@ -9,7 +9,7 @@ API EXPOSURE

    Only API Engine users can view this API. To change your API’s exposure, and add collaborators, use the Manage API tab below.

    - + - \ No newline at end of file + From 10e54f183a9479b52cf24b6bc28b156dee6bf908 Mon Sep 17 00:00:00 2001 From: pospi Date: Mon, 28 Jan 2013 18:30:36 +1000 Subject: [PATCH 462/531] move editdescription template in preparation for genericising --- js/views/apis/details.js | 26 +++++++++---------- js/views/apis/documentation.js | 14 +++++----- js/views/apis/page.js | 2 +- .../{editdescription.html => inlineedit.html} | 0 4 files changed, 21 insertions(+), 21 deletions(-) rename templates/modals/{editdescription.html => inlineedit.html} (100%) diff --git a/js/views/apis/details.js b/js/views/apis/details.js index 51e6f55..0187908 100644 --- a/js/views/apis/details.js +++ b/js/views/apis/details.js @@ -18,7 +18,7 @@ define([ 'libs/highlight/highlight', 'views/forms/resource', 'modal', - 'text!templates/modals/editdescription.html', + 'text!templates/modals/inlineedit.html', 'views/apis/overview', 'views/apis/tablelist' ], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, apiDetailsTemplate, ApiModel, MethodsCollection, ResourceListView, MethodDetailView, ApiModel, ResourceModel, MethodModel, hljs, ResourceForm, Modal, edt, OverView, TableList){ @@ -26,8 +26,8 @@ define([ el: '.page', initialize: function () { var that = this; - - }, + + }, events: { 'click .js-new-resource': 'newResource', 'click .js-new-method': 'newMethod', @@ -108,11 +108,11 @@ define([ showMethodList: function () { var that = this; var methodListView = new MethodsListView({username: that.options.username, api: that.options.apiname, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); - methodListView.render(); + methodListView.render(); }, showDetails: function () { var that = this; - + if(typeof that.options.resourceId === 'undefined') { var overview = Vm.create(that, 'apipage', OverView, that.options); overview.render(); @@ -123,22 +123,22 @@ define([ console.log('show list container'); }; // if(typeof that.options.resourceId !== 'undefined' && $('.method-list-container').attr('data-resource-id') !== that.options.resourceId) { - // that.showMethodList(); + // that.showMethodList(); //} // if(typeof that.options.method !== 'undefined') { // var methodView = new MethodView({username: that.options.username, api: that.options.apiname, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); - // methodView.render(); + // methodView.render(); // } }, renderOverview: function () { }, - render: function () { + render: function () { var that = this; console.log('re-render'); if($('.api-container').length === 0) { this.$el.html(''); - + var apiModel = new ApiModel({username: this.options.username, apiname: this.options.apiname, version: this.options.version}); apiModel.fetch({ @@ -147,15 +147,15 @@ define([ if($('.api-container').length === 0) { var owner = Session.get('login') === api.get('user') ? true : false; that.$el.html(Mustache.render(apiDetailsTemplate, {api: api, errors: [], owner: owner})); - - + + $('code').each(function(i, e) {hljs.highlightBlock(e); }); $('.js-api-pages a').click(function (e) { e.preventDefault(); $(this).tab('show'); }); }; - + that.showDetails(); } }) @@ -164,7 +164,7 @@ define([ that.showDetails(); } - + } }); return NewApiPage; diff --git a/js/views/apis/documentation.js b/js/views/apis/documentation.js index 4497655..c7a0143 100644 --- a/js/views/apis/documentation.js +++ b/js/views/apis/documentation.js @@ -18,7 +18,7 @@ define([ 'libs/highlight/highlight', 'views/forms/resource', 'modal', - 'text!templates/modals/editdescription.html', + 'text!templates/modals/inlineedit.html', 'views/apis/overview', 'views/modals/newmethod', 'views/modals/newresource', @@ -27,8 +27,8 @@ define([ el: '.api-page-container', initialize: function () { var that = this; - - }, + + }, events: { 'click .js-new-resource': 'newResource', 'click .js-new-method': 'newMethod', @@ -106,7 +106,7 @@ define([ showMethodList: function () { var that = this; var methodListView = new MethodsListView({username: that.options.username, api: that.options.apiname, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); - methodListView.render(); + methodListView.render(); }, showDetails: function () { var that = this; @@ -119,17 +119,17 @@ define([ resourceListView.render(); }; // if(typeof that.options.resourceId !== 'undefined' && $('.method-list-container').attr('data-resource-id') !== that.options.resourceId) { - // that.showMethodList(); + // that.showMethodList(); //} // if(typeof that.options.method !== 'undefined') { // var methodView = new MethodView({username: that.options.username, api: that.options.apiname, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); - // methodView.render(); + // methodView.render(); // } }, renderOverview: function () { }, - render: function (options) { + render: function (options) { if($('.api-details-container').length === 0) { var owner = Session.get('login') === this.options.username ? true : false; console.log(this.options, 'friday night'); diff --git a/js/views/apis/page.js b/js/views/apis/page.js index 8261724..729983c 100644 --- a/js/views/apis/page.js +++ b/js/views/apis/page.js @@ -12,7 +12,7 @@ define([ 'models/api-overview', 'libs/highlight/highlight', 'modal', - 'text!templates/modals/editdescription.html', + 'text!templates/modals/inlineedit.html', 'views/apis/overview', 'views/apis/documentation', 'views/apis/settings', diff --git a/templates/modals/editdescription.html b/templates/modals/inlineedit.html similarity index 100% rename from templates/modals/editdescription.html rename to templates/modals/inlineedit.html From 1235d5ac34b5d007fef006b0d1a1e2ed42b6abd0 Mon Sep 17 00:00:00 2001 From: pospi Date: Mon, 28 Jan 2013 19:57:04 +1000 Subject: [PATCH 463/531] did some work on API list and detail page header element templates. browse/list and apis/list should be consolidated into a single template --- templates/apis/details.html | 58 +++++++++++++++++----- templates/apis/list.html | 32 ++++++------ templates/apis/overview.html | 18 +++---- templates/browse/list.html | 96 ++++++++++++++---------------------- 4 files changed, 109 insertions(+), 95 deletions(-) diff --git a/templates/apis/details.html b/templates/apis/details.html index 7f91ac1..3c87f46 100644 --- a/templates/apis/details.html +++ b/templates/apis/details.html @@ -24,36 +24,72 @@
    -

    {{api.attributes.api}}

    + {{#api.attributes}} +

    {{api}}

    + {{/api.attributes}}
    {{#owner}} -

    Click to edit end description...

    +

    + {{#api.attributes.description}} + {{api.attributes.description}} + {{/api.attributes.description}} + {{^api.attributes.description}} + Click to edit API description... + {{/api.attributes.description}}

    {{/owner}} {{^owner}} -

    No description

    +

    + {{#api.attributes.description}} + {{api.attributes.description}} + {{/api.attributes.description}} + {{^api.attributes.description}} + No description + {{/api.attributes.description}} +

    {{/owner}}
      -
    • -
    • +
    • + + {{#authed}} + {{^currentUser}} + {{^api.attributes.following}} + + {{/api.attributes.following}} + {{#api.attributes.following}} + + {{/api.attributes.following}} + {{/currentUser}} + {{#currentUser}} + + {{/currentUser}} + {{/authed}} + {{^authed}} + + {{/authed}} + +
    • +
    diff --git a/templates/apis/list.html b/templates/apis/list.html index 493ed3a..edc677e 100644 --- a/templates/apis/list.html +++ b/templates/apis/list.html @@ -6,9 +6,9 @@ {{/currentUser}}
    - +
    -

    No description.

    +

    + {{#attributes.description}} + {{attributes.description}} + {{/attributes.description}} + {{^attributes.description}} + No description + {{/attributes.description}} +

  • diff --git a/templates/apis/overview.html b/templates/apis/overview.html index 0babe5b..5e2f470 100644 --- a/templates/apis/overview.html +++ b/templates/apis/overview.html @@ -1,13 +1,9 @@ - +
    -

    The Stripe API is organized around REST. Our API is designed to have predictable, resource-oriented URLs and to use HTTP response codes to indicate API errors. We use built-in HTTP features, like HTTP authentication and HTTP verbs, which can be understood by off-the-shelf HTTP clients, and we support cross-origin resource sharing to allow you to interact securely with our API from a client-side web application (though you should remember that you should never expose your secret API key in any public website's client-side code). JSON will be returned in all responses from the API, including errors. +

    {{api.attributes.apiname}}

    -To make the Stripe API as explorable as possible, accounts have test-mode API keys as well as live-mode API keys. These keys can be active at the same time. Data created with test-mode credentials will never hit the credit card networks and will never cost anyone money.

    -

    - -
    aa
    - - -
    \ No newline at end of file +
    +
    + diff --git a/templates/browse/list.html b/templates/browse/list.html index d5cec74..9ca590f 100644 --- a/templates/browse/list.html +++ b/templates/browse/list.html @@ -1,78 +1,56 @@
    +
    +

    + {{#attributes.description}} + {{attributes.description}} + {{/attributes.description}} + {{^attributes.description}} + No description + {{/attributes.description}} +

    + +
    - {{^attributes.owner}} {{#authed}} + {{^currentUser}} {{^attributes.following}} - - + {{/attributes.following}} {{#attributes.following}} - {{/attributes.following}} - {{/authed}} - {{/attributes.owner}} + {{/currentUser}} - {{^authed}} - + {{/authed}} - {{/authed}} - {{#attributes.owner}} + {{^authed}} + {{/authed}} - {{/attributes.owner}} + {{#currentUser}} + + {{/currentUser}}
    - -
    - -
    -
    - - {{/apis}} -
  • - No more APIs -
  • - {{^apis}} -
    - This user has no API's +
    - {{/apis}} - \ No newline at end of file +
    + + {{/apis}} + {{#apis.length}} +
  • No more APIs
  • + {{/apis.length}} + From 10d4b19b015f139f060ce7054dbe7abca0eb8ed9 Mon Sep 17 00:00:00 2001 From: pospi Date: Thu, 31 Jan 2013 19:43:01 +1000 Subject: [PATCH 464/531] genericised inline modal functionality --- js/libs/modal/modal.js | 60 +++++++++++++++++++++++--------- templates/modals/inlineedit.html | 19 +++++----- 2 files changed, 51 insertions(+), 28 deletions(-) diff --git a/js/libs/modal/modal.js b/js/libs/modal/modal.js index e0976d6..f7359f7 100644 --- a/js/libs/modal/modal.js +++ b/js/libs/modal/modal.js @@ -1,53 +1,79 @@ -define(['jquery', 'form'], function ($, FormFactory) { +define(['jquery', 'mustache', 'form', 'text!templates/modals/inlineedit.html'], function ($, Mustache, FormFactory, inlineEditTpl) { var defaultOptions = { - + // inline : { + // from : $(ev.currentTarget), required. element to inline edit + // model : this.options.model, required. model to run the update on + // field : 'description', required. field to update in the model + // title : 'Edit description', title for inline edit dialog. Defaults to 'data-inline-title' attribute of 'from' element. + // value : 'value to prefill with', defaults to value of element to inline, or its text contents + // savetext : 'text for OK button', default 'Save' + // canceltext : 'text for cancel button' default 'Cancel' + // } }; var modal = function (options) { var options = $.extend({}, defaultOptions, options), that = this; - + // add overlay this.overlay = $('
    '); this.overlay.addClass('overlay') $('body').append(this.overlay); + // create container element this.el = $('
    '); - this.el.html(options.content); this.el.addClass('modal') this.el.css({visibility: 'hidden'}); + // set contents as appropriate + if (options.content) { + this.el.html(options.content); + } else if (options.inline) { + var from = $(options.inline.from); + this.el.html(Mustache.render(inlineEditTpl, { + title : options.inline.title || from.attr('data-inline-title') || 'Edit field', + value : $.trim(options.inline.value || from.val() || from.text()), + savetext : options.inline.savetext || 'Save', + canceltext : options.inline.canceltext || 'Cancel' + })); + } + + // append to DOM $('body').append(this.el); - - + // position onscreen depending on modal type if(options.inline) { - var from = options.inline.from; - var to = $(options.inline.to, this.el); - var fromTop = $(from).offset().top; - var fromLeft = $(from).offset().left; - $(to).css({ + var to = $(".inline-field", this.el), + fromTop = from.offset().top, + fromLeft = from.offset().left, + toTop = this.el.offset().top - to.offset().top, + toLeft = this.el.offset().left - to.offset().left; + + to.css({ width: from.width(), height: from.height() }); - var toTop = $(this.el).offset().top - $(to).offset().top; - var toLeft = $(this.el).offset().left - $(to).offset().left; - $(this.el).css({ + + this.el.css({ top: fromTop + toTop, left: fromLeft + toLeft, position: 'absolute' - }) + }); } else { $(this.el).css({ 'margin-left': -($(this.el).width() / 2) + 'px' }); } - this.el.css({visibility: 'visible'}); - // bind form controller if one is specified in options if (options.form) { this.form = FormFactory.create($(options.form.element, this.el), options.form.model, options.form); } + // otherwise, bind submit event for inline modals + else if (options.inline && options.inline.model) { + this.form = FormFactory.create($('form.inline-edit', this.el), options.inline.model, options.inline.form || {}); + } + + this.el.css({visibility: 'visible'}); }; diff --git a/templates/modals/inlineedit.html b/templates/modals/inlineedit.html index 6a8f880..67f1a9f 100644 --- a/templates/modals/inlineedit.html +++ b/templates/modals/inlineedit.html @@ -1,22 +1,19 @@ -
    - + - -
    \ No newline at end of file + From 494812549bd53ece878e9b9811682793deb9c514 Mon Sep 17 00:00:00 2001 From: pospi Date: Thu, 31 Jan 2013 19:53:50 +1000 Subject: [PATCH 465/531] allow refactoring error message definitions out of main form templates for re-use in inline modals --- js/libs/modal/modal.js | 5 ++++- templates/modals/inlineedit.html | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/js/libs/modal/modal.js b/js/libs/modal/modal.js index f7359f7..9fd9796 100644 --- a/js/libs/modal/modal.js +++ b/js/libs/modal/modal.js @@ -4,8 +4,10 @@ define(['jquery', 'mustache', 'form', 'text!templates/modals/inlineedit.html'], // from : $(ev.currentTarget), required. element to inline edit // model : this.options.model, required. model to run the update on // field : 'description', required. field to update in the model - // title : 'Edit description', title for inline edit dialog. Defaults to 'data-inline-title' attribute of 'from' element. // value : 'value to prefill with', defaults to value of element to inline, or its text contents + // errordef : string A block of markup to inflate into the dialog's error handler div for handling of serverside errors. + // Edits which could result in any kind of client error should provide this field to avoid having the global error handler called. + // title : 'Edit description', title for inline edit dialog. Defaults to 'data-inline-title' attribute of 'from' element. // savetext : 'text for OK button', default 'Save' // canceltext : 'text for cancel button' default 'Cancel' // } @@ -32,6 +34,7 @@ define(['jquery', 'mustache', 'form', 'text!templates/modals/inlineedit.html'], this.el.html(Mustache.render(inlineEditTpl, { title : options.inline.title || from.attr('data-inline-title') || 'Edit field', value : $.trim(options.inline.value || from.val() || from.text()), + errordef : options.inline.errordef || '', savetext : options.inline.savetext || 'Save', canceltext : options.inline.canceltext || 'Cancel' })); diff --git a/templates/modals/inlineedit.html b/templates/modals/inlineedit.html index 67f1a9f..d10db64 100644 --- a/templates/modals/inlineedit.html +++ b/templates/modals/inlineedit.html @@ -5,7 +5,7 @@ From bb0b35c8f048f9a9a53d14a730babaecc53f785c Mon Sep 17 00:00:00 2001 From: pospi Date: Thu, 31 Jan 2013 19:56:27 +1000 Subject: [PATCH 466/531] refactor various pages to use new mechanisms --- js/views/apis/details.js | 29 +++++------------------- js/views/apis/documentation.js | 27 ++++------------------ js/views/settings/account.js | 5 ++-- templates/settings/account-errordef.html | 5 ++++ templates/settings/account.html | 4 +--- 5 files changed, 20 insertions(+), 50 deletions(-) create mode 100644 templates/settings/account-errordef.html diff --git a/js/views/apis/details.js b/js/views/apis/details.js index 0187908..fb12cee 100644 --- a/js/views/apis/details.js +++ b/js/views/apis/details.js @@ -18,10 +18,9 @@ define([ 'libs/highlight/highlight', 'views/forms/resource', 'modal', - 'text!templates/modals/inlineedit.html', 'views/apis/overview', 'views/apis/tablelist' -], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, apiDetailsTemplate, ApiModel, MethodsCollection, ResourceListView, MethodDetailView, ApiModel, ResourceModel, MethodModel, hljs, ResourceForm, Modal, edt, OverView, TableList){ +], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, apiDetailsTemplate, ApiModel, MethodsCollection, ResourceListView, MethodDetailView, ApiModel, ResourceModel, MethodModel, hljs, ResourceForm, Modal, OverView, TableList){ var NewApiPage = Backbone.View.extend({ el: '.page', initialize: function () { @@ -31,33 +30,17 @@ define([ events: { 'click .js-new-resource': 'newResource', 'click .js-new-method': 'newMethod', - 'click .api-description': 'editDescription' + 'click .edit-api-description': 'editDescription' }, editDescription: function(ev) { var modal = Modal.create({ - content: edt, inline: { - from: $(ev.currentTarget), - to: '.xx' + from : $(ev.currentTarget), + model : this.options.model, + field : 'description' } }); - $('.editdescription').on('submit', function(ev) { - console.log('asd'); - var api = new ApiModel({ - username: 'thomasdavis', - apiname: 'ApiEngine', - version: 1 - }); - var apiDetails = $(ev.currentTarget).serializeObject(); - apiDetails.name = 'ApiEngine'; - api.save(apiDetails, { - success: function (model) { - - } - }) - return false; - }); - window.modal = modal; + modal.show(); }, newResource: function () { var resourceForm = Vm.create(this, 'resourceform', ResourceForm, { diff --git a/js/views/apis/documentation.js b/js/views/apis/documentation.js index c7a0143..e832e8a 100644 --- a/js/views/apis/documentation.js +++ b/js/views/apis/documentation.js @@ -18,11 +18,10 @@ define([ 'libs/highlight/highlight', 'views/forms/resource', 'modal', - 'text!templates/modals/inlineedit.html', 'views/apis/overview', 'views/modals/newmethod', 'views/modals/newresource', -], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, docsTemplate, ApiModel, MethodsCollection, ResourceListView, MethodDetailView, ApiModel, ResourceModel, MethodModel, hljs, ResourceForm, Modal, edt, OverView, NewMethod, NewResource){ +], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, docsTemplate, ApiModel, MethodsCollection, ResourceListView, MethodDetailView, ApiModel, ResourceModel, MethodModel, hljs, ResourceForm, Modal, OverView, NewMethod, NewResource){ var NewApiPage = Backbone.View.extend({ el: '.api-page-container', initialize: function () { @@ -36,29 +35,13 @@ define([ }, editDescription: function(ev) { var modal = Modal.create({ - content: edt, inline: { - from: $(ev.currentTarget), - to: '.xx' + from : $(ev.currentTarget), + model : this.options.model, + field : 'description' } }); - $('.editdescription').on('submit', function(ev) { - console.log('asd'); - var api = new ApiModel({ - username: 'thomasdavis', - apiname: 'ApiEngine', - version: 1 - }); - var apiDetails = $(ev.currentTarget).serializeObject(); - apiDetails.name = 'ApiEngine'; - api.save(apiDetails, { - success: function (model) { - - } - }) - return false; - }); - window.modal = modal; + modal.show(); }, newResource: function () { console.log(this.options); diff --git a/js/views/settings/account.js b/js/views/settings/account.js index c89d1fb..3097955 100644 --- a/js/views/settings/account.js +++ b/js/views/settings/account.js @@ -9,9 +9,10 @@ define([ 'modal', 'form', 'text!templates/settings/account.html', + 'text!templates/settings/account-errordef.html', 'text!templates/modals/deleteaccount.html', 'models/account' -], function($, _, Backbone, Mustache, Router, Vm, Session, Modal, FormFactory, settingTemplate, confirmTemplate, AccountModel){ +], function($, _, Backbone, Mustache, Router, Vm, Session, Modal, FormFactory, settingTemplate, errorDefs, confirmTemplate, AccountModel){ var SettingPage = Backbone.View.extend({ el: '.settings-page-container', initialize: function () { @@ -22,7 +23,7 @@ define([ render: function (options) { $('.settings-menu a').removeClass('active'); $('.settings-menu .account').addClass('active'); - this.$el.html(Mustache.render(settingTemplate, {user : Session.get('user')})); + this.$el.html(Mustache.render(settingTemplate, {user : Session.get('user'), errordef : errorDefs})); this.form = FormFactory.create($('form.update-account'), new AccountModel({ login : Session.get('login'), diff --git a/templates/settings/account-errordef.html b/templates/settings/account-errordef.html new file mode 100644 index 0000000..1b64c6b --- /dev/null +++ b/templates/settings/account-errordef.html @@ -0,0 +1,5 @@ + + + + + diff --git a/templates/settings/account.html b/templates/settings/account.html index ecbd530..14e5a4d 100644 --- a/templates/settings/account.html +++ b/templates/settings/account.html @@ -4,9 +4,7 @@
    - - - + {{errordef}}
    From 9714b2d32ce4f7d3ef12ecc3e07f51228a3199b1 Mon Sep 17 00:00:00 2001 From: pospi Date: Thu, 31 Jan 2013 20:16:30 +1000 Subject: [PATCH 467/531] stop double logging of 5xx error codes --- js/libs/form/form.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/js/libs/form/form.js b/js/libs/form/form.js index dc5bc04..134c12d 100644 --- a/js/libs/form/form.js +++ b/js/libs/form/form.js @@ -303,14 +303,16 @@ define(['require', 'jquery', 'underscore', 'mustache', 'models/error'], function modal.show(); // log to server - var error = new ErrorModel(); - error.save({ - "page": window.location.href, - "context": that.model.url(), - "code": xhr ? xhr.status : 0, - "error": "Error key '" + code + "' is unhandled in the UI", - "payload": _.clone(that.model.attributes) - }, {}); + if (xhr.status < 500 || xhr.status >= 600) { + var error = new ErrorModel(); + error.save({ + "page": window.location.href, + "context": that.model.url(), + "code": xhr ? xhr.status : 0, + "error": "Error key '" + code + "' is unhandled in the UI", + "payload": _.clone(that.model.attributes) + }, {}); + } } ); }; From 6cb3a141d97b8b08819ec419dcd5d5ff6c91e3d1 Mon Sep 17 00:00:00 2001 From: pospi Date: Thu, 31 Jan 2013 20:17:17 +1000 Subject: [PATCH 468/531] send correct field name to backend when using inline modals --- js/libs/modal/modal.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/js/libs/modal/modal.js b/js/libs/modal/modal.js index 9fd9796..efd208b 100644 --- a/js/libs/modal/modal.js +++ b/js/libs/modal/modal.js @@ -72,8 +72,19 @@ define(['jquery', 'mustache', 'form', 'text!templates/modals/inlineedit.html'], this.form = FormFactory.create($(options.form.element, this.el), options.form.model, options.form); } // otherwise, bind submit event for inline modals - else if (options.inline && options.inline.model) { - this.form = FormFactory.create($('form.inline-edit', this.el), options.inline.model, options.inline.form || {}); + else if (options.inline && options.inline.model && options.inline.field) { + this.form = FormFactory.create($('form.inline-edit', this.el), options.inline.model, $.extend({ + onPreValidate : function(attribs) { + attribs[options.inline.field] = attribs.field; + delete attribs.field; + + if (options.inline.form && options.inline.form.onPreValidate) { + attribs = options.inline.form.onPreValidate.call(that.form, attribs); + } + + return attribs; + } + }, options.inline.form || {})); } this.el.css({visibility: 'visible'}); From 21598a0fa76e4abee03ee9aee1edc9635566c088 Mon Sep 17 00:00:00 2001 From: pospi Date: Thu, 31 Jan 2013 20:18:14 +1000 Subject: [PATCH 469/531] provide a means of converting API summary responses into Api records for updating --- js/models/api-overview.js | 11 +++++++++++ js/views/apis/details.js | 2 +- js/views/apis/documentation.js | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/js/models/api-overview.js b/js/models/api-overview.js index 1b87934..8ce743c 100644 --- a/js/models/api-overview.js +++ b/js/models/api-overview.js @@ -7,6 +7,17 @@ define([ idAttribute: 'apiname', url: function () { return '/user/' +this.get('username')+ '/api/' +this.get('apiname') + '/' +this.get('version') + '/summary'; + }, + + toApi : function() { + return new Api({ + username : this.get('username'), + apiname : this.get('apiname'), + version : this.get('version'), + label : this.get('label'), + baseurl : this.get('baseurl'), + index : this.get('index') + }); } }); return ApiModel; diff --git a/js/views/apis/details.js b/js/views/apis/details.js index fb12cee..13bb9fa 100644 --- a/js/views/apis/details.js +++ b/js/views/apis/details.js @@ -36,7 +36,7 @@ define([ var modal = Modal.create({ inline: { from : $(ev.currentTarget), - model : this.options.model, + model : this.options.model.toApi(), field : 'description' } }); diff --git a/js/views/apis/documentation.js b/js/views/apis/documentation.js index e832e8a..11b68f5 100644 --- a/js/views/apis/documentation.js +++ b/js/views/apis/documentation.js @@ -37,7 +37,7 @@ define([ var modal = Modal.create({ inline: { from : $(ev.currentTarget), - model : this.options.model, + model : this.options.model.toApi(), field : 'description' } }); From f678ad8fcce517cad74e8b08ee9ab9d779b76c38 Mon Sep 17 00:00:00 2001 From: pospi Date: Thu, 31 Jan 2013 20:24:39 +1000 Subject: [PATCH 470/531] bind form success and error callbacks to the form instance to allow calling default handlers --- js/libs/form/form.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/libs/form/form.js b/js/libs/form/form.js index 134c12d..410d5be 100644 --- a/js/libs/form/form.js +++ b/js/libs/form/form.js @@ -183,7 +183,7 @@ define(['require', 'jquery', 'underscore', 'mustache', 'models/error'], function // fire custom success callback instead of default one if present if (that.options && that.options.success) { - that.options.success(model, response, options); + that.options.success.call(that, model, response, options); } else { that.showSuccess(); } @@ -197,7 +197,7 @@ define(['require', 'jquery', 'underscore', 'mustache', 'models/error'], function } catch (e) {} if (that.options && that.options.error) { // fire custom error callback if present - that.options.error(model, responseJSON, options); + that.options.error.call(that, model, responseJSON, options); } else if ($.isPlainObject(responseJSON)) { // if response was OK, attempt to throw it as an API error that.handleAPIError(xhr, responseJSON, options); } else { // otherwise throw up to global error handler From 99b334b08b879427068aec80cf984f086c47f92a Mon Sep 17 00:00:00 2001 From: pospi Date: Thu, 31 Jan 2013 20:24:55 +1000 Subject: [PATCH 471/531] cleanup form with modals? --- js/libs/modal/modal.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/libs/modal/modal.js b/js/libs/modal/modal.js index efd208b..66c737a 100644 --- a/js/libs/modal/modal.js +++ b/js/libs/modal/modal.js @@ -102,6 +102,7 @@ define(['jquery', 'mustache', 'form', 'text!templates/modals/inlineedit.html'], that.el.remove(); that.overlay.remove(); + delete that.form; delete that; }); }; From 8763e573398926e825578f532bace5500271a6ad Mon Sep 17 00:00:00 2001 From: pospi Date: Thu, 31 Jan 2013 20:25:38 +1000 Subject: [PATCH 472/531] navigate to homepage after logging out --- js/views/settings/account.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/views/settings/account.js b/js/views/settings/account.js index 3097955..b50be5a 100644 --- a/js/views/settings/account.js +++ b/js/views/settings/account.js @@ -84,6 +84,8 @@ define([ that.modal.hide(); // logout Session.logout(); + // go back to homepage + Backbone.router.navigate('/'); } } }); From 102f712f269f38cd57767176531a0292a1cad9d3 Mon Sep 17 00:00:00 2001 From: pospi Date: Thu, 31 Jan 2013 20:27:12 +1000 Subject: [PATCH 473/531] whitespace fixes --- js/views/apis/list.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js/views/apis/list.js b/js/views/apis/list.js index e446cc8..e8e2faf 100644 --- a/js/views/apis/list.js +++ b/js/views/apis/list.js @@ -13,7 +13,7 @@ define([ el: '.private-container', initialize: function () { var that = this; - + $('body').on('hover', '.js-following', function (ev) { var button = $(ev.currentTarget); if(ev.type === 'mouseenter') { @@ -74,7 +74,7 @@ define([ console.log(apiData, 'headache'); var apiModel = new ApiModel(); apiModel.set({username: Session.get('login')}); - if(apiData.private === 'true') { + if(apiData.private === 'true') { apiData.private = true; } else { apiData.private = false; @@ -96,7 +96,7 @@ define([ console.log(this.options.username, 'asdasdasd'); currentUser = false; console.log(Session.get('login'), that.options.username); - if(Session.get('login') === that.options.username && typeof Session.get('login') !== 'undefined') { + if(Session.get('login') === that.options.username && typeof Session.get('login') !== 'undefined') { currentUser = true; } console.log(currentUser); @@ -109,7 +109,7 @@ define([ } }); - + } }); return ApisPage; From 3df639c2a11ebb7e0019f14c33afa936a2d95b4f Mon Sep 17 00:00:00 2001 From: pospi Date: Thu, 31 Jan 2013 20:28:53 +1000 Subject: [PATCH 474/531] handle inline modal success --- js/libs/modal/modal.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/js/libs/modal/modal.js b/js/libs/modal/modal.js index 66c737a..bd45263 100644 --- a/js/libs/modal/modal.js +++ b/js/libs/modal/modal.js @@ -83,6 +83,17 @@ define(['jquery', 'mustache', 'form', 'text!templates/modals/inlineedit.html'], } return attribs; + }, + success : function(model, response, options) { + try { + from.val(model.get(options.inline.field)); + } catch(e) { + from.text(model.get(options.inline.field)); + } + if (options.inline.form && options.inline.form.success) { + options.inline.form.success.call(this, model, response, options); + } + that.hide(); } }, options.inline.form || {})); } From 5b1d36458b0216940b0950170b8393aa6b6d28ce Mon Sep 17 00:00:00 2001 From: pospi Date: Fri, 1 Feb 2013 18:12:38 +1000 Subject: [PATCH 475/531] log errors as JSON instead of text --- js/libs/form/form.js | 7 ++++++- js/views/app.js | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/js/libs/form/form.js b/js/libs/form/form.js index 410d5be..afb1067 100644 --- a/js/libs/form/form.js +++ b/js/libs/form/form.js @@ -228,13 +228,18 @@ define(['require', 'jquery', 'underscore', 'mustache', 'models/error'], function // don't duplicate the global logging performed in app.js if (xhr.status < 500 || xhr.status >= 600) { + var responseJSON = xhr.responseText; + try { + responseJSON = JSON.parse(xhr.responseText); + } catch (e) {} + // log to server var error = new ErrorModel(); error.save({ "page": window.location.href, "context": this.model.url(), "code": xhr.status, - "error": xhr.responseText, + "error": responseJSON, "payload": _.clone(that.model.attributes) }, {}); } diff --git a/js/views/app.js b/js/views/app.js index e5f2b1a..65fd0ae 100644 --- a/js/views/app.js +++ b/js/views/app.js @@ -21,12 +21,17 @@ define([ // when no UI elements are found for handling a valid server error condition. $("body").ajaxError(function(ev, res, req) { if(res.status >= 500 && res.status <= 600) { + var responseJSON = xhr.responseText; + try { + responseJSON = JSON.parse(xhr.responseText); + } catch (e) {} + var error = new ErrorModel(); error.save({ "page": window.location.href, "context": req.type + ' ' + req.url, "code": res.status, - "error": res.responseText, + "error": responseJSON, "payload": req.data }, {}); } From 25039841b704ef1e09660c8128d853f3a34c9b5c Mon Sep 17 00:00:00 2001 From: pospi Date: Fri, 1 Feb 2013 18:40:30 +1000 Subject: [PATCH 476/531] prevent unhandled server errors masking the real cause of an error --- js/libs/form/form.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/js/libs/form/form.js b/js/libs/form/form.js index afb1067..8b21811 100644 --- a/js/libs/form/form.js +++ b/js/libs/form/form.js @@ -135,7 +135,7 @@ define(['require', 'jquery', 'underscore', 'mustache', 'models/error'], function invalidCount++; $.each(v, function(k2, errCode) { if (!that.showError(fldName, errCode)) { - that.handleNonConfiguredError(fldName, null, errCode); + that.handleNonConfiguredError(fldName, null, errCode, null); } }); } @@ -260,12 +260,12 @@ define(['require', 'jquery', 'underscore', 'mustache', 'models/error'], function } $.each(fields, function(k, fld) { if (!that.showError(fld, errCode)) { - that.handleNonConfiguredError(fld, xhr, errCode, response.message); + that.handleNonConfiguredError(fld, xhr, errCode, response); } }); } else { if (!this.showError(null, errCode)) { - this.handleNonConfiguredError(null, xhr, errCode, response.message); + this.handleNonConfiguredError(null, xhr, errCode, response); } } }; @@ -290,7 +290,7 @@ define(['require', 'jquery', 'underscore', 'mustache', 'models/error'], function errorLbl.css('display', 'block'); return true; }; - form.prototype.handleNonConfiguredError = function(field, xhr, code, msg) + form.prototype.handleNonConfiguredError = function(field, xhr, code, response) { var that = this; require(['modal', 'text!templates/modals/error.html'], @@ -300,7 +300,7 @@ define(['require', 'jquery', 'underscore', 'mustache', 'models/error'], function errorHTML = Mustache.render(errorTemplate, { apiError : true, code : code, - message : msg ? msg : "Unknown error code " + code + message : (response && response.message) ? response.message : "Unknown error code " + code }); modal = Modal.create({ content: errorHTML @@ -314,7 +314,10 @@ define(['require', 'jquery', 'underscore', 'mustache', 'models/error'], function "page": window.location.href, "context": that.model.url(), "code": xhr ? xhr.status : 0, - "error": "Error key '" + code + "' is unhandled in the UI", + "error": { + "unhandled" : true, + "response" : response + }, "payload": _.clone(that.model.attributes) }, {}); } From e8a1ee27f3181b38099a080c0236b68e7850707d Mon Sep 17 00:00:00 2001 From: pospi Date: Sat, 2 Feb 2013 18:43:29 +1000 Subject: [PATCH 477/531] restructured error logging mechanisms again for backend compatibility --- js/libs/form/form.js | 10 +++++----- js/views/app.js | 7 +++++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/js/libs/form/form.js b/js/libs/form/form.js index 8b21811..0552882 100644 --- a/js/libs/form/form.js +++ b/js/libs/form/form.js @@ -314,11 +314,11 @@ define(['require', 'jquery', 'underscore', 'mustache', 'models/error'], function "page": window.location.href, "context": that.model.url(), "code": xhr ? xhr.status : 0, - "error": { - "unhandled" : true, - "response" : response - }, - "payload": _.clone(that.model.attributes) + "error": "Error key '" + code + "' is unhandled in the UI", + "payload": { + sent : _.clone(that.model.attributes), + received : response + } }, {}); } } diff --git a/js/views/app.js b/js/views/app.js index 65fd0ae..3eb81ce 100644 --- a/js/views/app.js +++ b/js/views/app.js @@ -31,8 +31,11 @@ define([ "page": window.location.href, "context": req.type + ' ' + req.url, "code": res.status, - "error": responseJSON, - "payload": req.data + "error": "Internal API error", + "payload": { + sent : req.data, + received : responseJSON + } }, {}); } console.log(arguments); From 85848cff14415775fce6d995d09c04b272233549 Mon Sep 17 00:00:00 2001 From: pospi Date: Sat, 2 Feb 2013 18:45:14 +1000 Subject: [PATCH 478/531] inject error blocks into forms correctly --- js/libs/modal/modal.js | 3 ++- js/views/settings/account.js | 2 +- templates/modals/inlineedit.html | 2 +- templates/settings/account.html | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/js/libs/modal/modal.js b/js/libs/modal/modal.js index bd45263..70fcc5f 100644 --- a/js/libs/modal/modal.js +++ b/js/libs/modal/modal.js @@ -34,9 +34,10 @@ define(['jquery', 'mustache', 'form', 'text!templates/modals/inlineedit.html'], this.el.html(Mustache.render(inlineEditTpl, { title : options.inline.title || from.attr('data-inline-title') || 'Edit field', value : $.trim(options.inline.value || from.val() || from.text()), - errordef : options.inline.errordef || '', savetext : options.inline.savetext || 'Save', canceltext : options.inline.canceltext || 'Cancel' + }, { + errordef : options.inline.errordef || '' })); } diff --git a/js/views/settings/account.js b/js/views/settings/account.js index b50be5a..f9262f0 100644 --- a/js/views/settings/account.js +++ b/js/views/settings/account.js @@ -23,7 +23,7 @@ define([ render: function (options) { $('.settings-menu a').removeClass('active'); $('.settings-menu .account').addClass('active'); - this.$el.html(Mustache.render(settingTemplate, {user : Session.get('user'), errordef : errorDefs})); + this.$el.html(Mustache.render(settingTemplate, {user : Session.get('user')}, {errordef : errorDefs})); this.form = FormFactory.create($('form.update-account'), new AccountModel({ login : Session.get('login'), diff --git a/templates/modals/inlineedit.html b/templates/modals/inlineedit.html index d10db64..3752950 100644 --- a/templates/modals/inlineedit.html +++ b/templates/modals/inlineedit.html @@ -5,7 +5,7 @@ diff --git a/templates/settings/account.html b/templates/settings/account.html index 14e5a4d..1bf98c4 100644 --- a/templates/settings/account.html +++ b/templates/settings/account.html @@ -4,7 +4,7 @@
    - {{errordef}} + {{>errordef}}
    From 49d6013801da0581d30a4df2a6c5fd74cef17007 Mon Sep 17 00:00:00 2001 From: pospi Date: Sat, 2 Feb 2013 19:43:15 +1000 Subject: [PATCH 479/531] remove cruft --- js/views/apis/details.js | 3 +-- js/views/apis/documentation.js | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/js/views/apis/details.js b/js/views/apis/details.js index 13bb9fa..e2d7675 100644 --- a/js/views/apis/details.js +++ b/js/views/apis/details.js @@ -12,7 +12,6 @@ define([ 'collections/methods', 'views/resource/list', 'views/methods/details', - 'models/api', 'models/resource', 'models/method', 'libs/highlight/highlight', @@ -20,7 +19,7 @@ define([ 'modal', 'views/apis/overview', 'views/apis/tablelist' -], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, apiDetailsTemplate, ApiModel, MethodsCollection, ResourceListView, MethodDetailView, ApiModel, ResourceModel, MethodModel, hljs, ResourceForm, Modal, OverView, TableList){ +], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, apiDetailsTemplate, ApiModel, MethodsCollection, ResourceListView, MethodDetailView, ResourceModel, MethodModel, hljs, ResourceForm, Modal, OverView, TableList){ var NewApiPage = Backbone.View.extend({ el: '.page', initialize: function () { diff --git a/js/views/apis/documentation.js b/js/views/apis/documentation.js index 11b68f5..6eb2154 100644 --- a/js/views/apis/documentation.js +++ b/js/views/apis/documentation.js @@ -12,7 +12,6 @@ define([ 'collections/methods', 'views/resource/list', 'views/methods/details', - 'models/api', 'models/resource', 'models/method', 'libs/highlight/highlight', @@ -21,7 +20,7 @@ define([ 'views/apis/overview', 'views/modals/newmethod', 'views/modals/newresource', -], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, docsTemplate, ApiModel, MethodsCollection, ResourceListView, MethodDetailView, ApiModel, ResourceModel, MethodModel, hljs, ResourceForm, Modal, OverView, NewMethod, NewResource){ +], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, docsTemplate, ApiModel, MethodsCollection, ResourceListView, MethodDetailView, ResourceModel, MethodModel, hljs, ResourceForm, Modal, OverView, NewMethod, NewResource){ var NewApiPage = Backbone.View.extend({ el: '.api-page-container', initialize: function () { From a9a43b5fb9d22e65b08d809ba2dae3cbea314c2f Mon Sep 17 00:00:00 2001 From: pospi Date: Sat, 2 Feb 2013 19:52:25 +1000 Subject: [PATCH 480/531] added autogrow plugin and setup inline editor modal to grow as needed for entry --- js/libs/autogrow/autogrow.js | 54 ++++++++++++++++++++++++++++++++++++ js/libs/modal/modal.js | 4 ++- js/main.js | 5 +++- 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 js/libs/autogrow/autogrow.js diff --git a/js/libs/autogrow/autogrow.js b/js/libs/autogrow/autogrow.js new file mode 100644 index 0000000..6f9fac7 --- /dev/null +++ b/js/libs/autogrow/autogrow.js @@ -0,0 +1,54 @@ +define(['jquery'], function($) { + /** + * Auto-growing textareas; technique ripped from Facebook + * + * http://github.com/jaz303/jquery-grab-bag/tree/master/javascripts/jquery.autogrow-textarea.js + */ + $.fn.autogrow = function(options) + { + return this.filter('textarea').each(function() + { + var self = this; + var $self = $(self); + var minHeight = $self.height(); + var noFlickerPad = $self.hasClass('autogrow-short') ? 0 : parseInt($self.css('lineHeight')); + + var shadow = $('
    ').css({ + position: 'absolute', + top: -10000, + left: -10000, + width: $self.width(), + fontSize: $self.css('fontSize'), + fontFamily: $self.css('fontFamily'), + fontWeight: $self.css('fontWeight'), + lineHeight: $self.css('lineHeight'), + resize: 'none' + }).appendTo(document.body); + + var update = function() + { + var times = function(string, number) + { + for (var i=0, r=''; i/g, '>') + .replace(/&/g, '&') + .replace(/\n$/, '
     ') + .replace(/\n/g, '
    ') + .replace(/ {2,}/g, function(space){ return times(' ', space.length - 1) + ' ' }); + + shadow.css('width', $self.width()); + shadow.html(val); + $self.css('height', Math.max(shadow.height() + noFlickerPad, minHeight)); + } + + $self.change(update).keyup(update).keydown(update); + $(window).resize(update); + + update(); + }); + }; +}); diff --git a/js/libs/modal/modal.js b/js/libs/modal/modal.js index 70fcc5f..617437f 100644 --- a/js/libs/modal/modal.js +++ b/js/libs/modal/modal.js @@ -1,4 +1,4 @@ -define(['jquery', 'mustache', 'form', 'text!templates/modals/inlineedit.html'], function ($, Mustache, FormFactory, inlineEditTpl) { +define(['jquery', 'autogrow', 'mustache', 'form', 'text!templates/modals/inlineedit.html'], function ($, nothing, Mustache, FormFactory, inlineEditTpl) { var defaultOptions = { // inline : { // from : $(ev.currentTarget), required. element to inline edit @@ -62,6 +62,8 @@ define(['jquery', 'mustache', 'form', 'text!templates/modals/inlineedit.html'], left: fromLeft + toLeft, position: 'absolute' }); + + to.autogrow().focus(); } else { $(this.el).css({ 'margin-left': -($(this.el).width() / 2) + 'px' diff --git a/js/main.js b/js/main.js index 63b5385..04984eb 100644 --- a/js/main.js +++ b/js/main.js @@ -10,10 +10,13 @@ require.config({ qtip: 'libs/qtip2/jquery.qtip.min', marked: 'libs/marked/marked', mustache: 'https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.7.0/mustache.min', + // APIe modal: 'libs/modal/modal', form: 'libs/form/form', // Require.js plugins text: 'libs/require/text', + // jquery plugins + autogrow : 'libs/autogrow/autogrow', // Just a short cut so we can put our html outside the js dir // When you have HTML/CSS designers this aids in keeping them out of the js directory @@ -40,7 +43,7 @@ require([ Proxino.track_errors(); var appView = Vm.create({}, 'AppView', AppView); - + Router.initialize({appView: appView}); appView.render(); // render() calls Backbone.history when its ready to start From d002f4a06540662df43e415bf850c20b127e23a3 Mon Sep 17 00:00:00 2001 From: pospi Date: Sat, 2 Feb 2013 20:01:44 +1000 Subject: [PATCH 481/531] fix autoselection code for inline modals, should be done on showing them --- js/libs/modal/modal.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/js/libs/modal/modal.js b/js/libs/modal/modal.js index 617437f..03cf85a 100644 --- a/js/libs/modal/modal.js +++ b/js/libs/modal/modal.js @@ -63,7 +63,7 @@ define(['jquery', 'autogrow', 'mustache', 'form', 'text!templates/modals/inlinee position: 'absolute' }); - to.autogrow().focus(); + to.autogrow(); } else { $(this.el).css({ 'margin-left': -($(this.el).width() / 2) + 'px' @@ -76,6 +76,8 @@ define(['jquery', 'autogrow', 'mustache', 'form', 'text!templates/modals/inlinee } // otherwise, bind submit event for inline modals else if (options.inline && options.inline.model && options.inline.field) { + this.inline = true; + this.form = FormFactory.create($('form.inline-edit', this.el), options.inline.model, $.extend({ onPreValidate : function(attribs) { attribs[options.inline.field] = attribs.field; @@ -102,11 +104,13 @@ define(['jquery', 'autogrow', 'mustache', 'form', 'text!templates/modals/inlinee } this.el.css({visibility: 'visible'}); - }; modal.prototype.show = function () { - this.el.addClass('shown') + this.el.addClass('shown'); + if (this.inline) { + $(".inline-field", this.el).focus().select(); + } }; modal.prototype.hide = function (animation) { From bf45e7426f0066078177d2db49a0208d1017c535 Mon Sep 17 00:00:00 2001 From: pospi Date: Sat, 2 Feb 2013 20:22:26 +1000 Subject: [PATCH 482/531] added a main app configuration flag to enable use of CDNs and alter main HTML file, since I just got capped --- index.html | 5 +++-- js/libs/modal/modal.js | 4 ++-- js/main.js | 12 +++++++----- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/index.html b/index.html index 7958fdd..a6683c3 100644 --- a/index.html +++ b/index.html @@ -9,7 +9,8 @@ - + + - + diff --git a/js/libs/modal/modal.js b/js/libs/modal/modal.js index 03cf85a..22410d1 100644 --- a/js/libs/modal/modal.js +++ b/js/libs/modal/modal.js @@ -49,8 +49,8 @@ define(['jquery', 'autogrow', 'mustache', 'form', 'text!templates/modals/inlinee var to = $(".inline-field", this.el), fromTop = from.offset().top, fromLeft = from.offset().left, - toTop = this.el.offset().top - to.offset().top, - toLeft = this.el.offset().left - to.offset().left; + toTop = this.el.offset().top - to.offset().top - parseInt(to.css('padding-top')), + toLeft = this.el.offset().left - to.offset().left - parseInt(to.css('padding-left')); to.css({ width: from.width(), diff --git a/js/main.js b/js/main.js index 04984eb..5eaf42f 100644 --- a/js/main.js +++ b/js/main.js @@ -1,15 +1,17 @@ -// Require.js allows us to configure shortcut alias -// Their usage will become more apparent futher along in the tutorial. +// Main application flags +var USE_CDNS = false; + +// require.js path aliases require.config({ paths: { // Major libraries - jquery: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.min', - underscore: 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.9.2/lodash.min', // https://github.com/amdjs + jquery: USE_CDNS ? 'https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.min' : 'libs/jquery/jquery-min', + underscore: USE_CDNS ? 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.9.2/lodash.min' : 'libs/underscore/underscore-min', // https://github.com/amdjs backbone: 'libs/backbone/backbone-min', // https://github.com/amdjs prettyprint: 'libs/prettyprint/prettyprint', qtip: 'libs/qtip2/jquery.qtip.min', marked: 'libs/marked/marked', - mustache: 'https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.7.0/mustache.min', + mustache: USE_CDNS ? 'https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.7.0/mustache.min' : 'libs/mustache/mustache', // APIe modal: 'libs/modal/modal', form: 'libs/form/form', From 9d8adf769f1d0a3c9cbde3926015d90899f75ef1 Mon Sep 17 00:00:00 2001 From: pospi Date: Sat, 2 Feb 2013 20:30:15 +1000 Subject: [PATCH 483/531] spent some time on modal prettiness which I think Rich will appreciate --- css/modal.css | 10 ++++++++++ js/libs/modal/modal.js | 17 ++++++++++------- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/css/modal.css b/css/modal.css index 66eea62..4f93aa2 100644 --- a/css/modal.css +++ b/css/modal.css @@ -36,6 +36,16 @@ left: 50%; border: 1px solid #ebebeb; z-index: 4; + visibility: hidden; + opacity: 0; + transition: opacity .3s; + -moz-transition: opacity .3s; + -webkit-transition: opacity .3s; + -o-transition: opacity .3s; +} +.modal.shown { + visibility: visible; + opacity: 1; } .modal-header { diff --git a/js/libs/modal/modal.js b/js/libs/modal/modal.js index 22410d1..f304394 100644 --- a/js/libs/modal/modal.js +++ b/js/libs/modal/modal.js @@ -23,8 +23,7 @@ define(['jquery', 'autogrow', 'mustache', 'form', 'text!templates/modals/inlinee // create container element this.el = $('
    '); - this.el.addClass('modal') - this.el.css({visibility: 'hidden'}); + this.el.addClass('modal'); // set contents as appropriate if (options.content) { @@ -49,12 +48,18 @@ define(['jquery', 'autogrow', 'mustache', 'form', 'text!templates/modals/inlinee var to = $(".inline-field", this.el), fromTop = from.offset().top, fromLeft = from.offset().left, - toTop = this.el.offset().top - to.offset().top - parseInt(to.css('padding-top')), - toLeft = this.el.offset().left - to.offset().left - parseInt(to.css('padding-left')); + toTop = this.el.offset().top - to.offset().top - + parseInt(to.css('padding-top')) + parseInt(from.css('padding-top')) - + (parseInt(to.css('border-top-width')) - parseInt(from.css('border-top-width'))), + toLeft = this.el.offset().left - to.offset().left - + parseInt(to.css('padding-left')) + parseInt(from.css('padding-left')) - + (parseInt(to.css('border-left-width')) - parseInt(from.css('border-left-width'))); to.css({ width: from.width(), - height: from.height() + height: from.height(), + fontSize : from.css('font-size'), + fontFamily : from.css('font-family') }); this.el.css({ @@ -102,8 +107,6 @@ define(['jquery', 'autogrow', 'mustache', 'form', 'text!templates/modals/inlinee } }, options.inline.form || {})); } - - this.el.css({visibility: 'visible'}); }; modal.prototype.show = function () { From b72b0e2e65b3657a566e149d7addaf3241cb41ea Mon Sep 17 00:00:00 2001 From: pospi Date: Sat, 2 Feb 2013 23:34:35 +1000 Subject: [PATCH 484/531] refactored api list template --- js/views/apis/list.js | 5 ++-- js/views/browse/page.js | 7 ++--- templates/apis/list-item.html | 49 ++++++++++++++++++++++++++++++++++ templates/apis/list.html | 50 +---------------------------------- templates/browse/list.html | 50 +---------------------------------- 5 files changed, 58 insertions(+), 103 deletions(-) diff --git a/js/views/apis/list.js b/js/views/apis/list.js index e8e2faf..e85b243 100644 --- a/js/views/apis/list.js +++ b/js/views/apis/list.js @@ -5,10 +5,11 @@ define([ 'mustache', 'models/session', 'text!templates/apis/list.html', + 'text!templates/apis/list-item.html', 'collections/apis', 'models/api', 'models/follower' -], function($, _, Backbone, Mustache, Session, apisListTemplate, ApisCollection, ApiModel, FollowerModel){ +], function($, _, Backbone, Mustache, Session, apisListTemplate, apisListItemTemplate, ApisCollection, ApiModel, FollowerModel){ var ApisPage = Backbone.View.extend({ el: '.private-container', initialize: function () { @@ -105,7 +106,7 @@ define([ }; apis.fetch({ success: function (collection) { - that.$el.html(Mustache.render(apisListTemplate, {authed: Session.get('auth'), currentUser: that.options.currentUser, _:_, is_public: that.options.is_public, apis: collection.models, username: Session.get('login'), location: that.options.location})); + that.$el.html(Mustache.render(apisListTemplate, {authed: Session.get('auth'), currentUser: that.options.currentUser, _:_, is_public: that.options.is_public, apis: collection.models, username: Session.get('login'), location: that.options.location}, {listtemplate: apisListItemTemplate})); } }); diff --git a/js/views/browse/page.js b/js/views/browse/page.js index 51e93ca..a31ac45 100644 --- a/js/views/browse/page.js +++ b/js/views/browse/page.js @@ -7,8 +7,9 @@ define([ 'text!templates/browse/page.html', 'collections/apis', 'text!templates/browse/list.html', + 'text!templates/apis/list-item.html', 'models/follower' -], function($, _, Backbone, Mustache, Session, browseTemplate, Apis, apiListTemplate, FollowerModel){ +], function($, _, Backbone, Mustache, Session, browseTemplate, Apis, apiListTemplate, apisListItemTemplate, FollowerModel){ var BrowseView = Backbone.View.extend({ el: '.page', initialize: function () { @@ -19,7 +20,7 @@ define([ } if(ev.type === 'mouseleave') { $(button).removeClass('btn-red').addClass('btn-green').text('FOLLOWING'); - + } }); }, @@ -77,7 +78,7 @@ define([ } return model; }); - $('.api-list-container').html(Mustache.render(apiListTemplate, {authed: Session.get('auth'), apis: apisl, _:_})); + $('.api-list-container').html(Mustache.render(apiListTemplate, {authed: Session.get('auth'), apis: apisl, _:_}, {listtemplate: apisListItemTemplate})); } }) } diff --git a/templates/apis/list-item.html b/templates/apis/list-item.html index e69de29..2b0f01b 100644 --- a/templates/apis/list-item.html +++ b/templates/apis/list-item.html @@ -0,0 +1,49 @@ +
  • + + +
    + + {{#authed}} + + {{^currentUser}} + {{^attributes.following}} + + {{/attributes.following}} + + {{#attributes.following}} + + {{/attributes.following}} + {{/currentUser}} + + {{/authed}} + + {{^authed}} + + {{/authed}} + + + {{#currentUser}} + + {{/currentUser}} +
    + +
    +
    +
  • diff --git a/templates/apis/list.html b/templates/apis/list.html index edc677e..3715674 100644 --- a/templates/apis/list.html +++ b/templates/apis/list.html @@ -13,55 +13,7 @@
      {{#apis}} -
    • - - -
      - - {{#authed}} - - {{^currentUser}} - {{^attributes.following}} - - {{/attributes.following}} - - {{#attributes.following}} - - {{/attributes.following}} - {{/currentUser}} - - {{/authed}} - - {{^authed}} - - {{/authed}} - - - {{#currentUser}} - - {{/currentUser}} -
      - -
      -
      -
    • + {{>listtemplate}} {{/apis}} {{#apis.length}}
    • No more APIs
    • diff --git a/templates/browse/list.html b/templates/browse/list.html index 9ca590f..68ff80e 100644 --- a/templates/browse/list.html +++ b/templates/browse/list.html @@ -1,54 +1,6 @@
        {{#apis}} -
      • - - -
        - - {{#authed}} - - {{^currentUser}} - {{^attributes.following}} - - {{/attributes.following}} - - {{#attributes.following}} - - {{/attributes.following}} - {{/currentUser}} - - {{/authed}} - - {{^authed}} - - {{/authed}} - - - {{#currentUser}} - - {{/currentUser}} -
        - -
        -
        -
      • + {{>listtemplate}} {{/apis}} {{#apis.length}}
      • No more APIs
      • From 640ada4ceca6de1eb86adf3db872d0c7c28c7907 Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 3 Feb 2013 01:12:48 +1000 Subject: [PATCH 485/531] added routes for activity streamse reduce API settings route to single pagee various file renaming and movements for clearer organisation to conventions. large-scale code de-duplication.e put global API view logic in base page and implement a loose hierarchy for calling parent methodse moved event bindings into appropriate views in the page hierarchy to make cross-page functionality more implicitly generice refactor tab highlighting behaviour and global API functionality to top-level page controllere whitespace --- js/router.js | 32 ++-- js/views/apis/collaborators.js | 9 +- js/views/apis/details.js | 153 ------------------ js/views/apis/documentation.js | 90 +++++------ js/views/apis/page.js | 153 ++++++++++-------- js/views/apis/settings.js | 13 +- js/views/methods/list.js | 10 +- js/views/methods/{details.js => page.js} | 12 +- js/views/notifications/list.js | 34 ++++ js/views/resource/page.js | 4 +- .../{overview.html => docs-overview.html} | 8 +- templates/apis/docs.html | 23 +++ templates/apis/documentation.html | 23 --- templates/apis/{details.html => page.html} | 4 +- templates/apis/settings.html | 0 templates/methods/{details.html => page.html} | 0 16 files changed, 241 insertions(+), 327 deletions(-) delete mode 100644 js/views/apis/details.js rename js/views/methods/{details.js => page.js} (96%) create mode 100644 js/views/notifications/list.js rename templates/apis/{overview.html => docs-overview.html} (55%) create mode 100644 templates/apis/docs.html delete mode 100644 templates/apis/documentation.html rename templates/apis/{details.html => page.html} (94%) create mode 100644 templates/apis/settings.html rename templates/methods/{details.html => page.html} (100%) diff --git a/js/router.js b/js/router.js index 6651731..9dd45e0 100644 --- a/js/router.js +++ b/js/router.js @@ -20,6 +20,7 @@ define([ 'apis/:id': 'showApi', 'apis/:id/method/:method_id': 'showApi', 'apis/:id/methods/edit': 'editMethod', + 'login': 'login', 'legal/:page': 'legal', 'browse': 'browse', @@ -31,18 +32,23 @@ define([ 'help': 'help', 'pricing': 'pricing', '': 'home', + ':username/:apiname/version/:version/resource/:resource/:method': 'apiPage', ':username/:apiname/version/:version/resource/:resource': 'apiPage', ':username/:apiname/version/:version': 'apiPage', - ':username/:apiname/settings/:page': 'apiSettingsPage', - ':username/settings/:page': 'settingsTab', + ':username/:apiname/version/:version/resource/:resource/:method/activity': 'apiActivityPage', + ':username/:apiname/version/:version/resource/:resource/activity': 'apiActivityPage', + ':username/:apiname/version/:version/activity' : 'apiActivityPage', + ':username/:apiname/settings': 'apiSettingsPage', ':username/:apiname/collaborators': 'collaboratorsTab', + + ':username/settings/:page': 'settingsTab', ':username': 'defaultAction' // All urls will trigger this route } }); var initialize = function(options){ - + var appView = options.appView; var router = new AppRouter(options); Backbone.router = router; @@ -55,8 +61,12 @@ define([ var apiDetailsView = Vm.create(appView, 'page', ApiPageView, {username: username, apiname: apiname, collaborators: true}); apiDetailsView.render(); }); - router.on('route:apiSettingsPage', function (username, apiname, page) { - var apiDetailsView = Vm.create(appView, 'page', ApiPageView, {username: username, apiname: apiname, page: page, settings: true}); + router.on('route:apiActivityPage', function (username, apiname, version, resourceId, method) { + var apiDetailsView = Vm.create(appView, 'page', ApiPageView, {username: username, apiname: apiname, activity: true, version: version, resourceId: resourceId, method: method}); + apiDetailsView.render(); + }); + router.on('route:apiSettingsPage', function (username, apiname) { + var apiDetailsView = Vm.create(appView, 'page', ApiPageView, {username: username, apiname: apiname, settings: true}); apiDetailsView.render(); }); /* @@ -74,17 +84,17 @@ define([ var membersView = Vm.create(appView, 'MembersView', MembersView, {}); membersView.render(); }); - */ + */ router.on('route:forgot_password', function (token) { var forgotView = Vm.create(appView, 'page', ForgotView, {token: token}); forgotView.render(); - }); + }); /* router.on('route:register', function (apiId) { var registerView = Vm.create(appView, 'RegisterView', RegisterView, {}); registerView.render(); }); - */ + */ router.on('route:showApi', function (apiId, methodId) { var apiDetailsView = Vm.create(appView, 'page', ApiDetailsView, {apiId: apiId, methodId: methodId}); apiDetailsView.render(); @@ -122,14 +132,14 @@ define([ var pricing = Vm.create(appView, 'page', Pricing, {}); pricing.render(); }); - }); + }); router.on('route:help', function () { require(['views/help/page'], function (Help) { var help = Vm.create(appView, 'page', Help, {}); help.render(); }); - }); + }); router.on('route:defaultAction', function (username) { var profilePage = Vm.create(appView, 'page', ProfilePage, {username: username}); profilePage.render(); @@ -139,7 +149,7 @@ define([ var profilePage = Vm.create(appView, 'page', ProfilePage, {username: username, tab: 'settings', setting: page}); profilePage.render(); }); - + }; return { initialize: initialize diff --git a/js/views/apis/collaborators.js b/js/views/apis/collaborators.js index 58d9775..ba3e0ea 100644 --- a/js/views/apis/collaborators.js +++ b/js/views/apis/collaborators.js @@ -5,16 +5,17 @@ define([ 'router', 'models/session', 'text!templates/apis/overview.html', - 'views/comments/comments', 'models/api' -], function($, _, Backbone, Router, Session, overviewTemplate, CommentsView, ApiModel){ +], function($, _, Backbone, Router, Session, overviewTemplate, ApiModel){ var Collaborators = Backbone.View.extend({ el: '.api-page-container', initialize: function () { var that = this; - - }, + + }, render: function () { + this.options.parent.activateTab('api-collab'); + var that = this; $('.api-container .tabs li.active').removeClass('active'); $('.api-container .tabs .api-collab').addClass('active'); diff --git a/js/views/apis/details.js b/js/views/apis/details.js deleted file mode 100644 index e2d7675..0000000 --- a/js/views/apis/details.js +++ /dev/null @@ -1,153 +0,0 @@ -define([ - 'jquery', - 'underscore', - 'backbone', - 'router', - 'vm', - 'mustache', - 'qtip', - 'models/session', - 'text!templates/apis/details.html', - 'models/api', - 'collections/methods', - 'views/resource/list', - 'views/methods/details', - 'models/resource', - 'models/method', - 'libs/highlight/highlight', - 'views/forms/resource', - 'modal', - 'views/apis/overview', - 'views/apis/tablelist' -], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, apiDetailsTemplate, ApiModel, MethodsCollection, ResourceListView, MethodDetailView, ResourceModel, MethodModel, hljs, ResourceForm, Modal, OverView, TableList){ - var NewApiPage = Backbone.View.extend({ - el: '.page', - initialize: function () { - var that = this; - - }, - events: { - 'click .js-new-resource': 'newResource', - 'click .js-new-method': 'newMethod', - 'click .edit-api-description': 'editDescription' - }, - editDescription: function(ev) { - var modal = Modal.create({ - inline: { - from : $(ev.currentTarget), - model : this.options.model.toApi(), - field : 'description' - } - }); - modal.show(); - }, - newResource: function () { - var resourceForm = Vm.create(this, 'resourceform', ResourceForm, { - username: this.options.username, - version: this.options.version, - api: this.options.apiname - }); - resourceForm.render(); - - return false; - }, - newMethod: function () { - $('#js-new-method-modal').modal('show'); - return false; - }, - saveMethod: function (ev) { - var that = this; - var methodData = $(ev.currentTarget).serializeObject(); - var methodModel = new MethodModel({ - username: this.options.username, - version: this.options.version, - api: this.options.apiname, - resourceId: this.options.resourceId - }); - methodModel.save(methodData, { - success: function () { - $('#js-new-method-modal').modal('hide'); - that.showMethodList(); - } - }); - return false; - }, - saveResource: function (ev) { - var resourceData = $(ev.currentTarget).serializeObject(); - console.log(resourceData); - var resourceModel = new ResourceModel({ - username: this.options.username, - version: this.options.version, - api: this.options.apiname - }); - resourceModel.save(resourceData, { - success: function () { - console.log('oooo', arguments); - } - }); - return false; - }, - showMethodList: function () { - var that = this; - var methodListView = new MethodsListView({username: that.options.username, api: that.options.apiname, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); - methodListView.render(); - }, - showDetails: function () { - var that = this; - - if(typeof that.options.resourceId === 'undefined') { - var overview = Vm.create(that, 'apipage', OverView, that.options); - overview.render(); - } - if($('.resource-list-container').attr('data-api-id') !== that.options.apiname) { - var resourceListView = Vm.create(that, 'resourceListView', ResourceListView, {username: that.options.username, api: that.options.apiname, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); - resourceListView.render(); - console.log('show list container'); - }; - // if(typeof that.options.resourceId !== 'undefined' && $('.method-list-container').attr('data-resource-id') !== that.options.resourceId) { - // that.showMethodList(); - //} - // if(typeof that.options.method !== 'undefined') { - // var methodView = new MethodView({username: that.options.username, api: that.options.apiname, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); - // methodView.render(); - // } - }, - renderOverview: function () { - - }, - render: function () { - var that = this; - console.log('re-render'); - if($('.api-container').length === 0) { - this.$el.html(''); - - var apiModel = new ApiModel({username: this.options.username, apiname: this.options.apiname, version: this.options.version}); - - apiModel.fetch({ - success: function (api) { - console.log('hljf' , hljs) - if($('.api-container').length === 0) { - var owner = Session.get('login') === api.get('user') ? true : false; - that.$el.html(Mustache.render(apiDetailsTemplate, {api: api, errors: [], owner: owner})); - - - $('code').each(function(i, e) {hljs.highlightBlock(e); }); - $('.js-api-pages a').click(function (e) { - e.preventDefault(); - $(this).tab('show'); - }); - }; - - that.showDetails(); - } - }) - } else { - - that.showDetails(); - - } - - } - }); - return NewApiPage; -}); diff --git a/js/views/apis/documentation.js b/js/views/apis/documentation.js index 6eb2154..eb941d3 100644 --- a/js/views/apis/documentation.js +++ b/js/views/apis/documentation.js @@ -7,11 +7,12 @@ define([ 'mustache', 'qtip', 'models/session', - 'text!templates/apis/documentation.html', + 'text!templates/apis/docs.html', 'models/api', 'collections/methods', 'views/resource/list', - 'views/methods/details', + 'views/methods/page', + 'views/resource/page', 'models/resource', 'models/method', 'libs/highlight/highlight', @@ -20,7 +21,7 @@ define([ 'views/apis/overview', 'views/modals/newmethod', 'views/modals/newresource', -], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, docsTemplate, ApiModel, MethodsCollection, ResourceListView, MethodDetailView, ResourceModel, MethodModel, hljs, ResourceForm, Modal, OverView, NewMethod, NewResource){ +], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, docsTemplate, ApiModel, MethodsCollection, ResourceListView, MethodDetailView, ResourceDetailView, ResourceModel, MethodModel, hljs, ResourceForm, Modal, OverView, NewMethod, NewResource){ var NewApiPage = Backbone.View.extend({ el: '.api-page-container', initialize: function () { @@ -29,28 +30,23 @@ define([ }, events: { 'click .js-new-resource': 'newResource', - 'click .js-new-method': 'newMethod', - 'click .edit-api-description': 'editDescription' - }, - editDescription: function(ev) { - var modal = Modal.create({ - inline: { - from : $(ev.currentTarget), - model : this.options.model.toApi(), - field : 'description' - } - }); - modal.show(); + 'click .js-new-method': 'newMethod' }, + + /*------------- --actions -------------------*/ + newResource: function () { - console.log(this.options); - var newResource = Vm.create(this, 'modal', NewResource, this.options); - newResource.render(); + var resourceForm = Vm.create(this, 'resourceform', NewResource, { + username: this.options.username, + version: this.options.version, + api: this.options.apiname + }); + resourceForm.render(); return false; }, newMethod: function () { - alert('new methods'); + $('#js-new-method-modal').modal('show'); return false; }, saveMethod: function (ev) { @@ -85,41 +81,41 @@ define([ }); return false; }, + + /*--------------- UI -------------------*/ + showMethodList: function () { var that = this; var methodListView = new MethodsListView({username: that.options.username, api: that.options.apiname, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); methodListView.render(); }, - showDetails: function () { - var that = this; - if(typeof that.options.resourceId === 'undefined') { - var overview = Vm.create(that, 'apipage', OverView, that.options); - overview.render(); - } - if($('.resource-list-container').attr('data-api-id') !== that.options.apiname && $('.resource-list').length === 0) { - var resourceListView = Vm.create(that, 'resourceListView', ResourceListView, that.options); - resourceListView.render(); - }; - // if(typeof that.options.resourceId !== 'undefined' && $('.method-list-container').attr('data-resource-id') !== that.options.resourceId) { - // that.showMethodList(); - //} - // if(typeof that.options.method !== 'undefined') { - // var methodView = new MethodView({username: that.options.username, api: that.options.apiname, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); - // methodView.render(); - // } - }, - renderOverview: function () { - + renderPageBody: function () { + if(typeof this.options.resourceId == 'undefined') { + // overview page + var overview = Vm.create(this, 'apitab', OverView, _.extend({parent : this.parent}, this.options)); + overview.render(); + } else if (typeof this.options.method == 'undefined') { + // resource page + var resourceDetailView = new ResourceDetailView({username: this.options.username, api: this.options.apiname, version: this.options.version, resourceId: this.options.resourceId, method: this.options.method}); + resourceDetailView.render(); + } else { + // method page + var methodDetailView = new MethodDetailView({username: this.options.username, api: this.options.apiname, version: this.options.version, resourceId: this.options.resourceId, method: this.options.method}); + methodDetailView.render(); + } }, render: function (options) { - if($('.api-details-container').length === 0) { - var owner = Session.get('login') === this.options.username ? true : false; - console.log(this.options, 'friday night'); - $('.api-container .tabs li.active').removeClass('active'); - $('.api-container .tabs .api-docs').addClass('active'); - this.$el.html(Mustache.render(docsTemplate, {api: this.options.apiname,user: this.options.username,version:this.options.version, owner: owner})); - } - this.showDetails(); + this.options.parent.activateTab('api-docs'); + + var owner = Session.get('login') === this.options.username ? true : false; + this.$el.html(Mustache.render(docsTemplate, {api: this.options.apiname,user: this.options.username,version:this.options.version, owner: owner})); + + // main area + this.renderPageBody(); + + // sidebar + var resourceListView = Vm.create(this, 'resourceListView', ResourceListView, this.options); + resourceListView.render(); } }); return NewApiPage; diff --git a/js/views/apis/page.js b/js/views/apis/page.js index 729983c..973d38c 100644 --- a/js/views/apis/page.js +++ b/js/views/apis/page.js @@ -1,3 +1,12 @@ +/** + * Top-level page controller for API pages + * + * Contains logic available to the API as a whole view. This includes: + * - editing basic API details (description). + * (Not to be confused with version details, which are managed by settings.js) + * - top-order page controls (tabs, etc) + * - following, unfollowing and sharing the API + */ define([ 'jquery', 'underscore', @@ -5,23 +14,22 @@ define([ 'router', 'vm', 'mustache', - 'qtip', 'models/session', - 'text!templates/apis/details.html', 'models/api', 'models/api-overview', 'libs/highlight/highlight', 'modal', - 'text!templates/modals/inlineedit.html', - 'views/apis/overview', + 'views/apis/collaborators', + 'views/apis/details', 'views/apis/documentation', + 'views/apis/overview', 'views/apis/settings', - 'views/apis/collaborators' -], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, apiDetailsTemplate, ApiModel, ApiSummary, hljs, Modal, edt, OverView, DocsView, SettingsView, CollaboratorsView){ + 'views/notifications/list', + 'text!templates/apis/page.html' +], function($, _, Backbone, Router, Vm, Mustache, Session, ApiModel, ApiSummary, hljs, Modal, CollaboratorsView, DetailsView, DocsView, OverView, SettingsView, ActivityView, apiDetailsTemplate){ var NewApiPage = Backbone.View.extend({ el: '.page', initialize: function () { - var that = this; }, events: { @@ -29,78 +37,95 @@ define([ }, editDescription: function(ev) { var modal = Modal.create({ - content: edt, inline: { - from: $(ev.currentTarget), - to: '.xx' + from : $(ev.currentTarget), + model : this.options.model.toApi(), + field : 'description' } }); - $('.editdescription').on('submit', function(ev) { - console.log('asd'); - var api = new ApiModel({ - username: 'thomasdavis', - apiname: 'ApiEngine', - version: 1 - }); - var apiDetails = $(ev.currentTarget).serializeObject(); - apiDetails.name = 'ApiEngine'; - api.save(apiDetails, { - success: function (model) { - - } - }) - return false; - }); - window.modal = modal; + modal.show(); }, render: function () { - var that = this; - if($('.api-container').length === 0) { + if(!this.model) { + // load the API summary on first init this.$el.html(''); - var apiModel = new ApiSummary({username: this.options.username, apiname: this.options.apiname, version: this.options.version}); + var that = this, + apiModel = new ApiSummary({username: this.options.username, apiname: this.options.apiname, version: this.options.version}); apiModel.fetch({ - success: function (api) { - if($('.api-container').length === 0) { - var owner = Session.get('login') === api.get('user') ? true : false; - console.log('why no api', api) - that.$el.html(Mustache.render(apiDetailsTemplate, {api: api, errors: [], owner: owner})); - if(that.options.version) { - var docsView = Vm.create(that, 'apitab', DocsView, that.options); - docsView.render({api: api}); - - } - if(that.options.settings) { - var settingsView = Vm.create(that, 'apitab', SettingsView, that.options); - settingsView.render(); - } - if(that.options.collaborators) { - var collaboratorsView = Vm.create(that, 'apitab', CollaboratorsView, that.options); - collaboratorsView.render(); - } - } - } - }) + success: function (api) { + that.options.model = api; + that.model = api; + that.rerenderChildren(); + }, + error : function () { + // :TODO: how to handle this? + } + }); } else { + this.rerenderChildren(); + } + }, - if(that.options.version) { - var docsView = Vm.create(that, 'apitab', DocsView, that.options); - docsView.render({api: api}); + rerenderChildren : function() + { + // :TODO: check passed in options for viewed resource / method ID and show according tabs - } - if(that.options.settings) { - var settingsView = Vm.create(that, 'apitab', SettingsView, that.options); - settingsView.render(); - } + var owner = Session.get('login') === this.model.get('user') ? true : false; - if(that.options.collaborators) { - var collaboratorsView = Vm.create(that, 'apitab', CollaboratorsView, that.options); - collaboratorsView.render(); - } - } + // render base page template + this.$el.html(Mustache.render(apiDetailsTemplate, {api: this.model, owner: Session.get('login') === this.model.get('user')})); + + // switch on active tab from router + if(this.options.collaborators) { + var collaboratorsView = Vm.create(this, 'apipage', CollaboratorsView, _.extend({parent : this}, this.options)); + collaboratorsView.render(); + } + else if(this.options.settings) { + var settingsView = Vm.create(this, 'apipage', SettingsView, _.extend({parent : this}, this.options)); + settingsView.render(); + } else if(this.options.activity) { + this.activateTab('api-activity'); + var actView = Vm.create(this, 'apipage', ActivityView, _.extend({parent : this}, this.options)); + actView.render(); + } else { + // default to documentation section + var docsView = Vm.create(this, 'apipage', DocsView, _.extend({parent : this}, this.options)); + docsView.render(); + } + }, + + /** ------------ shared behaviours ----------------*/ + + // mark tab active + activateTab : function(clss) { + $('.api-container .tabs li.active').removeClass('active'); + $('.api-container .tabs .' + clss).addClass('active'); + }, + + editDescription: function(ev) { + var modal = Modal.create({ + inline: { + from : $(ev.currentTarget), + model : this.options.model.toApi(), + field : 'description' + } + }); + modal.show(); + }, + + unfollowApi: function (ev) { + + return false; + }, + followApi: function (ev) { + return false; + }, + shareApi : function(ev) { + // :TODO: } }); return NewApiPage; diff --git a/js/views/apis/settings.js b/js/views/apis/settings.js index 2e6313e..e460d91 100644 --- a/js/views/apis/settings.js +++ b/js/views/apis/settings.js @@ -4,7 +4,7 @@ define([ 'backbone', 'router', 'models/session', - 'text!templates/apis/overview.html', + 'text!templates/apis/settings.html', 'views/comments/comments', 'models/api' ], function($, _, Backbone, Router, Session, overviewTemplate, CommentsView, ApiModel){ @@ -12,13 +12,12 @@ define([ el: '.api-page-container', initialize: function () { var that = this; - - }, + + }, render: function () { - var that = this; - $('.api-container .tabs li.active').removeClass('active'); - $('.api-container .tabs .api-settings').addClass('active'); - this.$el.html('settings page'); + this.options.parent.activateTab('api-settings'); + + this.$el.html(Mustache.render(overviewTemplate, this.options)); } }); return SettingsPage; diff --git a/js/views/methods/list.js b/js/views/methods/list.js index 9148830..ae9aa0e 100644 --- a/js/views/methods/list.js +++ b/js/views/methods/list.js @@ -8,7 +8,7 @@ define([ 'text!templates/methods/list.html', 'views/forms/resource', 'views/forms/method', - 'views/methods/details', + 'views/methods/page', 'collections/methods', 'models/method', 'models/notificationtotal' @@ -17,7 +17,7 @@ define([ el: '.method-list-container', initialize: function () { var that = this; - + }, events: { 'click .js-edit-resource': 'editResource', @@ -53,7 +53,7 @@ define([ that.options.method = $(ev.currentTarget).attr('data-method-id'); } var methodView = Vm.create(this, 'methodpageview', MethodView, {username: that.options.username, api: that.options.api, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); - methodView.render(); + methodView.render(); } }, render: function () { @@ -93,7 +93,7 @@ define([ }); notifEla.attr('data-method-totals', methodTotals); $(notifEla).text($(notifEla).attr('data-method-totals')).show(200); - if(model.get('resource') !== 0){ + if(model.get('resource') !== 0){ notifEla.text(model.get('resource')).show(); } } @@ -106,7 +106,7 @@ define([ } }); - + } }); return ApisPage; diff --git a/js/views/methods/details.js b/js/views/methods/page.js similarity index 96% rename from js/views/methods/details.js rename to js/views/methods/page.js index 00bbfb6..adaf2c9 100644 --- a/js/views/methods/details.js +++ b/js/views/methods/page.js @@ -6,18 +6,18 @@ define([ 'router', 'mustache', 'models/session', - 'text!templates/methods/details.html', + 'text!templates/methods/page.html', 'models/method', 'views/forms/method', 'views/comments/comments', 'models/clearnotification' ], function($, _, Backbone, Vm, Router, Mustache, Session, methodTemplate, MethodModel, MethodForm, CommentsView, ClearNModel){ var MethodDetailsView = Backbone.View.extend({ - el: '.method-container', + el: '.docs-container', initialize: function () { var that = this; - - }, + + }, events: { 'click .js-edit-method': 'saveMethod' }, @@ -62,7 +62,7 @@ define([ var methodCount = methodEl.text(); methodEl.fadeOut(200).text('0'); var resourceEl = $('.resource-notification[data-resource-id="'+that.options.resourceId+'"]'); - + $(resourceEl).attr('data-method-totals', $(resourceEl).attr('data-method-totals')*1 - methodCount*1); $(resourceEl).text($(resourceEl).attr('data-method-totals')); if($(resourceEl).attr('data-method-totals')*1 === 0) { @@ -70,7 +70,7 @@ define([ } } - + }) var commentsView = new CommentsView({ methodId: that.options.method, diff --git a/js/views/notifications/list.js b/js/views/notifications/list.js new file mode 100644 index 0000000..027eb7a --- /dev/null +++ b/js/views/notifications/list.js @@ -0,0 +1,34 @@ +define([ + 'jquery', + 'underscore', + 'backbone', + 'mustache', + 'models/session', + 'text!templates/apis/list.html', + 'text!templates/apis/list-item.html', + 'collections/notifications' +], function($, _, Backbone, Mustache, Session, apisListTemplate, apisListItemTemplate, NotificationsCollection){ + var NotsPage = Backbone.View.extend({ + el: '.private-container', + initialize: function () { + + }, + events: { + + }, + render: function () { + var that = this; + notifications = new NotificationsCollection([], this.options); + + notifications.fetch({ + success: function (collection) { + console.log('done got', collection); + // that.$el.html(Mustache.render(apisListTemplate, { + // notifications: collection.models + // })); + } + }); + } + }); + return NotsPage; +}); diff --git a/js/views/resource/page.js b/js/views/resource/page.js index 079e6df..8c3520e 100644 --- a/js/views/resource/page.js +++ b/js/views/resource/page.js @@ -10,10 +10,10 @@ define([ 'views/comments/comments' ], function($, _, Backbone, Vm, Session, ResourceModel, resourcePageTemplate, ClearNModel, CommentsView){ var ResourcesPage = Backbone.View.extend({ - el: '.method-container', + el: '.docs-container', initialize: function () { var that = this; - + }, events: { }, diff --git a/templates/apis/overview.html b/templates/apis/docs-overview.html similarity index 55% rename from templates/apis/overview.html rename to templates/apis/docs-overview.html index 5e2f470..680c75f 100644 --- a/templates/apis/overview.html +++ b/templates/apis/docs-overview.html @@ -1,8 +1,8 @@ - +

        + Overview +

        -

        {{api.attributes.apiname}}

        +

        {{apiname}}

        diff --git a/templates/apis/docs.html b/templates/apis/docs.html new file mode 100644 index 0000000..78aa7ad --- /dev/null +++ b/templates/apis/docs.html @@ -0,0 +1,23 @@ +
        + +
        + +
        + + + + +
        + Loading resources +
        +
        +
        +
        +
        +
        +
        +
        diff --git a/templates/apis/documentation.html b/templates/apis/documentation.html deleted file mode 100644 index 876521b..0000000 --- a/templates/apis/documentation.html +++ /dev/null @@ -1,23 +0,0 @@ -
        - -
        - -
        - - - - -
        - Loading resources -
        -
        -
        -
        -
        -
        -
        -
        \ No newline at end of file diff --git a/templates/apis/details.html b/templates/apis/page.html similarity index 94% rename from templates/apis/details.html rename to templates/apis/page.html index 3c87f46..cf9e36b 100644 --- a/templates/apis/details.html +++ b/templates/apis/page.html @@ -86,9 +86,11 @@

        {{api}}

        diff --git a/templates/apis/settings.html b/templates/apis/settings.html new file mode 100644 index 0000000..e69de29 diff --git a/templates/methods/details.html b/templates/methods/page.html similarity index 100% rename from templates/methods/details.html rename to templates/methods/page.html From ba2444a96b9eb4dcf55c614ccbb06e20c9b9d7ff Mon Sep 17 00:00:00 2001 From: pospi Date: Thu, 7 Feb 2013 19:47:19 +1000 Subject: [PATCH 486/531] restore modal default behaviour of showing initially to avoid rewriting calling code elsewhere --- js/libs/form/form.js | 2 -- js/libs/modal/modal.js | 5 +++++ js/views/apis/page.js | 2 -- js/views/settings/account.js | 2 -- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/js/libs/form/form.js b/js/libs/form/form.js index 0552882..132ab43 100644 --- a/js/libs/form/form.js +++ b/js/libs/form/form.js @@ -222,7 +222,6 @@ define(['require', 'jquery', 'underscore', 'mustache', 'models/error'], function that.modal = Modal.create({ content: errorTemplate }); - that.modal.show(); } ); @@ -305,7 +304,6 @@ define(['require', 'jquery', 'underscore', 'mustache', 'models/error'], function modal = Modal.create({ content: errorHTML }); - modal.show(); // log to server if (xhr.status < 500 || xhr.status >= 600) { diff --git a/js/libs/modal/modal.js b/js/libs/modal/modal.js index f304394..3143740 100644 --- a/js/libs/modal/modal.js +++ b/js/libs/modal/modal.js @@ -11,6 +11,7 @@ define(['jquery', 'autogrow', 'mustache', 'form', 'text!templates/modals/inlinee // savetext : 'text for OK button', default 'Save' // canceltext : 'text for cancel button' default 'Cancel' // } + startHidden : false }; var modal = function (options) { var options = $.extend({}, defaultOptions, options), @@ -107,6 +108,10 @@ define(['jquery', 'autogrow', 'mustache', 'form', 'text!templates/modals/inlinee } }, options.inline.form || {})); } + + if (!options.startHidden) { + this.show(); + } }; modal.prototype.show = function () { diff --git a/js/views/apis/page.js b/js/views/apis/page.js index 973d38c..275133b 100644 --- a/js/views/apis/page.js +++ b/js/views/apis/page.js @@ -43,7 +43,6 @@ define([ field : 'description' } }); - modal.show(); }, render: function () { @@ -113,7 +112,6 @@ define([ field : 'description' } }); - modal.show(); }, unfollowApi: function (ev) { diff --git a/js/views/settings/account.js b/js/views/settings/account.js index f9262f0..b733bbe 100644 --- a/js/views/settings/account.js +++ b/js/views/settings/account.js @@ -89,8 +89,6 @@ define([ } } }); - - this.modal.show(); } }); return SettingPage; From ea09ed8ae8191b217f70bf270bd9ac3fab2fe0e8 Mon Sep 17 00:00:00 2001 From: maddogdavis Date: Sun, 10 Feb 2013 14:26:38 +1000 Subject: [PATCH 487/531] extra space --- js/main.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/main.js b/js/main.js index 5eaf42f..a109cd3 100644 --- a/js/main.js +++ b/js/main.js @@ -44,6 +44,7 @@ require([ Proxino.key = "QI-BctdhtytsUUJERc5HfA"; Proxino.track_errors(); + var appView = Vm.create({}, 'AppView', AppView); Router.initialize({appView: appView}); From 877b533c2c35e1093dcd36f3da957b11f38a5b86 Mon Sep 17 00:00:00 2001 From: maddogdavis Date: Sun, 10 Feb 2013 14:29:48 +1000 Subject: [PATCH 488/531] remove space --- js/main.js | 1 - 1 file changed, 1 deletion(-) diff --git a/js/main.js b/js/main.js index a109cd3..5eaf42f 100644 --- a/js/main.js +++ b/js/main.js @@ -44,7 +44,6 @@ require([ Proxino.key = "QI-BctdhtytsUUJERc5HfA"; Proxino.track_errors(); - var appView = Vm.create({}, 'AppView', AppView); Router.initialize({appView: appView}); From 5680c97139046ab5ed3858a4326cb1691bbfde26 Mon Sep 17 00:00:00 2001 From: pospi Date: Thu, 7 Feb 2013 19:47:19 +1000 Subject: [PATCH 489/531] restore modal default behaviour of showing initially to avoid rewriting calling code elsewhere --- js/libs/form/form.js | 2 -- js/libs/modal/modal.js | 5 +++++ js/views/apis/page.js | 2 -- js/views/settings/account.js | 2 -- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/js/libs/form/form.js b/js/libs/form/form.js index 0552882..132ab43 100644 --- a/js/libs/form/form.js +++ b/js/libs/form/form.js @@ -222,7 +222,6 @@ define(['require', 'jquery', 'underscore', 'mustache', 'models/error'], function that.modal = Modal.create({ content: errorTemplate }); - that.modal.show(); } ); @@ -305,7 +304,6 @@ define(['require', 'jquery', 'underscore', 'mustache', 'models/error'], function modal = Modal.create({ content: errorHTML }); - modal.show(); // log to server if (xhr.status < 500 || xhr.status >= 600) { diff --git a/js/libs/modal/modal.js b/js/libs/modal/modal.js index f304394..3143740 100644 --- a/js/libs/modal/modal.js +++ b/js/libs/modal/modal.js @@ -11,6 +11,7 @@ define(['jquery', 'autogrow', 'mustache', 'form', 'text!templates/modals/inlinee // savetext : 'text for OK button', default 'Save' // canceltext : 'text for cancel button' default 'Cancel' // } + startHidden : false }; var modal = function (options) { var options = $.extend({}, defaultOptions, options), @@ -107,6 +108,10 @@ define(['jquery', 'autogrow', 'mustache', 'form', 'text!templates/modals/inlinee } }, options.inline.form || {})); } + + if (!options.startHidden) { + this.show(); + } }; modal.prototype.show = function () { diff --git a/js/views/apis/page.js b/js/views/apis/page.js index 973d38c..275133b 100644 --- a/js/views/apis/page.js +++ b/js/views/apis/page.js @@ -43,7 +43,6 @@ define([ field : 'description' } }); - modal.show(); }, render: function () { @@ -113,7 +112,6 @@ define([ field : 'description' } }); - modal.show(); }, unfollowApi: function (ev) { diff --git a/js/views/settings/account.js b/js/views/settings/account.js index f9262f0..b733bbe 100644 --- a/js/views/settings/account.js +++ b/js/views/settings/account.js @@ -89,8 +89,6 @@ define([ } } }); - - this.modal.show(); } }); return SettingPage; From c39e080ecee649df1ea19e220a19e0e7d95e1608 Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 10 Feb 2013 15:21:14 +1000 Subject: [PATCH 490/531] created a host-based config mechanism and setup config files for local dev, staging and prod --- js/config/apiengine.io.js | 8 ++++++++ js/config/localhost.js | 8 ++++++++ js/config/s.apiengine.io.js | 8 ++++++++ js/main.js | 20 +++++++++++++------- js/views/app.js | 24 ++++++------------------ 5 files changed, 43 insertions(+), 25 deletions(-) create mode 100644 js/config/apiengine.io.js create mode 100644 js/config/localhost.js create mode 100644 js/config/s.apiengine.io.js diff --git a/js/config/apiengine.io.js b/js/config/apiengine.io.js new file mode 100644 index 0000000..b981d0e --- /dev/null +++ b/js/config/apiengine.io.js @@ -0,0 +1,8 @@ +define([], function() { + return { + server_path : 'https://apiengine.io:443', + base_url : '/', + fullbore : false, + use_cdn : true + }; +}); diff --git a/js/config/localhost.js b/js/config/localhost.js new file mode 100644 index 0000000..2ef666f --- /dev/null +++ b/js/config/localhost.js @@ -0,0 +1,8 @@ +define([], function() { + return { + server_path : 'https://s.apiengine.io:443', + base_url : '/repos/apiengine-client/', + fullbore : true, + use_cdn : false + }; +}); diff --git a/js/config/s.apiengine.io.js b/js/config/s.apiengine.io.js new file mode 100644 index 0000000..fd3552d --- /dev/null +++ b/js/config/s.apiengine.io.js @@ -0,0 +1,8 @@ +define([], function() { + return { + server_path : 'https://s.apiengine.io:443', + base_url : '/', + fullbore : true, + use_cdn : true + }; +}); diff --git a/js/main.js b/js/main.js index 5eaf42f..705b2c0 100644 --- a/js/main.js +++ b/js/main.js @@ -1,17 +1,20 @@ -// Main application flags -var USE_CDNS = false; +// determine the host we're running on. :TODO: error check for nonexistent config files +var APIE_HOST = window.location.hostname; -// require.js path aliases +// determine the host we're running on +require(['config/' + APIE_HOST], function(Config) { + + // require.js path aliases require.config({ paths: { // Major libraries - jquery: USE_CDNS ? 'https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.min' : 'libs/jquery/jquery-min', - underscore: USE_CDNS ? 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.9.2/lodash.min' : 'libs/underscore/underscore-min', // https://github.com/amdjs + jquery: Config.use_cdn ? 'https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.min' : 'libs/jquery/jquery-min', + underscore: Config.use_cdn ? 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.9.2/lodash.min' : 'libs/underscore/underscore-min', // https://github.com/amdjs backbone: 'libs/backbone/backbone-min', // https://github.com/amdjs prettyprint: 'libs/prettyprint/prettyprint', qtip: 'libs/qtip2/jquery.qtip.min', marked: 'libs/marked/marked', - mustache: USE_CDNS ? 'https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.7.0/mustache.min' : 'libs/mustache/mustache', + mustache: Config.use_cdn ? 'https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.7.0/mustache.min' : 'libs/mustache/mustache', // APIe modal: 'libs/modal/modal', form: 'libs/form/form', @@ -28,6 +31,7 @@ require.config({ }); + // Let's kick off the application require([ @@ -44,9 +48,11 @@ require([ Proxino.key = "QI-BctdhtytsUUJERc5HfA"; Proxino.track_errors(); - var appView = Vm.create({}, 'AppView', AppView); + var appView = Vm.create({}, 'AppView', AppView, Config); Router.initialize({appView: appView}); appView.render(); // render() calls Backbone.history when its ready to start }); + +}); diff --git a/js/views/app.js b/js/views/app.js index 3eb81ce..6bdfdbe 100644 --- a/js/views/app.js +++ b/js/views/app.js @@ -59,19 +59,10 @@ define([ return o; }; - - - $.ajaxPrefilter( function( options, originalOptions, jqXHR ) { - // Your server goes below - if(options.url.indexOf('proxino') === -1) { - options.url = 'https://s.apiengine.io' + options.url; - //options.url = 'http://192.168.2.111:3000' + options.url; - }// else { - //options.url = 'http://d3gscmgl75g1oq.cloudfront.net' + options.url; - - // }; - - }); + var that = this; + $.ajaxPrefilter( function( options, originalOptions, jqXHR ) { + options.url = that.options.server_path + options.url; + }); }, render: function () { @@ -100,11 +91,8 @@ define([ } }); var notifications = new Notifications(); - var root = '/'; - if(window.location.hostname === 'localhost') { - root = '/repos/apiengine-client/'; - } - Backbone.history.start({pushState: true, root: root}); + + Backbone.history.start({pushState: true, root: that.options.base_url}); }); From e7479a48884b1dc50a0ca81435b2c0ba6df5dadd Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 10 Feb 2013 15:36:22 +1000 Subject: [PATCH 491/531] added another layer of indirection to the config loading process so that config files can be swapped out easily --- js/config/PERSONA.js | 10 ++++++++++ js/main.js | 16 +++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 js/config/PERSONA.js diff --git a/js/config/PERSONA.js b/js/config/PERSONA.js new file mode 100644 index 0000000..150617d --- /dev/null +++ b/js/config/PERSONA.js @@ -0,0 +1,10 @@ +/** + * You can override this by the name of the config file you wish to load if necessary. + * When unspecified, the config file matching the hostname of the machine the client is running on will be + * loaded instead. + * + * For example, to load config/s.apiengine.io.js as your app configuration, return "s.apiengine.io". + */ +define([], function() { + return ''; +}); diff --git a/js/main.js b/js/main.js index 705b2c0..01aec47 100644 --- a/js/main.js +++ b/js/main.js @@ -1,8 +1,12 @@ -// determine the host we're running on. :TODO: error check for nonexistent config files -var APIE_HOST = window.location.hostname; +require(['config/PERSONA'], function(confFile) { -// determine the host we're running on -require(['config/' + APIE_HOST], function(Config) { +// load the current host's config file if no override config is specified +if (!confFile) { + confFile = window.location.hostname; +} + +// load the application configuration +require(['config/' + confFile], function(Config) { // require.js path aliases require.config({ @@ -32,7 +36,7 @@ require.config({ }); -// Let's kick off the application +// Actually kick off the application require([ 'views/app', @@ -56,3 +60,5 @@ require([ }); }); + +}); From 689f4756da89b5af0e0ae93bb9ea746fdae380d9 Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 10 Feb 2013 19:00:21 +1000 Subject: [PATCH 492/531] adjusted Resource and Method model definitions and calling code to functional state added loose modal code for creating resources and methods --- js/models/method.js | 5 ++--- js/models/resource.js | 7 ++----- js/views/apis/documentation.js | 22 ++++++++++++++-------- js/views/forms/method.js | 6 +++--- js/views/forms/resource.js | 4 ++-- js/views/methods/page.js | 8 ++++---- js/views/modals/newmethod.js | 28 +++++++++++++++++++++++----- js/views/modals/newresource.js | 4 ++-- templates/modals/newmethod.html | 26 ++++++++++++++++++++++++++ templates/modals/newresource.html | 15 ++++++--------- 10 files changed, 84 insertions(+), 41 deletions(-) create mode 100644 templates/modals/newmethod.html diff --git a/js/models/method.js b/js/models/method.js index ecf0275..efd23df 100644 --- a/js/models/method.js +++ b/js/models/method.js @@ -4,10 +4,9 @@ define([ 'models/session' ], function(_, Backbone, Session) { var MethodModel = Backbone.Model.extend({ + idAttribute : 'method', urlRoot: function () { - - return '/user/' +this.get('username')+ '/api/' +this.get('apiname')+ '/' + this.get('version') + '/resource/' + this.get('resourceId') + '/method'; - + return '/user/' +this.options.username+ '/api/' +this.options.apiname+ '/' + this.options.version + '/resource/' + this.options.resourceId; } }); return MethodModel; diff --git a/js/models/resource.js b/js/models/resource.js index 5c6ff7f..689793c 100644 --- a/js/models/resource.js +++ b/js/models/resource.js @@ -4,12 +4,9 @@ define([ 'models/session' ], function(_, Backbone, Session) { var ResourceModel = Backbone.Model.extend({ + idAttribute : 'id', urlRoot: function () { - return '/user/' +this.options.username+ '/api/' +this.options.apiname+ '/' + this.options.version + '/resource'; - }, - parse: function (res, xhr) { - window.aaa = xhr; - console.log(arguments); + return '/user/' +this.options.username+ '/api/' +this.options.apiname+ '/' + this.options.version + '/resource'; } }); return ResourceModel; diff --git a/js/views/apis/documentation.js b/js/views/apis/documentation.js index eb941d3..1fb931b 100644 --- a/js/views/apis/documentation.js +++ b/js/views/apis/documentation.js @@ -39,23 +39,29 @@ define([ var resourceForm = Vm.create(this, 'resourceform', NewResource, { username: this.options.username, version: this.options.version, - api: this.options.apiname + apiname: this.options.apiname }); resourceForm.render(); return false; }, newMethod: function () { - $('#js-new-method-modal').modal('show'); + var methodForm = Vm.create(this, 'methodform', NewMethod, { + username: this.options.username, + version: this.options.version, + apiname: this.options.apiname + }); + methodForm.render(); + return false; }, saveMethod: function (ev) { var that = this; var methodData = $(ev.currentTarget).serializeObject(); - var methodModel = new MethodModel({ + var methodModel = new MethodModel({}, { username: this.options.username, version: this.options.version, - api: this.options.apiname, + apiname: this.options.apiname, resourceId: this.options.resourceId }); methodModel.save(methodData, { @@ -72,7 +78,7 @@ define([ var resourceModel = new ResourceModel({ username: this.options.username, version: this.options.version, - api: this.options.apiname + apiname: this.options.apiname }); resourceModel.save(resourceData, { success: function () { @@ -86,7 +92,7 @@ define([ showMethodList: function () { var that = this; - var methodListView = new MethodsListView({username: that.options.username, api: that.options.apiname, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); + var methodListView = new MethodsListView({username: that.options.username, apiname: that.options.apiname, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); methodListView.render(); }, renderPageBody: function () { @@ -96,11 +102,11 @@ define([ overview.render(); } else if (typeof this.options.method == 'undefined') { // resource page - var resourceDetailView = new ResourceDetailView({username: this.options.username, api: this.options.apiname, version: this.options.version, resourceId: this.options.resourceId, method: this.options.method}); + var resourceDetailView = new ResourceDetailView({username: this.options.username, apiname: this.options.apiname, version: this.options.version, resourceId: this.options.resourceId, method: this.options.method}); resourceDetailView.render(); } else { // method page - var methodDetailView = new MethodDetailView({username: this.options.username, api: this.options.apiname, version: this.options.version, resourceId: this.options.resourceId, method: this.options.method}); + var methodDetailView = new MethodDetailView({username: this.options.username, apiname: this.options.apiname, version: this.options.version, resourceId: this.options.resourceId, method: this.options.method}); methodDetailView.render(); } }, diff --git a/js/views/forms/method.js b/js/views/forms/method.js index 2532958..e197614 100644 --- a/js/views/forms/method.js +++ b/js/views/forms/method.js @@ -13,10 +13,10 @@ define([ var that = this; this.method = this.options.method; if(typeof this.options.method === 'undefined') { - this.method = new MethodModel({ + this.method = new MethodModel({}, { username: this.options.username, version: this.options.version, - api: this.options.api, + apiname: this.options.api, resourceId: this.options.resourceId }); } @@ -39,7 +39,7 @@ define([ var methodTypes = ['POST', 'GET', 'DELETE', 'PUT']; $('body').append(_.template(methodEditTemplate, {methodTypes: methodTypes, method: this.method})); $('#js-new-method-modal').modal('show'); - + } }); return ResourceForm; diff --git a/js/views/forms/resource.js b/js/views/forms/resource.js index 94a7054..f2a5489 100644 --- a/js/views/forms/resource.js +++ b/js/views/forms/resource.js @@ -16,7 +16,7 @@ define([ this.resource = new ResourceModel({ username: this.options.username, version: this.options.version, - api: this.options.api + apiname: this.options.api }); } }, @@ -36,7 +36,7 @@ define([ render: function () { $('body').append(_.template(resourceEditTemplate, {resource: this.resource})); $('#js-new-resource-modal').modal('show'); - + } }); return ResourceForm; diff --git a/js/views/methods/page.js b/js/views/methods/page.js index adaf2c9..4c4734b 100644 --- a/js/views/methods/page.js +++ b/js/views/methods/page.js @@ -39,11 +39,11 @@ define([ console.log(this.options, 'is there a resource id'); $('[data-method-id='+ this.options.method +']', $('[data-resource-id='+this.options.resourceId+']')).addClass('active'); - this.method = new MethodModel(); - this.method.set({ - id: this.options.method, + this.method = new MethodModel({ + method: this.options.method + }, { version: this.options.version, - api: this.options.api, + apiname: this.options.api, username: this.options.username, resourceId: this.options.resourceId }); diff --git a/js/views/modals/newmethod.js b/js/views/modals/newmethod.js index f47aaa3..2cfbec5 100644 --- a/js/views/modals/newmethod.js +++ b/js/views/modals/newmethod.js @@ -4,15 +4,33 @@ define([ 'backbone', 'models/session', 'mustache', -], function($, _, Backbone, Session, Mustache, headerLayoutTemplate, MainMenuView){ + 'modal', + 'text!templates/modals/newmethod.html', + 'models/method' +], function($, _, Backbone, Session, Mustache, Modal, methodModal, Method){ var NewMethod = Backbone.View.extend({ - el: '.header', + el: 'body', initialize: function () { }, + events: { + 'submit .new-resource-form': 'newMethod' + }, + newMethod: function (ev) { + var that = this; + var details = $(ev.currentTarget).serializeObject(); + var method = new Method(); + method.options = this.options; + var request = method.save(details, {success:function (model) { + Backbone.history.navigate(that.options.username + '/' + that.options.apiname + '/version/' + that.options.version + '/resource/' + this.options.resourceId + '/' + model.get('method'), {trigger: true}); + that.modal.hide(); + }}); + return false; + }, render: function () { - - - + this.modal = Modal.create({ + content: methodModal + }); + $('.modal input')[0].focus(); } }); return NewMethod; diff --git a/js/views/modals/newresource.js b/js/views/modals/newresource.js index 0a1c955..e78fdbc 100644 --- a/js/views/modals/newresource.js +++ b/js/views/modals/newresource.js @@ -20,8 +20,8 @@ define([ var details = $(ev.currentTarget).serializeObject(); var resource = new Resource(); resource.options = this.options; - var request = resource.save(details, {success:function () { - Backbone.history.navigate(that.options.username + '/' + that.options.apiname + '/version/' + that.options.version + '/resource/' + '19', {trigger: true}); + var request = resource.save(details, {success:function (model) { + Backbone.history.navigate(that.options.username + '/' + that.options.apiname + '/version/' + that.options.version + '/resource/' + model.get('id'), {trigger: true}); that.modal.hide(); }}); diff --git a/templates/modals/newmethod.html b/templates/modals/newmethod.html new file mode 100644 index 0000000..6501fdd --- /dev/null +++ b/templates/modals/newmethod.html @@ -0,0 +1,26 @@ +
        + + + + + +
        diff --git a/templates/modals/newresource.html b/templates/modals/newresource.html index ca76d38..577760a 100644 --- a/templates/modals/newresource.html +++ b/templates/modals/newresource.html @@ -1,23 +1,20 @@ -
        + -
        \ No newline at end of file + From aa0cd58357314deec0fbd7d7a1b622ed76ee8907 Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 10 Feb 2013 20:50:27 +1000 Subject: [PATCH 493/531] store app config into Router instance and provide a globally accessible method for returning the app base URL --- js/main.js | 2 +- js/router.js | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/js/main.js b/js/main.js index 01aec47..4dd731e 100644 --- a/js/main.js +++ b/js/main.js @@ -54,7 +54,7 @@ require([ var appView = Vm.create({}, 'AppView', AppView, Config); - Router.initialize({appView: appView}); + Router.initialize({appView : appView, config : Config}); appView.render(); // render() calls Backbone.history when its ready to start }); diff --git a/js/router.js b/js/router.js index 9dd45e0..87c349a 100644 --- a/js/router.js +++ b/js/router.js @@ -44,6 +44,10 @@ define([ ':username/settings/:page': 'settingsTab', ':username': 'defaultAction' // All urls will trigger this route + }, + + getBaseUrl : function() { + return window.location.hostname + this.Config.base_url; } }); @@ -51,6 +55,7 @@ define([ var appView = options.appView; var router = new AppRouter(options); + router.Config = options.config; Backbone.router = router; router.on('route:apiPage', function (username, apiname, version, resourceId, method) { var apiDetailsView = Vm.create(appView, 'page', ApiPageView, {username: username, apiname: apiname, version: version, resourceId: resourceId, method: method}); From 8aa8f056c018ac825b4d3b19618f9357aba46391 Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 10 Feb 2013 20:51:17 +1000 Subject: [PATCH 494/531] hookup AddThis share controls for APIs --- js/main.js | 2 ++ js/views/apis/list.js | 22 +++++++++++++++++----- js/views/apis/page.js | 16 ++++++++++------ templates/apis/list-item.html | 2 +- templates/apis/page.html | 2 +- 5 files changed, 31 insertions(+), 13 deletions(-) diff --git a/js/main.js b/js/main.js index 4dd731e..91ed174 100644 --- a/js/main.js +++ b/js/main.js @@ -26,6 +26,8 @@ require.config({ text: 'libs/require/text', // jquery plugins autogrow : 'libs/autogrow/autogrow', + // External services + addthis : "//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-51176d76142335d0", // Just a short cut so we can put our html outside the js dir // When you have HTML/CSS designers this aids in keeping them out of the js directory diff --git a/js/views/apis/list.js b/js/views/apis/list.js index e85b243..7ac284b 100644 --- a/js/views/apis/list.js +++ b/js/views/apis/list.js @@ -3,13 +3,14 @@ define([ 'underscore', 'backbone', 'mustache', + 'addthis', 'models/session', 'text!templates/apis/list.html', 'text!templates/apis/list-item.html', 'collections/apis', 'models/api', 'models/follower' -], function($, _, Backbone, Mustache, Session, apisListTemplate, apisListItemTemplate, ApisCollection, ApiModel, FollowerModel){ +], function($, _, Backbone, Mustache, unused, Session, apisListTemplate, apisListItemTemplate, ApisCollection, ApiModel, FollowerModel){ var ApisPage = Backbone.View.extend({ el: '.private-container', initialize: function () { @@ -22,17 +23,17 @@ define([ } if(ev.type === 'mouseleave') { $(button).removeClass('btn-red').addClass('btn-green').text('FOLLOWING'); - + } }); }, events: { 'click .js-new-api-button': 'editApi', 'submit .js-new-api-form': 'saveApi', - 'click .js-follow.btn-blue': 'followApi', - 'click .js-following.btn-red': 'unfollow' + 'click .js-follow': 'followApi', + 'click .js-following': 'unfollowApi' }, - unfollow: function (ev) { + unfollowApi: function (ev) { var button = $(ev.currentTarget); var apiEl = $(ev.currentTarget).parents('.api-list-item'); @@ -107,6 +108,17 @@ define([ apis.fetch({ success: function (collection) { that.$el.html(Mustache.render(apisListTemplate, {authed: Session.get('auth'), currentUser: that.options.currentUser, _:_, is_public: that.options.is_public, apis: collection.models, username: Session.get('login'), location: that.options.location}, {listtemplate: apisListItemTemplate})); + + // activate the share buttons + _.each(collection.models, function(model) { + addthis.button('#' + model.get('user') + '-' + model.get('name'), { + services_compact : "facebook,twitter,digg,pinterest,email", + ui_click : true + }, { + url: Backbone.router.getBaseUrl() + model.get('user') + '/' + model.get('name'), + title: model.get('name') + ' on API Engine' + }); + }); } }); diff --git a/js/views/apis/page.js b/js/views/apis/page.js index 275133b..98f6abe 100644 --- a/js/views/apis/page.js +++ b/js/views/apis/page.js @@ -11,7 +11,6 @@ define([ 'jquery', 'underscore', 'backbone', - 'router', 'vm', 'mustache', 'models/session', @@ -26,7 +25,7 @@ define([ 'views/apis/settings', 'views/notifications/list', 'text!templates/apis/page.html' -], function($, _, Backbone, Router, Vm, Mustache, Session, ApiModel, ApiSummary, hljs, Modal, CollaboratorsView, DetailsView, DocsView, OverView, SettingsView, ActivityView, apiDetailsTemplate){ +], function($, _, Backbone, Vm, Mustache, Session, ApiModel, ApiSummary, hljs, Modal, CollaboratorsView, DetailsView, DocsView, OverView, SettingsView, ActivityView, apiDetailsTemplate){ var NewApiPage = Backbone.View.extend({ el: '.page', initialize: function () { @@ -77,6 +76,15 @@ define([ // render base page template this.$el.html(Mustache.render(apiDetailsTemplate, {api: this.model, owner: Session.get('login') === this.model.get('user')})); + // activate addThis share button for the API + addthis.button('#' + this.model.get('username') + '-' + this.model.get('apiname'), { + services_compact : "facebook,twitter,digg,pinterest,email", + ui_click : true + }, { + url: Backbone.router.getBaseUrl() + this.model.get('username') + '/' + this.model.get('apiname'), + title: this.model.get('apiname') + ' on API Engine' + }); + // switch on active tab from router if(this.options.collaborators) { var collaboratorsView = Vm.create(this, 'apipage', CollaboratorsView, _.extend({parent : this}, this.options)); @@ -120,10 +128,6 @@ define([ }, followApi: function (ev) { return false; - }, - - shareApi : function(ev) { - // :TODO: } }); return NewApiPage; diff --git a/templates/apis/list-item.html b/templates/apis/list-item.html index 2b0f01b..b815457 100644 --- a/templates/apis/list-item.html +++ b/templates/apis/list-item.html @@ -43,7 +43,7 @@

        FOLLOWERS {{/currentUser}}
        - +

        diff --git a/templates/apis/page.html b/templates/apis/page.html index cf9e36b..ccf937e 100644 --- a/templates/apis/page.html +++ b/templates/apis/page.html @@ -78,7 +78,7 @@

        {{api}}

        {{/authed}} -
      • +
    From 251bbd4dc7cd89a08e831bd0667ad794456cf322 Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 3 Mar 2013 14:03:52 +1000 Subject: [PATCH 495/531] proper share button graphic --- css/button.css | 3 ++- img/share-icon.png | Bin 0 -> 1143 bytes templates/apis/list-item.html | 2 +- templates/apis/page.html | 2 +- templates/browse/page.html | 2 +- templates/profile/page.html | 4 ++-- 6 files changed, 7 insertions(+), 6 deletions(-) create mode 100644 img/share-icon.png diff --git a/css/button.css b/css/button.css index 3e315e5..be43626 100644 --- a/css/button.css +++ b/css/button.css @@ -439,7 +439,8 @@ We need to have disabled state I think ? ``` */ .btn-share .icon { - color: #171717; + background: transparent url(../img/share-icon.png); + width: 14px; height: 16px; display: block; } .slider-buttons { list-style: none; diff --git a/img/share-icon.png b/img/share-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..53bba45b58fec5555766f2f3bffd8fdbc4cbfa31 GIT binary patch literal 1143 zcmaJ>Pi)gx9Cqj*s#eJ=5R4TK9?C+{S9!v~fby)m4;6YEBHter?^>ey;tx zxIJv8OeKtgs8orH0~-jb;)2@S01eO-khpPx3y5huA%w(0yB2lNZPRjCux!6S`o8b? z`@P?1pGyy%@YXlgQxxS*^@uo5MM&Ur>Wn~;C;eM-$vUw19$TMUtv2tZ9+B!Z8T*mq;bQ| zZYWcTTTsTx$|5vTKE?DX!pI&)CWsI6;MkC6sHk9nwSku;A!XQDHWZi=qcl-qG))!4 zJ$!efEgWy-!|fcG2)6TqczZk<;3BQb5EqD-xgt`gbZFo*SKZ-?6}hezbdy9Dp{0EX z)ue@Vuu-z0RnDcmqTUu)t(;3wMJ`K{Vco`l)addSagRIQwk=s~8y_0P?G~|hf8)X_ z@=3f&iQQS}d46quy{qcTugl9rz8hc9E`3%k?3xTVAGr{d{*H~+TzPl0rS^{pHRqRF z_j+E4vy0sRn`ir-&_mD7gRzOa(k}})?s+C#8q%KTOAFPdx3M)}v5lJKo}N2=y4_p+ zoLc>|vBC5H+BcV(-_@tjp6O@j4+y!c((PD+UAbMXDgL`sM7zf79=`e^-?MM|Q7TvZ zF#G+t-qN1mLUU`q$IQOfTHme3stXr8!T$N=ZZ?B|{7bT)RIfBNT`nD^8Y$tm_mXfv z(RXzz{qjuWXOrIj{LY>$u}dxTBSU-)Ywmb*WX?LaLD}?q!I(-t)5eJ{{gY4 Ba!UXJ literal 0 HcmV?d00001 diff --git a/templates/apis/list-item.html b/templates/apis/list-item.html index b815457..a201807 100644 --- a/templates/apis/list-item.html +++ b/templates/apis/list-item.html @@ -43,7 +43,7 @@

    FOLLOWERS {{/currentUser}}
    - +

    diff --git a/templates/apis/page.html b/templates/apis/page.html index ccf937e..cbdae9a 100644 --- a/templates/apis/page.html +++ b/templates/apis/page.html @@ -78,7 +78,7 @@

    {{api}}

    {{/authed}} -
  • +
  • diff --git a/templates/browse/page.html b/templates/browse/page.html index 94f4efd..7d5f36d 100644 --- a/templates/browse/page.html +++ b/templates/browse/page.html @@ -23,7 +23,7 @@

    Facebook

    - +
    diff --git a/templates/profile/page.html b/templates/profile/page.html index e31b9b8..4c09889 100644 --- a/templates/profile/page.html +++ b/templates/profile/page.html @@ -52,10 +52,10 @@

    {{user.attributes.login}}

    --> {{/currentUser}} - +
    From a0ecf3ec788c1cc56ecf7311ed84d4a93cdc80f8 Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 3 Mar 2013 14:07:29 +1000 Subject: [PATCH 496/531] whitespace --- css/button.css | 14 +++++++------- js/views/home/login.js | 2 +- templates/browse/page.html | 4 ++-- templates/profile/page.html | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/css/button.css b/css/button.css index be43626..74a88d5 100644 --- a/css/button.css +++ b/css/button.css @@ -86,7 +86,7 @@ hrmm border-right: 2px solid #fff; border-bottom: 2px solid #fff; border-left: 2px solid #fff; - font-family: 'Nexa Bold'; + font-family: 'Nexa Bold'; letter-spacing: 1px; padding: 0 5px 5px 5px; /* Safari */ @@ -116,8 +116,8 @@ hrmm line-height: 30px; padding: 0 10px 0 10px; cursor: pointer; - -webkit-transition:background 0.5s ease-in; - -webkit-transition:color 0.1s ease-in; + -webkit-transition:background 0.5s ease-in; + -webkit-transition:color 0.1s ease-in; font-size: 14px; } a.btn { @@ -226,7 +226,7 @@ a.btn { background: linear-gradient(to bottom, #adc45c 0%,#65c543 4%,#65c543 100%); /* W3C */ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#adc45c', endColorstr='#65c543',GradientType=0 ); /* IE6-9 */ } -.btn.btn-red-hover:hover, +.btn.btn-red-hover:hover, .btn-red:hover { background: #fd7686; /* Old browsers */ background: -moz-linear-gradient(top, #fd7686 0%, #ff3048 4%, #ff3048 100%); /* FF3.6+ */ @@ -272,7 +272,7 @@ a.btn { /* -## Disabled state +## Disabled state We need to have disabled state I think ? @@ -508,7 +508,7 @@ We need to have disabled state I think ? border-style:solid; border-color:#5a8f00 transparent; /* reduce the damage in FF3.0 */ - display:block; + display:block; width:0; } @@ -522,7 +522,7 @@ We need to have disabled state I think ? border-style:solid; border-color:#fff transparent; /* reduce the damage in FF3.0 */ - display:block; + display:block; width:0; } diff --git a/js/views/home/login.js b/js/views/home/login.js index 71ec8b3..36cd6b4 100644 --- a/js/views/home/login.js +++ b/js/views/home/login.js @@ -34,7 +34,7 @@ define([ }); } }); - + }, render: function () { this.modal = Modal.create({ diff --git a/templates/browse/page.html b/templates/browse/page.html index 7d5f36d..ec1dd0f 100644 --- a/templates/browse/page.html +++ b/templates/browse/page.html @@ -35,7 +35,7 @@

    Facebook

    -->
    - +
    • All
    • @@ -47,4 +47,4 @@

      Facebook

    -
    \ No newline at end of file +
    diff --git a/templates/profile/page.html b/templates/profile/page.html index 4c09889..6e473bf 100644 --- a/templates/profile/page.html +++ b/templates/profile/page.html @@ -44,7 +44,7 @@

    {{user.attributes.login}}

    {{#user.attributes.profile.linkedin}} {{/user.attributes.profile.linkedin}} - +
    {{#currentUser}} @@ -76,4 +76,4 @@

    {{user.attributes.login}}

    - \ No newline at end of file + From 7e91e8d1c1a0d7544300f277a6d10815e44ef0ae Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 3 Mar 2013 14:07:58 +1000 Subject: [PATCH 497/531] remove cruft --- js/views/apis/page.js | 3 +-- js/views/home/login.js | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/js/views/apis/page.js b/js/views/apis/page.js index 98f6abe..ad9fd50 100644 --- a/js/views/apis/page.js +++ b/js/views/apis/page.js @@ -19,13 +19,12 @@ define([ 'libs/highlight/highlight', 'modal', 'views/apis/collaborators', - 'views/apis/details', 'views/apis/documentation', 'views/apis/overview', 'views/apis/settings', 'views/notifications/list', 'text!templates/apis/page.html' -], function($, _, Backbone, Vm, Mustache, Session, ApiModel, ApiSummary, hljs, Modal, CollaboratorsView, DetailsView, DocsView, OverView, SettingsView, ActivityView, apiDetailsTemplate){ +], function($, _, Backbone, Vm, Mustache, Session, ApiModel, ApiSummary, hljs, Modal, CollaboratorsView, DocsView, OverView, SettingsView, ActivityView, apiDetailsTemplate){ var NewApiPage = Backbone.View.extend({ el: '.page', initialize: function () { diff --git a/js/views/home/login.js b/js/views/home/login.js index 36cd6b4..14c839c 100644 --- a/js/views/home/login.js +++ b/js/views/home/login.js @@ -9,7 +9,6 @@ define([ 'text!templates/modals/login.html', 'text!templates/common/error-box.html' ], function($, _, Backbone, Session, loginTemplate, Mustache, Modal, logint, errorT){ - console.log(Mustache); var ExamplePage = Backbone.View.extend({ el: 'body', initialize: function () { From a9bbcb6823de8114c5e481e2c0499e0906df6007 Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 3 Mar 2013 14:44:44 +1000 Subject: [PATCH 498/531] hookup resource list code properly, read notifications for API overview & adjust DOM to make this possible --- js/views/resource/list.js | 44 ++++++++++++++++++++---------------- templates/apis/docs.html | 9 ++++++-- templates/resource/list.html | 20 ++++++---------- 3 files changed, 38 insertions(+), 35 deletions(-) diff --git a/js/views/resource/list.js b/js/views/resource/list.js index db850ca..94ed23b 100644 --- a/js/views/resource/list.js +++ b/js/views/resource/list.js @@ -16,7 +16,7 @@ define([ el: '.resource-list-container', initialize: function () { var that = this; - + }, events: { 'click a[data-resource-id]': 'showMethodList', @@ -32,14 +32,14 @@ define([ } else { var el = $('[data-resource-id=' + this.options.resourceId + ']'); } - if(el.length > 0) { + if(el.length > 0) { this.expandMethods($(el).parents('li[data-resource-id]')); } - + //var methodListView = new MethodsListView({username: that.options.username, api: that.options.api, version: that.options.version, resourceId: that.options.resourceId, method: that.options.method}); - //methodListView.render(); + //methodListView.render(); var resourcePageView = Vm.create(this, 'resourcepageview', ResourcePageView, that.options); - resourcePageView.render(); + resourcePageView.render(); }, expandMethodsHandler: function (ev) { $(ev.currentTarget).text('-'); @@ -47,12 +47,12 @@ define([ var ele = $(ev.currentTarget).parents('li[data-resource-id]'); this.expandMethods(ele); }, - expandMethods: function (ele) { + expandMethods: function (ele) { var resourceId = $(ele).attr('data-resource-id'); var el = $(ele).next('li'); var methodListView = Vm.create(this, 'methodlist'+this.options.resourceId, MethodsListView, {username: this.options.username, apiname: this.options.apiname, version: this.options.version, resourceId: resourceId, method: this.options.method, el: el}); methodListView.setElement(el); - methodListView.render(); + methodListView.render(); }, contractMethods: function (ev) { $(ev.currentTarget).removeClass('expanded'); @@ -67,16 +67,18 @@ define([ that.$el.attr('data-api-id', that.options.apiname); resources.fetch({ success: function (collection) { + // mark active resource in list if we're viewing one if(that.options.resourceId) { - - collection.get(that.options.resourceId).set({active: 'active'}); + collection.get(that.options.resourceId).set({active: 'active'}); } that.$el.html(Mustache.render(resourceListTemplate, {_:_, selectedResource: that.options.resourceId, is_public: that.options.is_public, resources: collection, username: Session.get('login'), location: that.options.location})); - if(typeof that.options.resourceId !== 'undefined') { //&& $('.method-list-container').attr('data-resource-id') !== that.options.resourceId) { - that.showMethodList(); + + // render method list for active resource + if(typeof that.options.resourceId !== 'undefined') { + that.showMethodList(); } - //that.showMethodList(); + // read in notification counts var notificationTotals = new NTotals(); notificationTotals.options = { api: that.options.apiname, @@ -84,17 +86,19 @@ define([ username: that.options.username }; notificationTotals.fetch({ - success: function (model) { - console.log('I dont know what to do', model); - //var notifEl = $('.notification[data-resource-id='+model.options.resourceId+']'); - // notifEl.text(model.get('resource')).show(); + success: function(model) { + // set notifiactions on the top-level API + if (model.get('api')) { + var anotifEl = $('ul.api-menu-list[data-api-id='+that.options.apiname+'] .api-notification'); + anotifEl.text(model.get('api')).show(); + } + + // set notifications on each resource _.each(model.get('resources'), function(method){ - console.log(method,'wtf is this'); if(method.count > 0) { - var anotifEl = $('.resource-notification[data-resource-id='+method.key+']'); + var anotifEl = $('li[data-resource-id='+method.key+'] .resource-notification'); anotifEl.text(method.count).show(); } - }); } }); @@ -105,7 +109,7 @@ define([ } }); - + } }); return ApisPage; diff --git a/templates/apis/docs.html b/templates/apis/docs.html index 78aa7ad..3abce64 100644 --- a/templates/apis/docs.html +++ b/templates/apis/docs.html @@ -8,8 +8,13 @@ - From 7c6a5aa0de9c2110fd7188c354b37c571a632922 Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 3 Mar 2013 14:45:56 +1000 Subject: [PATCH 499/531] clean up API overview page code a bit --- js/views/apis/overview.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/js/views/apis/overview.js b/js/views/apis/overview.js index 8ed05b5..e294fb6 100644 --- a/js/views/apis/overview.js +++ b/js/views/apis/overview.js @@ -2,19 +2,20 @@ define([ 'jquery', 'underscore', 'backbone', + 'mustache', 'router', 'models/session', - 'text!templates/apis/overview.html', + 'text!templates/apis/docs-overview.html', 'views/comments/comments', 'models/api', 'views/resource/tablelist' -], function($, _, Backbone, Router, Session, overviewTemplate, CommentsView, ApiModel, TableList){ +], function($, _, Backbone, Mustache, Router, Session, overviewTemplate, CommentsView, ApiModel, TableList){ var NewApiPage = Backbone.View.extend({ - el: '.method-container', + el: '.docs-container', initialize: function () { var that = this; - - }, + + }, render: function () { var that = this; $('.api-menu-container a.active').removeClass('active'); From a4654efc7b9ab49f3e73ff38ae6c376a34051193 Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 3 Mar 2013 15:25:34 +1000 Subject: [PATCH 500/531] update underscore and backbone versions. Will put back into CDN later --- js/libs/backbone/backbone-min.js | 40 - js/libs/backbone/backbone.js | 1498 ++++++++++++++++++++++++++ js/libs/underscore/underscore-min.js | 31 - js/libs/underscore/underscore.js | 1234 +++++++++++++++++++++ js/main.js | 4 +- 5 files changed, 2734 insertions(+), 73 deletions(-) delete mode 100644 js/libs/backbone/backbone-min.js create mode 100644 js/libs/backbone/backbone.js delete mode 100644 js/libs/underscore/underscore-min.js create mode 100644 js/libs/underscore/underscore.js diff --git a/js/libs/backbone/backbone-min.js b/js/libs/backbone/backbone-min.js deleted file mode 100644 index 2a70224..0000000 --- a/js/libs/backbone/backbone-min.js +++ /dev/null @@ -1,40 +0,0 @@ -// Backbone.js 0.9.2 - -// (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc. -// Backbone may be freely distributed under the MIT license. -// For all details and documentation: -// http://backbonejs.org -(function(h,g){typeof exports!=="undefined"?g(h,exports,require("underscore")):typeof define==="function"&&define.amd?define(["underscore","jquery","exports"],function(f,i,p){h.Backbone=g(h,p,f,i)}):h.Backbone=g(h,{},h._,h.jQuery||h.Zepto||h.ender)})(this,function(h,g,f,i){var p=h.Backbone,y=Array.prototype.slice,z=Array.prototype.splice;g.VERSION="0.9.2";g.setDomLibrary=function(a){i=a};g.noConflict=function(){h.Backbone=p;return g};g.emulateHTTP=false;g.emulateJSON=false;var q=/\s+/,l=g.Events= -{on:function(a,b,c){var d,e,f,g,j;if(!b)return this;a=a.split(q);for(d=this._callbacks||(this._callbacks={});e=a.shift();)f=(j=d[e])?j.tail:{},f.next=g={},f.context=c,f.callback=b,d[e]={tail:g,next:j?j.next:f};return this},off:function(a,b,c){var d,e,k,g,j,h;if(e=this._callbacks){if(!a&&!b&&!c)return delete this._callbacks,this;for(a=a?a.split(q):f.keys(e);d=a.shift();)if(k=e[d],delete e[d],k&&(b||c))for(g=k.tail;(k=k.next)!==g;)if(j=k.callback,h=k.context,b&&j!==b||c&&h!==c)this.on(d,j,h);return this}}, -trigger:function(a){var b,c,d,e,f,g;if(!(d=this._callbacks))return this;f=d.all;a=a.split(q);for(g=y.call(arguments,1);b=a.shift();){if(c=d[b])for(e=c.tail;(c=c.next)!==e;)c.callback.apply(c.context||this,g);if(c=f){e=c.tail;for(b=[b].concat(g);(c=c.next)!==e;)c.callback.apply(c.context||this,b)}}return this}};l.bind=l.on;l.unbind=l.off;var o=g.Model=function(a,b){var c;a||(a={});b&&b.parse&&(a=this.parse(a));if(c=n(this,"defaults"))a=f.extend({},c,a);if(b&&b.collection)this.collection=b.collection; -this.attributes={};this._escapedAttributes={};this.cid=f.uniqueId("c");this.changed={};this._silent={};this._pending={};this.set(a,{silent:true});this.changed={};this._silent={};this._pending={};this._previousAttributes=f.clone(this.attributes);this.initialize.apply(this,arguments)};f.extend(o.prototype,l,{changed:null,_silent:null,_pending:null,idAttribute:"id",initialize:function(){},toJSON:function(){return f.clone(this.attributes)},get:function(a){return this.attributes[a]},escape:function(a){var b; -if(b=this._escapedAttributes[a])return b;b=this.get(a);return this._escapedAttributes[a]=f.escape(b==null?"":""+b)},has:function(a){return this.get(a)!=null},set:function(a,b,c){var d,e;f.isObject(a)||a==null?(d=a,c=b):(d={},d[a]=b);c||(c={});if(!d)return this;if(d instanceof o)d=d.attributes;if(c.unset)for(e in d)d[e]=void 0;if(!this._validate(d,c))return false;if(this.idAttribute in d)this.id=d[this.idAttribute];var b=c.changes={},g=this.attributes,h=this._escapedAttributes,j=this._previousAttributes|| -{};for(e in d){a=d[e];if(!f.isEqual(g[e],a)||c.unset&&f.has(g,e))delete h[e],(c.silent?this._silent:b)[e]=true;c.unset?delete g[e]:g[e]=a;!f.isEqual(j[e],a)||f.has(g,e)!=f.has(j,e)?(this.changed[e]=a,c.silent||(this._pending[e]=true)):(delete this.changed[e],delete this._pending[e])}c.silent||this.change(c);return this},unset:function(a,b){(b||(b={})).unset=true;return this.set(a,null,b)},clear:function(a){(a||(a={})).unset=true;return this.set(f.clone(this.attributes),a)},fetch:function(a){var a= -a?f.clone(a):{},b=this,c=a.success;a.success=function(d,e,f){if(!b.set(b.parse(d,f),a))return false;c&&c(b,d)};a.error=g.wrapError(a.error,b,a);return(this.sync||g.sync).call(this,"read",this,a)},save:function(a,b,c){var d,e;f.isObject(a)||a==null?(d=a,c=b):(d={},d[a]=b);c=c?f.clone(c):{};if(c.wait){if(!this._validate(d,c))return false;e=f.clone(this.attributes)}a=f.extend({},c,{silent:true});if(d&&!this.set(d,c.wait?a:c))return false;var k=this,h=c.success;c.success=function(a,b,e){b=k.parse(a,e); -c.wait&&(delete c.wait,b=f.extend(d||{},b));if(!k.set(b,c))return false;h?h(k,a):k.trigger("sync",k,a,c)};c.error=g.wrapError(c.error,k,c);b=this.isNew()?"create":"update";b=(this.sync||g.sync).call(this,b,this,c);c.wait&&this.set(e,a);return b},destroy:function(a){var a=a?f.clone(a):{},b=this,c=a.success,d=function(){b.trigger("destroy",b,b.collection,a)};if(this.isNew())return d(),false;a.success=function(e){a.wait&&d();c?c(b,e):b.trigger("sync",b,e,a)};a.error=g.wrapError(a.error,b,a);var e=(this.sync|| -g.sync).call(this,"delete",this,a);a.wait||d();return e},url:function(){var a=n(this,"urlRoot")||n(this.collection,"url")||t();return this.isNew()?a:a+(a.charAt(a.length-1)=="/"?"":"/")+encodeURIComponent(this.id)},parse:function(a){return a},clone:function(){return new this.constructor(this.attributes)},isNew:function(){return this.id==null},change:function(a){a||(a={});var b=this._changing;this._changing=true;for(var c in this._silent)this._pending[c]=true;var d=f.extend({},a.changes,this._silent); -this._silent={};for(c in d)this.trigger("change:"+c,this,this.get(c),a);if(b)return this;for(;!f.isEmpty(this._pending);){this._pending={};this.trigger("change",this,a);for(c in this.changed)!this._pending[c]&&!this._silent[c]&&delete this.changed[c];this._previousAttributes=f.clone(this.attributes)}this._changing=false;return this},hasChanged:function(a){return!arguments.length?!f.isEmpty(this.changed):f.has(this.changed,a)},changedAttributes:function(a){if(!a)return this.hasChanged()?f.clone(this.changed): -false;var b,c=false,d=this._previousAttributes,e;for(e in a)if(!f.isEqual(d[e],b=a[e]))(c||(c={}))[e]=b;return c},previous:function(a){return!arguments.length||!this._previousAttributes?null:this._previousAttributes[a]},previousAttributes:function(){return f.clone(this._previousAttributes)},isValid:function(){return!this.validate(this.attributes)},_validate:function(a,b){if(b.silent||!this.validate)return true;var a=f.extend({},this.attributes,a),c=this.validate(a,b);if(!c)return true;b&&b.error? -b.error(this,c,b):this.trigger("error",this,c,b);return false}});var r=g.Collection=function(a,b){b||(b={});if(b.model)this.model=b.model;if(b.comparator)this.comparator=b.comparator;this._reset();this.initialize.apply(this,arguments);a&&this.reset(a,{silent:true,parse:b.parse})};f.extend(r.prototype,l,{model:o,initialize:function(){},toJSON:function(a){return this.map(function(b){return b.toJSON(a)})},add:function(a,b){var c,d,e,g,h,j={},i={},l=[];b||(b={});a=f.isArray(a)?a.slice():[a];for(c=0,d= -a.length;c').hide().appendTo("body")[0].contentWindow,this.navigate(a);if(this._hasPushState)i(window).bind("popstate", -this.checkUrl);else if(this._wantsHashChange&&"onhashchange"in window&&!b)i(window).bind("hashchange",this.checkUrl);else if(this._wantsHashChange)this._checkUrlInterval=setInterval(this.checkUrl,this.interval);this.fragment=a;a=window.location;b=a.pathname==this.options.root;if(this._wantsHashChange&&this._wantsPushState&&!this._hasPushState&&!b)return this.fragment=this.getFragment(null,true),window.location.replace(this.options.root+"#"+this.fragment),true;else if(this._wantsPushState&&this._hasPushState&& -b&&a.hash)this.fragment=this.getHash().replace(s,""),window.history.replaceState({},document.title,a.protocol+"//"+a.host+this.options.root+this.fragment);if(!this.options.silent)return this.loadUrl()},stop:function(){i(window).unbind("popstate",this.checkUrl).unbind("hashchange",this.checkUrl);clearInterval(this._checkUrlInterval);m.started=false},route:function(a,b){this.handlers.unshift({route:a,callback:b})},checkUrl:function(){var a=this.getFragment();a==this.fragment&&this.iframe&&(a=this.getFragment(this.getHash(this.iframe))); -if(a==this.fragment)return false;this.iframe&&this.navigate(a);this.loadUrl()||this.loadUrl(this.getHash())},loadUrl:function(a){var b=this.fragment=this.getFragment(a);return f.any(this.handlers,function(a){if(a.route.test(b))return a.callback(b),true})},navigate:function(a,b){if(!m.started)return false;if(!b||b===true)b={trigger:b};var c=(a||"").replace(s,"");if(this.fragment!=c)this._hasPushState?(c.indexOf(this.options.root)!=0&&(c=this.options.root+c),this.fragment=c,window.history[b.replace? -"replaceState":"pushState"]({},document.title,c)):this._wantsHashChange?(this.fragment=c,this._updateHash(window.location,c,b.replace),this.iframe&&c!=this.getFragment(this.getHash(this.iframe))&&(b.replace||this.iframe.document.open().close(),this._updateHash(this.iframe.location,c,b.replace))):window.location.assign(this.options.root+a),b.trigger&&this.loadUrl(a)},_updateHash:function(a,b,c){c?a.replace(a.toString().replace(/(javascript:|#).*$/,"")+"#"+b):a.hash=b}});var v=g.View=function(a){this.cid= -f.uniqueId("view");this._configure(a||{});this._ensureElement();this.initialize.apply(this,arguments);this.delegateEvents()},E=/^(\S+)\s*(.*)$/,w="model,collection,el,id,attributes,className,tagName".split(",");f.extend(v.prototype,l,{tagName:"div",$:function(a){return this.$el.find(a)},initialize:function(){},render:function(){return this},remove:function(){this.$el.remove();return this},make:function(a,b,c){a=document.createElement(a);b&&i(a).attr(b);c!=null&&i(a).html(c);return a},setElement:function(a, -b){this.$el&&this.undelegateEvents();this.$el=a instanceof i?a:i(a);this.el=this.$el[0];b!==false&&this.delegateEvents();return this},delegateEvents:function(a){if(a||(a=n(this,"events"))){this.undelegateEvents();for(var b in a){var c=a[b];f.isFunction(c)||(c=this[a[b]]);if(!c)throw Error('Method "'+a[b]+'" does not exist');var d=b.match(E),e=d[1],d=d[2],c=f.bind(c,this);e+=".delegateEvents"+this.cid;d===""?this.$el.bind(e,c):this.$el.delegate(d,e,c)}}},undelegateEvents:function(){this.$el.unbind(".delegateEvents"+ -this.cid)},_configure:function(a){this.options&&(a=f.extend({},this.options,a));for(var b=0,c=w.length;b').hide().appendTo('body')[0].contentWindow; + this.navigate(fragment); + } + + // Depending on whether we're using pushState or hashes, and whether + // 'onhashchange' is supported, determine how we check the URL state. + if (this._hasPushState) { + Backbone.$(window).on('popstate', this.checkUrl); + } else if (this._wantsHashChange && ('onhashchange' in window) && !oldIE) { + Backbone.$(window).on('hashchange', this.checkUrl); + } else if (this._wantsHashChange) { + this._checkUrlInterval = setInterval(this.checkUrl, this.interval); + } + + // Determine if we need to change the base url, for a pushState link + // opened by a non-pushState browser. + this.fragment = fragment; + var loc = this.location; + var atRoot = loc.pathname.replace(/[^\/]$/, '$&/') === this.root; + + // If we've started off with a route from a `pushState`-enabled browser, + // but we're currently in a browser that doesn't support it... + if (this._wantsHashChange && this._wantsPushState && !this._hasPushState && !atRoot) { + this.fragment = this.getFragment(null, true); + this.location.replace(this.root + this.location.search + '#' + this.fragment); + // Return immediately as browser will do redirect to new url + return true; + + // Or if we've started out with a hash-based route, but we're currently + // in a browser where it could be `pushState`-based instead... + } else if (this._wantsPushState && this._hasPushState && atRoot && loc.hash) { + this.fragment = this.getHash().replace(routeStripper, ''); + this.history.replaceState({}, document.title, this.root + this.fragment + loc.search); + } + + if (!this.options.silent) return this.loadUrl(); + }, + + // Disable Backbone.history, perhaps temporarily. Not useful in a real app, + // but possibly useful for unit testing Routers. + stop: function() { + Backbone.$(window).off('popstate', this.checkUrl).off('hashchange', this.checkUrl); + clearInterval(this._checkUrlInterval); + History.started = false; + }, + + // Add a route to be tested when the fragment changes. Routes added later + // may override previous routes. + route: function(route, callback) { + this.handlers.unshift({route: route, callback: callback}); + }, + + // Checks the current URL to see if it has changed, and if it has, + // calls `loadUrl`, normalizing across the hidden iframe. + checkUrl: function(e) { + var current = this.getFragment(); + if (current === this.fragment && this.iframe) { + current = this.getFragment(this.getHash(this.iframe)); + } + if (current === this.fragment) return false; + if (this.iframe) this.navigate(current); + this.loadUrl() || this.loadUrl(this.getHash()); + }, + + // Attempt to load the current URL fragment. If a route succeeds with a + // match, returns `true`. If no defined routes matches the fragment, + // returns `false`. + loadUrl: function(fragmentOverride) { + var fragment = this.fragment = this.getFragment(fragmentOverride); + var matched = _.any(this.handlers, function(handler) { + if (handler.route.test(fragment)) { + handler.callback(fragment); + return true; + } + }); + return matched; + }, + + // Save a fragment into the hash history, or replace the URL state if the + // 'replace' option is passed. You are responsible for properly URL-encoding + // the fragment in advance. + // + // The options object can contain `trigger: true` if you wish to have the + // route callback be fired (not usually desirable), or `replace: true`, if + // you wish to modify the current URL without adding an entry to the history. + navigate: function(fragment, options) { + if (!History.started) return false; + if (!options || options === true) options = {trigger: options}; + fragment = this.getFragment(fragment || ''); + if (this.fragment === fragment) return; + this.fragment = fragment; + var url = this.root + fragment; + + // If pushState is available, we use it to set the fragment as a real URL. + if (this._hasPushState) { + this.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, url); + + // If hash changes haven't been explicitly disabled, update the hash + // fragment to store history. + } else if (this._wantsHashChange) { + this._updateHash(this.location, fragment, options.replace); + if (this.iframe && (fragment !== this.getFragment(this.getHash(this.iframe)))) { + // Opening and closing the iframe tricks IE7 and earlier to push a + // history entry on hash-tag change. When replace is true, we don't + // want this. + if(!options.replace) this.iframe.document.open().close(); + this._updateHash(this.iframe.location, fragment, options.replace); + } + + // If you've told us that you explicitly don't want fallback hashchange- + // based history, then `navigate` becomes a page refresh. + } else { + return this.location.assign(url); + } + if (options.trigger) this.loadUrl(fragment); + }, + + // Update the hash location, either replacing the current entry, or adding + // a new one to the browser history. + _updateHash: function(location, fragment, replace) { + if (replace) { + var href = location.href.replace(/(javascript:|#).*$/, ''); + location.replace(href + '#' + fragment); + } else { + // gh-1649: Some browsers require that `hash` contains a leading #. + location.hash = '#' + fragment; + } + } + + }); + + // Create the default Backbone.history. + Backbone.history = new History; + + // Backbone.View + // ------------- + + // Creating a Backbone.View creates its initial element outside of the DOM, + // if an existing element is not provided... + var View = Backbone.View = function(options) { + this.cid = _.uniqueId('view'); + this._configure(options || {}); + this._ensureElement(); + this.initialize.apply(this, arguments); + this.delegateEvents(); + }; + + // Cached regex to split keys for `delegate`. + var delegateEventSplitter = /^(\S+)\s*(.*)$/; + + // List of view options to be merged as properties. + var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events']; + + // Set up all inheritable **Backbone.View** properties and methods. + _.extend(View.prototype, Events, { + + // The default `tagName` of a View's element is `"div"`. + tagName: 'div', + + // jQuery delegate for element lookup, scoped to DOM elements within the + // current view. This should be prefered to global lookups where possible. + $: function(selector) { + return this.$el.find(selector); + }, + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize: function(){}, + + // **render** is the core function that your view should override, in order + // to populate its element (`this.el`), with the appropriate HTML. The + // convention is for **render** to always return `this`. + render: function() { + return this; + }, + + // Remove this view by taking the element out of the DOM, and removing any + // applicable Backbone.Events listeners. + remove: function() { + this.$el.remove(); + this.stopListening(); + return this; + }, + + // Change the view's element (`this.el` property), including event + // re-delegation. + setElement: function(element, delegate) { + if (this.$el) this.undelegateEvents(); + this.$el = element instanceof Backbone.$ ? element : Backbone.$(element); + this.el = this.$el[0]; + if (delegate !== false) this.delegateEvents(); + return this; + }, + + // Set callbacks, where `this.events` is a hash of + // + // *{"event selector": "callback"}* + // + // { + // 'mousedown .title': 'edit', + // 'click .button': 'save' + // 'click .open': function(e) { ... } + // } + // + // pairs. Callbacks will be bound to the view, with `this` set properly. + // Uses event delegation for efficiency. + // Omitting the selector binds the event to `this.el`. + // This only works for delegate-able events: not `focus`, `blur`, and + // not `change`, `submit`, and `reset` in Internet Explorer. + delegateEvents: function(events) { + if (!(events || (events = _.result(this, 'events')))) return; + this.undelegateEvents(); + for (var key in events) { + var method = events[key]; + if (!_.isFunction(method)) method = this[events[key]]; + if (!method) throw new Error('Method "' + events[key] + '" does not exist'); + var match = key.match(delegateEventSplitter); + var eventName = match[1], selector = match[2]; + method = _.bind(method, this); + eventName += '.delegateEvents' + this.cid; + if (selector === '') { + this.$el.on(eventName, method); + } else { + this.$el.on(eventName, selector, method); + } + } + }, + + // Clears all callbacks previously bound to the view with `delegateEvents`. + // You usually don't need to use this, but may wish to if you have multiple + // Backbone views attached to the same DOM element. + undelegateEvents: function() { + this.$el.off('.delegateEvents' + this.cid); + }, + + // Performs the initial configuration of a View with a set of options. + // Keys with special meaning *(model, collection, id, className)*, are + // attached directly to the view. + _configure: function(options) { + if (this.options) options = _.extend({}, _.result(this, 'options'), options); + _.extend(this, _.pick(options, viewOptions)); + this.options = options; + }, + + // Ensure that the View has a DOM element to render into. + // If `this.el` is a string, pass it through `$()`, take the first + // matching element, and re-assign it to `el`. Otherwise, create + // an element from the `id`, `className` and `tagName` properties. + _ensureElement: function() { + if (!this.el) { + var attrs = _.extend({}, _.result(this, 'attributes')); + if (this.id) attrs.id = _.result(this, 'id'); + if (this.className) attrs['class'] = _.result(this, 'className'); + var $el = Backbone.$('<' + _.result(this, 'tagName') + '>').attr(attrs); + this.setElement($el, false); + } else { + this.setElement(_.result(this, 'el'), false); + } + } + + }); + + // Backbone.sync + // ------------- + + // Map from CRUD to HTTP for our default `Backbone.sync` implementation. + var methodMap = { + 'create': 'POST', + 'update': 'PUT', + 'patch': 'PATCH', + 'delete': 'DELETE', + 'read': 'GET' + }; + + // Override this function to change the manner in which Backbone persists + // models to the server. You will be passed the type of request, and the + // model in question. By default, makes a RESTful Ajax request + // to the model's `url()`. Some possible customizations could be: + // + // * Use `setTimeout` to batch rapid-fire updates into a single request. + // * Send up the models as XML instead of JSON. + // * Persist models via WebSockets instead of Ajax. + // + // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests + // as `POST`, with a `_method` parameter containing the true HTTP method, + // as well as all requests with the body as `application/x-www-form-urlencoded` + // instead of `application/json` with the model in a param named `model`. + // Useful when interfacing with server-side languages like **PHP** that make + // it difficult to read the body of `PUT` requests. + Backbone.sync = function(method, model, options) { + var type = methodMap[method]; + + // Default options, unless specified. + _.defaults(options || (options = {}), { + emulateHTTP: Backbone.emulateHTTP, + emulateJSON: Backbone.emulateJSON + }); + + // Default JSON-request options. + var params = {type: type, dataType: 'json'}; + + // Ensure that we have a URL. + if (!options.url) { + params.url = _.result(model, 'url') || urlError(); + } + + // Ensure that we have the appropriate request data. + if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) { + params.contentType = 'application/json'; + params.data = JSON.stringify(options.attrs || model.toJSON(options)); + } + + // For older servers, emulate JSON by encoding the request into an HTML-form. + if (options.emulateJSON) { + params.contentType = 'application/x-www-form-urlencoded'; + params.data = params.data ? {model: params.data} : {}; + } + + // For older servers, emulate HTTP by mimicking the HTTP method with `_method` + // And an `X-HTTP-Method-Override` header. + if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) { + params.type = 'POST'; + if (options.emulateJSON) params.data._method = type; + var beforeSend = options.beforeSend; + options.beforeSend = function(xhr) { + xhr.setRequestHeader('X-HTTP-Method-Override', type); + if (beforeSend) return beforeSend.apply(this, arguments); + }; + } + + // Don't process data on a non-GET request. + if (params.type !== 'GET' && !options.emulateJSON) { + params.processData = false; + } + + var success = options.success; + options.success = function(resp) { + if (success) success(model, resp, options); + model.trigger('sync', model, resp, options); + }; + + var error = options.error; + options.error = function(xhr) { + if (error) error(model, xhr, options); + model.trigger('error', model, xhr, options); + }; + + // Make the request, allowing the user to override any Ajax options. + var xhr = options.xhr = Backbone.ajax(_.extend(params, options)); + model.trigger('request', model, xhr, options); + return xhr; + }; + + // Set the default implementation of `Backbone.ajax` to proxy through to `$`. + Backbone.ajax = function() { + return Backbone.$.ajax.apply(Backbone.$, arguments); + }; + + // Helpers + // ------- + + // Helper function to correctly set up the prototype chain, for subclasses. + // Similar to `goog.inherits`, but uses a hash of prototype properties and + // class properties to be extended. + var extend = function(protoProps, staticProps) { + var parent = this; + var child; + + // The constructor function for the new subclass is either defined by you + // (the "constructor" property in your `extend` definition), or defaulted + // by us to simply call the parent's constructor. + if (protoProps && _.has(protoProps, 'constructor')) { + child = protoProps.constructor; + } else { + child = function(){ return parent.apply(this, arguments); }; + } + + // Add static properties to the constructor function, if supplied. + _.extend(child, parent, staticProps); + + // Set the prototype chain to inherit from `parent`, without calling + // `parent`'s constructor function. + var Surrogate = function(){ this.constructor = child; }; + Surrogate.prototype = parent.prototype; + child.prototype = new Surrogate; + + // Add prototype properties (instance properties) to the subclass, + // if supplied. + if (protoProps) _.extend(child.prototype, protoProps); + + // Set a convenience property in case the parent's prototype is needed + // later. + child.__super__ = parent.prototype; + + return child; + }; + + // Set up inheritance for the model, collection, router, view and history. + Model.extend = Collection.extend = Router.extend = View.extend = History.extend = extend; + + // Throw an error when a URL is needed, and none is supplied. + var urlError = function() { + throw new Error('A "url" property or function must be specified'); + }; + + return Backbone; +})); diff --git a/js/libs/underscore/underscore-min.js b/js/libs/underscore/underscore-min.js deleted file mode 100644 index 9f494e6..0000000 --- a/js/libs/underscore/underscore-min.js +++ /dev/null @@ -1,31 +0,0 @@ -// Underscore.js 1.3.1 -// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. -// Underscore is freely distributable under the MIT license. -// Portions of Underscore are inspired or borrowed from Prototype, -// Oliver Steele's Functional, and John Resig's Micro-Templating. -// For all details and documentation: -// http://documentcloud.github.com/underscore -(function(){function q(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== -c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&q(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&q(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c, -h)&&!f--)break;g=!f}}d.pop();return g}var r=this,G=r._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,H=k.unshift,l=o.toString,I=o.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,p=k.indexOf,D=k.lastIndexOf,o=Array.isArray,J=Object.keys,s=Function.prototype.bind,b=function(a){return new m(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else typeof define==="function"&&define.amd&& -define("underscore",function(){return b}),r._=b;b.VERSION="1.3.1";var j=b.each=b.forEach=function(a,c,d){if(a!=null)if(w&&a.forEach===w)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a==null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&& -(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e; -if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e=e&&c.call(b,a,g,h)))return n});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return n});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return p&&a.indexOf===p?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a, -function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck=function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a, -b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c= -e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e= -0;e= -0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=J||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]}); -return a};b.defaults=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return q(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=o||function(a){return l.call(a)=="[object Array]"}; -b.isObject=function(a){return a===Object(a)};b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!b.has(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate= -function(a){return l.call(a)=="[object Date]"};b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return I.call(a,b)};b.noConflict=function(){r._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g, -"/")};b.mixin=function(a){j(b.functions(a),function(c){K(c,b[c]=a[c])})};var L=0;b.uniqueId=function(a){var b=L++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var t=/.^/,u=function(a){return a.replace(/\\\\/g,"\\").replace(/\\'/g,"'")};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape|| -t,function(a,b){return"',_.escape("+u(b)+"),'"}).replace(d.interpolate||t,function(a,b){return"',"+u(b)+",'"}).replace(d.evaluate||t,function(a,b){return"');"+u(b).replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var v=function(a,c){return c? -b(a).chain():a},K=function(a,c){m.prototype[a]=function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return v(b.apply(this._wrapped,arguments), -this._chain)}});m.prototype.chain=function(){this._chain=true;return this};m.prototype.value=function(){return this._wrapped}}).call(this); diff --git a/js/libs/underscore/underscore.js b/js/libs/underscore/underscore.js new file mode 100644 index 0000000..5574d14 --- /dev/null +++ b/js/libs/underscore/underscore.js @@ -0,0 +1,1234 @@ +// Underscore.js 1.4.4 +// http://underscorejs.org +// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore may be freely distributed under the MIT license. + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `global` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Establish the object that gets returned to break out of a loop iteration. + var breaker = {}; + + // Save bytes in the minified (but not gzipped) version: + var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; + + // Create quick reference variables for speed access to core prototypes. + var push = ArrayProto.push, + slice = ArrayProto.slice, + concat = ArrayProto.concat, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeForEach = ArrayProto.forEach, + nativeMap = ArrayProto.map, + nativeReduce = ArrayProto.reduce, + nativeReduceRight = ArrayProto.reduceRight, + nativeFilter = ArrayProto.filter, + nativeEvery = ArrayProto.every, + nativeSome = ArrayProto.some, + nativeIndexOf = ArrayProto.indexOf, + nativeLastIndexOf = ArrayProto.lastIndexOf, + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { + if (obj instanceof _) return obj; + if (!(this instanceof _)) return new _(obj); + this._wrapped = obj; + }; + + // Export the Underscore object for **Node.js**, with + // backwards-compatibility for the old `require()` API. If we're in + // the browser, add `_` as a global object via a string identifier, + // for Closure Compiler "advanced" mode. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else { + root._ = _; + } + + // Current version. + _.VERSION = '1.4.4'; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles objects with the built-in `forEach`, arrays, and raw objects. + // Delegates to **ECMAScript 5**'s native `forEach` if available. + var each = _.each = _.forEach = function(obj, iterator, context) { + if (obj == null) return; + if (nativeForEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (var i = 0, l = obj.length; i < l; i++) { + if (iterator.call(context, obj[i], i, obj) === breaker) return; + } + } else { + for (var key in obj) { + if (_.has(obj, key)) { + if (iterator.call(context, obj[key], key, obj) === breaker) return; + } + } + } + }; + + // Return the results of applying the iterator to each element. + // Delegates to **ECMAScript 5**'s native `map` if available. + _.map = _.collect = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); + each(obj, function(value, index, list) { + results[results.length] = iterator.call(context, value, index, list); + }); + return results; + }; + + var reduceError = 'Reduce of empty array with no initial value'; + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. + _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduce && obj.reduce === nativeReduce) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); + } + each(obj, function(value, index, list) { + if (!initial) { + memo = value; + initial = true; + } else { + memo = iterator.call(context, memo, value, index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // The right-associative version of reduce, also known as `foldr`. + // Delegates to **ECMAScript 5**'s native `reduceRight` if available. + _.reduceRight = _.foldr = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + } + var length = obj.length; + if (length !== +length) { + var keys = _.keys(obj); + length = keys.length; + } + each(obj, function(value, index, list) { + index = keys ? keys[--length] : --length; + if (!initial) { + memo = obj[index]; + initial = true; + } else { + memo = iterator.call(context, memo, obj[index], index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, iterator, context) { + var result; + any(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) { + result = value; + return true; + } + }); + return result; + }; + + // Return all the elements that pass a truth test. + // Delegates to **ECMAScript 5**'s native `filter` if available. + // Aliased as `select`. + _.filter = _.select = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); + each(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) results[results.length] = value; + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, iterator, context) { + return _.filter(obj, function(value, index, list) { + return !iterator.call(context, value, index, list); + }, context); + }; + + // Determine whether all of the elements match a truth test. + // Delegates to **ECMAScript 5**'s native `every` if available. + // Aliased as `all`. + _.every = _.all = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = true; + if (obj == null) return result; + if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); + each(obj, function(value, index, list) { + if (!(result = result && iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if at least one element in the object matches a truth test. + // Delegates to **ECMAScript 5**'s native `some` if available. + // Aliased as `any`. + var any = _.some = _.any = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = false; + if (obj == null) return result; + if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); + each(obj, function(value, index, list) { + if (result || (result = iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if the array or object contains a given value (using `===`). + // Aliased as `include`. + _.contains = _.include = function(obj, target) { + if (obj == null) return false; + if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; + return any(obj, function(value) { + return value === target; + }); + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + var isFunc = _.isFunction(method); + return _.map(obj, function(value) { + return (isFunc ? method : value[method]).apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, function(value){ return value[key]; }); + }; + + // Convenience version of a common use case of `filter`: selecting only objects + // containing specific `key:value` pairs. + _.where = function(obj, attrs, first) { + if (_.isEmpty(attrs)) return first ? null : []; + return _[first ? 'find' : 'filter'](obj, function(value) { + for (var key in attrs) { + if (attrs[key] !== value[key]) return false; + } + return true; + }); + }; + + // Convenience version of a common use case of `find`: getting the first object + // containing specific `key:value` pairs. + _.findWhere = function(obj, attrs) { + return _.where(obj, attrs, true); + }; + + // Return the maximum element or (element-based computation). + // Can't optimize arrays of integers longer than 65,535 elements. + // See: https://bugs.webkit.org/show_bug.cgi?id=80797 + _.max = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.max.apply(Math, obj); + } + if (!iterator && _.isEmpty(obj)) return -Infinity; + var result = {computed : -Infinity, value: -Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed >= result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.min.apply(Math, obj); + } + if (!iterator && _.isEmpty(obj)) return Infinity; + var result = {computed : Infinity, value: Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed < result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Shuffle an array. + _.shuffle = function(obj) { + var rand; + var index = 0; + var shuffled = []; + each(obj, function(value) { + rand = _.random(index++); + shuffled[index - 1] = shuffled[rand]; + shuffled[rand] = value; + }); + return shuffled; + }; + + // An internal function to generate lookup iterators. + var lookupIterator = function(value) { + return _.isFunction(value) ? value : function(obj){ return obj[value]; }; + }; + + // Sort the object's values by a criterion produced by an iterator. + _.sortBy = function(obj, value, context) { + var iterator = lookupIterator(value); + return _.pluck(_.map(obj, function(value, index, list) { + return { + value : value, + index : index, + criteria : iterator.call(context, value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index < right.index ? -1 : 1; + }), 'value'); + }; + + // An internal function used for aggregate "group by" operations. + var group = function(obj, value, context, behavior) { + var result = {}; + var iterator = lookupIterator(value || _.identity); + each(obj, function(value, index) { + var key = iterator.call(context, value, index, obj); + behavior(result, key, value); + }); + return result; + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = function(obj, value, context) { + return group(obj, value, context, function(result, key, value) { + (_.has(result, key) ? result[key] : (result[key] = [])).push(value); + }); + }; + + // Counts instances of an object that group by a certain criterion. Pass + // either a string attribute to count by, or a function that returns the + // criterion. + _.countBy = function(obj, value, context) { + return group(obj, value, context, function(result, key) { + if (!_.has(result, key)) result[key] = 0; + result[key]++; + }); + }; + + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iterator, context) { + iterator = iterator == null ? _.identity : lookupIterator(iterator); + var value = iterator.call(context, obj); + var low = 0, high = array.length; + while (low < high) { + var mid = (low + high) >>> 1; + iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid; + } + return low; + }; + + // Safely convert anything iterable into a real, live array. + _.toArray = function(obj) { + if (!obj) return []; + if (_.isArray(obj)) return slice.call(obj); + if (obj.length === +obj.length) return _.map(obj, _.identity); + return _.values(obj); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + if (obj == null) return 0; + return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head` and `take`. The **guard** check + // allows it to work with `_.map`. + _.first = _.head = _.take = function(array, n, guard) { + if (array == null) return void 0; + return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; + }; + + // Returns everything but the last entry of the array. Especially useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. The **guard** check allows it to work with + // `_.map`. + _.initial = function(array, n, guard) { + return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. The **guard** check allows it to work with `_.map`. + _.last = function(array, n, guard) { + if (array == null) return void 0; + if ((n != null) && !guard) { + return slice.call(array, Math.max(array.length - n, 0)); + } else { + return array[array.length - 1]; + } + }; + + // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. + // Especially useful on the arguments object. Passing an **n** will return + // the rest N values in the array. The **guard** + // check allows it to work with `_.map`. + _.rest = _.tail = _.drop = function(array, n, guard) { + return slice.call(array, (n == null) || guard ? 1 : n); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, _.identity); + }; + + // Internal implementation of a recursive `flatten` function. + var flatten = function(input, shallow, output) { + each(input, function(value) { + if (_.isArray(value)) { + shallow ? push.apply(output, value) : flatten(value, shallow, output); + } else { + output.push(value); + } + }); + return output; + }; + + // Return a completely flattened version of an array. + _.flatten = function(array, shallow) { + return flatten(array, shallow, []); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iterator, context) { + if (_.isFunction(isSorted)) { + context = iterator; + iterator = isSorted; + isSorted = false; + } + var initial = iterator ? _.map(array, iterator, context) : array; + var results = []; + var seen = []; + each(initial, function(value, index) { + if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { + seen.push(value); + results.push(array[index]); + } + }); + return results; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(concat.apply(ArrayProto, arguments)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. + _.intersection = function(array) { + var rest = slice.call(arguments, 1); + return _.filter(_.uniq(array), function(item) { + return _.every(rest, function(other) { + return _.indexOf(other, item) >= 0; + }); + }); + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function(array) { + var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); + return _.filter(array, function(value){ return !_.contains(rest, value); }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + var args = slice.call(arguments); + var length = _.max(_.pluck(args, 'length')); + var results = new Array(length); + for (var i = 0; i < length; i++) { + results[i] = _.pluck(args, "" + i); + } + return results; + }; + + // Converts lists into objects. Pass either a single array of `[key, value]` + // pairs, or two parallel arrays of the same length -- one of keys, and one of + // the corresponding values. + _.object = function(list, values) { + if (list == null) return {}; + var result = {}; + for (var i = 0, l = list.length; i < l; i++) { + if (values) { + result[list[i]] = values[i]; + } else { + result[list[i][0]] = list[i][1]; + } + } + return result; + }; + + // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), + // we need this function. Return the position of the first occurrence of an + // item in an array, or -1 if the item is not included in the array. + // Delegates to **ECMAScript 5**'s native `indexOf` if available. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = function(array, item, isSorted) { + if (array == null) return -1; + var i = 0, l = array.length; + if (isSorted) { + if (typeof isSorted == 'number') { + i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted); + } else { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + } + if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); + for (; i < l; i++) if (array[i] === item) return i; + return -1; + }; + + // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. + _.lastIndexOf = function(array, item, from) { + if (array == null) return -1; + var hasIndex = from != null; + if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { + return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); + } + var i = (hasIndex ? from : array.length); + while (i--) if (array[i] === item) return i; + return -1; + }; + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = arguments[2] || 1; + + var len = Math.max(Math.ceil((stop - start) / step), 0); + var idx = 0; + var range = new Array(len); + + while(idx < len) { + range[idx++] = start; + start += step; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if + // available. + _.bind = function(func, context) { + if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + var args = slice.call(arguments, 2); + return function() { + return func.apply(context, args.concat(slice.call(arguments))); + }; + }; + + // Partially apply a function by creating a version that has had some of its + // arguments pre-filled, without changing its dynamic `this` context. + _.partial = function(func) { + var args = slice.call(arguments, 1); + return function() { + return func.apply(this, args.concat(slice.call(arguments))); + }; + }; + + // Bind all of an object's methods to that object. Useful for ensuring that + // all callbacks defined on an object belong to it. + _.bindAll = function(obj) { + var funcs = slice.call(arguments, 1); + if (funcs.length === 0) funcs = _.functions(obj); + each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memo = {}; + hasher || (hasher = _.identity); + return function() { + var key = hasher.apply(this, arguments); + return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); + }; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ return func.apply(null, args); }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = function(func) { + return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); + }; + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. + _.throttle = function(func, wait) { + var context, args, timeout, result; + var previous = 0; + var later = function() { + previous = new Date; + timeout = null; + result = func.apply(context, args); + }; + return function() { + var now = new Date; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + } else if (!timeout) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + _.debounce = function(func, wait, immediate) { + var timeout, result; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + if (!immediate) result = func.apply(context, args); + }; + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) result = func.apply(context, args); + return result; + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = function(func) { + var ran = false, memo; + return function() { + if (ran) return memo; + ran = true; + memo = func.apply(this, arguments); + func = null; + return memo; + }; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return function() { + var args = [func]; + push.apply(args, arguments); + return wrapper.apply(this, args); + }; + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var funcs = arguments; + return function() { + var args = arguments; + for (var i = funcs.length - 1; i >= 0; i--) { + args = [funcs[i].apply(this, args)]; + } + return args[0]; + }; + }; + + // Returns a function that will only be executed after being called N times. + _.after = function(times, func) { + if (times <= 0) return func(); + return function() { + if (--times < 1) { + return func.apply(this, arguments); + } + }; + }; + + // Object Functions + // ---------------- + + // Retrieve the names of an object's properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = nativeKeys || function(obj) { + if (obj !== Object(obj)) throw new TypeError('Invalid object'); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key; + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + var values = []; + for (var key in obj) if (_.has(obj, key)) values.push(obj[key]); + return values; + }; + + // Convert an object into a list of `[key, value]` pairs. + _.pairs = function(obj) { + var pairs = []; + for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]); + return pairs; + }; + + // Invert the keys and values of an object. The values must be serializable. + _.invert = function(obj) { + var result = {}; + for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key; + return result; + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Return a copy of the object only containing the whitelisted properties. + _.pick = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + each(keys, function(key) { + if (key in obj) copy[key] = obj[key]; + }); + return copy; + }; + + // Return a copy of the object without the blacklisted properties. + _.omit = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + for (var key in obj) { + if (!_.contains(keys, key)) copy[key] = obj[key]; + } + return copy; + }; + + // Fill in a given object with default properties. + _.defaults = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + if (obj[prop] == null) obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Internal recursive comparison function for `isEqual`. + var eq = function(a, b, aStack, bStack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal. + if (a === b) return a !== 0 || 1 / a == 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a instanceof _) a = a._wrapped; + if (b instanceof _) b = b._wrapped; + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className != toString.call(b)) return false; + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a == +b; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') return false; + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] == a) return bStack[length] == b; + } + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + var size = 0, result = true; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + if (!(result = eq(a[size], b[size], aStack, bStack))) break; + } + } + } else { + // Objects with different constructors are not equivalent, but `Object`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) && + _.isFunction(bCtor) && (bCtor instanceof bCtor))) { + return false; + } + // Deep compare objects. + for (var key in a) { + if (_.has(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (_.has(b, key) && !(size--)) break; + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + return result; + }; + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b, [], []); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (obj == null) return true; + if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; + for (var key in obj) if (_.has(obj, key)) return false; + return true; + }; + + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType === 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) == '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function(obj) { + return obj === Object(obj); + }; + + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. + each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { + _['is' + name] = function(obj) { + return toString.call(obj) == '[object ' + name + ']'; + }; + }); + + // Define a fallback version of the method in browsers (ahem, IE), where + // there isn't any inspectable "Arguments" type. + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return !!(obj && _.has(obj, 'callee')); + }; + } + + // Optimize `isFunction` if appropriate. + if (typeof (/./) !== 'function') { + _.isFunction = function(obj) { + return typeof obj === 'function'; + }; + } + + // Is a given object a finite number? + _.isFinite = function(obj) { + return isFinite(obj) && !isNaN(parseFloat(obj)); + }; + + // Is the given value `NaN`? (NaN is the only number which does not equal itself). + _.isNaN = function(obj) { + return _.isNumber(obj) && obj != +obj; + }; + + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; + }; + + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Shortcut function for checking if an object has a given property directly + // on itself (in other words, not on a prototype). + _.has = function(obj, key) { + return hasOwnProperty.call(obj, key); + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iterators. + _.identity = function(value) { + return value; + }; + + // Run a function **n** times. + _.times = function(n, iterator, context) { + var accum = Array(n); + for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); + return accum; + }; + + // Return a random integer between min and max (inclusive). + _.random = function(min, max) { + if (max == null) { + max = min; + min = 0; + } + return min + Math.floor(Math.random() * (max - min + 1)); + }; + + // List of HTML entities for escaping. + var entityMap = { + escape: { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '/': '/' + } + }; + entityMap.unescape = _.invert(entityMap.escape); + + // Regexes containing the keys and values listed immediately above. + var entityRegexes = { + escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'), + unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g') + }; + + // Functions for escaping and unescaping strings to/from HTML interpolation. + _.each(['escape', 'unescape'], function(method) { + _[method] = function(string) { + if (string == null) return ''; + return ('' + string).replace(entityRegexes[method], function(match) { + return entityMap[method][match]; + }); + }; + }); + + // If the value of the named property is a function then invoke it; + // otherwise, return it. + _.result = function(object, property) { + if (object == null) return null; + var value = object[property]; + return _.isFunction(value) ? value.call(object) : value; + }; + + // Add your own custom functions to the Underscore object. + _.mixin = function(obj) { + each(_.functions(obj), function(name){ + var func = _[name] = obj[name]; + _.prototype[name] = function() { + var args = [this._wrapped]; + push.apply(args, arguments); + return result.call(this, func.apply(_, args)); + }; + }); + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /(.)^/; + + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\t': 't', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + _.template = function(text, data, settings) { + var render; + settings = _.defaults({}, settings, _.templateSettings); + + // Combine delimiters into one regular expression via alternation. + var matcher = new RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + + // Compile the template source, escaping string literals appropriately. + var index = 0; + var source = "__p+='"; + text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset) + .replace(escaper, function(match) { return '\\' + escapes[match]; }); + + if (escape) { + source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; + } + if (interpolate) { + source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; + } + if (evaluate) { + source += "';\n" + evaluate + "\n__p+='"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + + // If a variable is not specified, place data values in local scope. + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __t,__p='',__j=Array.prototype.join," + + "print=function(){__p+=__j.call(arguments,'');};\n" + + source + "return __p;\n"; + + try { + render = new Function(settings.variable || 'obj', '_', source); + } catch (e) { + e.source = source; + throw e; + } + + if (data) return render(data, _); + var template = function(data) { + return render.call(this, data, _); + }; + + // Provide the compiled function source as a convenience for precompilation. + template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; + + return template; + }; + + // Add a "chain" function, which will delegate to the wrapper. + _.chain = function(obj) { + return _(obj).chain(); + }; + + // OOP + // --------------- + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + + // Helper function to continue chaining intermediate results. + var result = function(obj) { + return this._chain ? _(obj).chain() : obj; + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + var obj = this._wrapped; + method.apply(obj, arguments); + if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; + return result.call(this, obj); + }; + }); + + // Add all accessor Array functions to the wrapper. + each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + return result.call(this, method.apply(this._wrapped, arguments)); + }; + }); + + _.extend(_.prototype, { + + // Start chaining a wrapped Underscore object. + chain: function() { + this._chain = true; + return this; + }, + + // Extracts the result from a wrapped and chained object. + value: function() { + return this._wrapped; + } + + }); + + // AMD define happens at the end for compatibility with AMD loaders + // that don't enforce next-turn semantics on modules. + if (typeof define === 'function' && define.amd) { + define('underscore', function() { + return _; + }); + } + +}).call(this); diff --git a/js/main.js b/js/main.js index 91ed174..2bba6a2 100644 --- a/js/main.js +++ b/js/main.js @@ -13,8 +13,8 @@ require.config({ paths: { // Major libraries jquery: Config.use_cdn ? 'https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.min' : 'libs/jquery/jquery-min', - underscore: Config.use_cdn ? 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.9.2/lodash.min' : 'libs/underscore/underscore-min', // https://github.com/amdjs - backbone: 'libs/backbone/backbone-min', // https://github.com/amdjs + underscore: 'libs/underscore/underscore', // https://github.com/amdjs + backbone: 'libs/backbone/backbone', // https://github.com/amdjs prettyprint: 'libs/prettyprint/prettyprint', qtip: 'libs/qtip2/jquery.qtip.min', marked: 'libs/marked/marked', From bda345646a75dbef21783c02008fe7c20a7e51cd Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 3 Mar 2013 15:28:18 +1000 Subject: [PATCH 501/531] presist the Resource object between resource and method list view so that we don't have to requery it needlessly --- js/views/methods/list.js | 26 ++++++++++++++++---------- js/views/resource/list.js | 28 +++++++++++++++++++++++----- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/js/views/methods/list.js b/js/views/methods/list.js index ae9aa0e..5614872 100644 --- a/js/views/methods/list.js +++ b/js/views/methods/list.js @@ -10,9 +10,9 @@ define([ 'views/forms/method', 'views/methods/page', 'collections/methods', - 'models/method', + 'models/resource', 'models/notificationtotal' - ], function($, _, Backbone, Vm, Mustache, Session, resourceListTemplate, ResourceForm, MethodForm, MethodView, Methods, MethodModel, NTotals){ + ], function($, _, Backbone, Vm, Mustache, Session, resourceListTemplate, ResourceForm, MethodForm, MethodView, Methods, ResourceModel, NTotals){ var ApisPage = Backbone.View.extend({ el: '.method-list-container', initialize: function () { @@ -59,17 +59,23 @@ define([ render: function () { var that = this; this.methods = new Methods(); - this.resource = new MethodModel(); + + // re-request resource only if necessary + if (that.options.resource) { + this.resource = that.options.resource; + } else { + this.resource = new ResourceModel(); + this.resource.options = { + username: that.options.username, + apiname: that.options.apiname, + version: that.options.version, + resourceId: that.options.resourceId + }; + this.resource.fetch(); + } that.$el.attr('data-resource-id', that.options.resourceId); that.$el.fadeIn(200); - this.resource.set({ - username: that.options.username, - apiname: that.options.apiname, - version: that.options.version, - resourceId: that.options.resourceId - }); - this.resource.fetch(); this.methods.username = that.options.username; this.methods.apiname = that.options.apiname; this.methods.version = that.options.version; diff --git a/js/views/resource/list.js b/js/views/resource/list.js index 94ed23b..32bbcab 100644 --- a/js/views/resource/list.js +++ b/js/views/resource/list.js @@ -48,9 +48,19 @@ define([ this.expandMethods(ele); }, expandMethods: function (ele) { - var resourceId = $(ele).attr('data-resource-id'); - var el = $(ele).next('li'); - var methodListView = Vm.create(this, 'methodlist'+this.options.resourceId, MethodsListView, {username: this.options.username, apiname: this.options.apiname, version: this.options.version, resourceId: resourceId, method: this.options.method, el: el}); + var resourceId = $(ele).attr('data-resource-id'), + resource = this.resources.get(resourceId), + el = $(ele).next('li'); + + var methodListView = Vm.create(this, 'methodlist'+this.options.resourceId, MethodsListView, { + username: this.options.username, + apiname: this.options.apiname, + version: this.options.version, + resourceId: resourceId, + resource: resource, + method: this.options.method, + el: el + }); methodListView.setElement(el); methodListView.render(); }, @@ -59,8 +69,11 @@ define([ $('.resource-submenu').fadeOut(200); }, render: function () { - var that = this; - var resources = new ResourcesCollection(); + var that = this, + resources = new ResourcesCollection(); + + that.resources = resources; // assign to the view so we don't have to requery in method lists + resources.username = that.options.username; resources.apiname = that.options.apiname; resources.version = that.options.version; @@ -110,6 +123,11 @@ define([ }); + }, + + clean : function() + { + this.resources = null; } }); return ApisPage; From 975f115763898da6594b9f52d05dd1687170960c Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 3 Mar 2013 16:28:17 +1000 Subject: [PATCH 502/531] enhance modal to allow inline popup of arbitrary page components --- js/libs/modal/modal.js | 95 +++++++++++++++++++++++++++++------------- 1 file changed, 65 insertions(+), 30 deletions(-) diff --git a/js/libs/modal/modal.js b/js/libs/modal/modal.js index 3143740..7081e9d 100644 --- a/js/libs/modal/modal.js +++ b/js/libs/modal/modal.js @@ -10,9 +10,16 @@ define(['jquery', 'autogrow', 'mustache', 'form', 'text!templates/modals/inlinee // title : 'Edit description', title for inline edit dialog. Defaults to 'data-inline-title' attribute of 'from' element. // savetext : 'text for OK button', default 'Save' // canceltext : 'text for cancel button' default 'Cancel' + // + // cloneDOM : false if true, take the whole DOM node for 'from' element, instead of putting its value inside the edit field // } startHidden : false }; + + //---------------------------------------------------------------------------- + // INITIAL RENDERING + //---------------------------------------------------------------------------- + var modal = function (options) { var options = $.extend({}, defaultOptions, options), that = this; @@ -33,7 +40,7 @@ define(['jquery', 'autogrow', 'mustache', 'form', 'text!templates/modals/inlinee var from = $(options.inline.from); this.el.html(Mustache.render(inlineEditTpl, { title : options.inline.title || from.attr('data-inline-title') || 'Edit field', - value : $.trim(options.inline.value || from.val() || from.text()), + value : options.inline.cloneDOM ? '' : ($.trim(options.inline.value || from.val() || from.text())), savetext : options.inline.savetext || 'Save', canceltext : options.inline.canceltext || 'Cancel' }, { @@ -45,35 +52,30 @@ define(['jquery', 'autogrow', 'mustache', 'form', 'text!templates/modals/inlinee $('body').append(this.el); // position onscreen depending on modal type - if(options.inline) { - var to = $(".inline-field", this.el), - fromTop = from.offset().top, - fromLeft = from.offset().left, - toTop = this.el.offset().top - to.offset().top - - parseInt(to.css('padding-top')) + parseInt(from.css('padding-top')) - - (parseInt(to.css('border-top-width')) - parseInt(from.css('border-top-width'))), - toLeft = this.el.offset().left - to.offset().left - - parseInt(to.css('padding-left')) + parseInt(from.css('padding-left')) - - (parseInt(to.css('border-left-width')) - parseInt(from.css('border-left-width'))); - - to.css({ - width: from.width(), - height: from.height(), - fontSize : from.css('font-size'), - fontFamily : from.css('font-family') - }); - - this.el.css({ - top: fromTop + toTop, - left: fromLeft + toLeft, - position: 'absolute' - }); - - to.autogrow(); + if (!options.inline) { + // REGULAR CENTERED MODALS + $(this.el).css({ + 'margin-left': -($(this.el).width() / 2) + 'px' + }); + } else if (!options.inline.cloneDOM) { + // INLINE EDIT MODALS + var to = $(".inline-field", this.el); + + matchPosition.call(this, from, to); + + to.css({ + fontSize : from.css('font-size'), + fontFamily : from.css('font-family') + }); + + to.autogrow(); } else { - $(this.el).css({ - 'margin-left': -($(this.el).width() / 2) + 'px' - }); + // INLINE COMPLEX MODALS + var to = $(options.inline.from).clone(); + + this.el.find('.inline-field').replaceWith(to); + + matchPosition.call(this, from, to); } // bind form controller if one is specified in options @@ -114,6 +116,37 @@ define(['jquery', 'autogrow', 'mustache', 'form', 'text!templates/modals/inlinee } }; + //---------------------------------------------------------------------------- + // INTERNALS + //---------------------------------------------------------------------------- + + function matchPosition(from, to) + { + fromTop = from.offset().top, + fromLeft = from.offset().left, + toTop = this.el.offset().top - to.offset().top - + parseInt(to.css('padding-top')) + parseInt(from.css('padding-top')) - + (parseInt(to.css('border-top-width')) - parseInt(from.css('border-top-width'))), + toLeft = this.el.offset().left - to.offset().left - + parseInt(to.css('padding-left')) + parseInt(from.css('padding-left')) - + (parseInt(to.css('border-left-width')) - parseInt(from.css('border-left-width'))); + + to.css({ + width: from.width(), + height: from.height() + }); + + this.el.css({ + top: fromTop + toTop, + left: fromLeft + toLeft, + position: 'absolute' + }); + } + + //---------------------------------------------------------------------------- + // OBJECT METHODS + //---------------------------------------------------------------------------- + modal.prototype.show = function () { this.el.addClass('shown'); if (this.inline) { @@ -133,7 +166,9 @@ define(['jquery', 'autogrow', 'mustache', 'form', 'text!templates/modals/inlinee }); }; - + //---------------------------------------------------------------------------- + // FACTORY + //---------------------------------------------------------------------------- var create = function (options) { var Modal = new modal(options); From 8f3d756e53f37e66f6a1d812785a397ee0c9373d Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 3 Mar 2013 16:41:22 +1000 Subject: [PATCH 503/531] start hooking up new method creation UI modify API resource list CSS so that borders find their way into the inline 'new method' popup whitespace fixes to CSS file --- css/apimenu.css | 37 ++++++++++++++++++---------------- js/views/apis/documentation.js | 16 ++++++++------- templates/apis/docs.html | 2 +- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/css/apimenu.css b/css/apimenu.css index d48ffed..f86727c 100644 --- a/css/apimenu.css +++ b/css/apimenu.css @@ -1,4 +1,4 @@ -/* +/* # API Resource Menu ``` @@ -12,7 +12,7 @@ - + - +
  • Api Version's @@ -54,7 +54,7 @@
    Loading
    - +
  • @@ -63,10 +63,8 @@ */ .api-menu-container { - width: 300px; + width: 300px; background: #fff; - border-left: 1px solid #ebebeb; - border-right: 1px solid #ebebeb; margin-bottom: 50px; padding-top: 5px; } @@ -83,9 +81,9 @@ width: 18px; height: 18px; background: url('../img/ajax-cog.png?embed'); - -webkit-animation-name: spin; + -webkit-animation-name: spin; -webkit-animation-duration: 2000ms; /* 40 seconds */ - -webkit-animation-iteration-count: infinite; + -webkit-animation-iteration-count: infinite; -webkit-animation-timing-function: linear; float: left; margin-right: 10px; @@ -96,7 +94,7 @@ .api-menu-list li .api-menu-list li:last-child { border-bottom: none; } - .api-list-ajax, + .api-list-ajax, .api-menu-list li a { display: block; padding: 15px 10px 15px 10px; @@ -111,6 +109,11 @@ position: relative; } + .api-menu-list.api-overview, .resource-list-container { + border-left: 1px solid #ebebeb; + border-right: 1px solid #ebebeb; + } + /* creates the smaller triangle */ .api-menu-list li a.active:after, .api-menu-list li a:hover:after { @@ -122,7 +125,7 @@ border-style:solid; border-color:#fff transparent; /* reduce the damage in FF3.0 */ - display:block; + display:block; width:0; } @@ -188,7 +191,7 @@ padding-left: 0; } - .resource-list { + .resource-list { list-style: none; padding: 0; margin: 0; @@ -223,7 +226,7 @@ width: 203px; line-height: 48px; } - .method-list { + .method-list { list-style: none; padding: 0; margin: 0; diff --git a/js/views/apis/documentation.js b/js/views/apis/documentation.js index 1fb931b..d0c405d 100644 --- a/js/views/apis/documentation.js +++ b/js/views/apis/documentation.js @@ -19,9 +19,9 @@ define([ 'views/forms/resource', 'modal', 'views/apis/overview', - 'views/modals/newmethod', + 'models/method' 'views/modals/newresource', -], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, docsTemplate, ApiModel, MethodsCollection, ResourceListView, MethodDetailView, ResourceDetailView, ResourceModel, MethodModel, hljs, ResourceForm, Modal, OverView, NewMethod, NewResource){ +], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, docsTemplate, ApiModel, MethodsCollection, ResourceListView, MethodDetailView, ResourceDetailView, ResourceModel, MethodModel, hljs, ResourceForm, Modal, OverView, Method, NewResource){ var NewApiPage = Backbone.View.extend({ el: '.api-page-container', initialize: function () { @@ -46,12 +46,14 @@ define([ return false; }, newMethod: function () { - var methodForm = Vm.create(this, 'methodform', NewMethod, { - username: this.options.username, - version: this.options.version, - apiname: this.options.apiname + var that = this; + + this.modal = Modal.create({ + inline : { + from : $('.resource-list-container'), + cloneDOM : true + } }); - methodForm.render(); return false; }, diff --git a/templates/apis/docs.html b/templates/apis/docs.html index 3abce64..0af45c3 100644 --- a/templates/apis/docs.html +++ b/templates/apis/docs.html @@ -8,7 +8,7 @@ - diff --git a/templates/modals/inlineedit.html b/templates/modals/inlineedit.html index 3752950..915e227 100644 --- a/templates/modals/inlineedit.html +++ b/templates/modals/inlineedit.html @@ -13,7 +13,7 @@ diff --git a/templates/resource/list.html b/templates/resource/list.html index f3e4c82..c959a4d 100644 --- a/templates/resource/list.html +++ b/templates/resource/list.html @@ -8,17 +8,15 @@
    -
  • -
    -
    -
    -
    -
    - - Loading - -
    +
  • {{/resources.models}} From 2fa45bfe4b148835c58c0cd4c7ee61d8d9899dc4 Mon Sep 17 00:00:00 2001 From: pospi Date: Sun, 3 Mar 2013 17:44:05 +1000 Subject: [PATCH 508/531] created a nice UI for making new methods: split new method dialog up a bit to make resource selection easier to manage --- css/apimenu.css | 23 +++++++++++++++++ js/views/apis/documentation.js | 45 ++++++++++++++++++++++++++++++++- templates/modals/newmethod.html | 19 +++----------- 3 files changed, 71 insertions(+), 16 deletions(-) diff --git a/css/apimenu.css b/css/apimenu.css index 92baff8..7be9590 100644 --- a/css/apimenu.css +++ b/css/apimenu.css @@ -288,3 +288,26 @@ height: 16px; display: inline-block; overflow: hidden; } + + +/* +New Method popup dialog + */ +.method-content { + position: absolute; + background: #FFF; + left: 100%; + width: 550px; + padding: 50px; + border-top: 1px solid #EBEBEB; + border-right: 1px solid #EBEBEB; + border-bottom: 1px solid #EBEBEB; + margin-left: -50px; + + transition: top 0.3s; + -moz-transition: top 0.3s; + -o-transition: top 0.3s; + -webkit-transition: top 0.3s; +} + +.method-content.form label { display: inline; } diff --git a/js/views/apis/documentation.js b/js/views/apis/documentation.js index 8871f72..d02d708 100644 --- a/js/views/apis/documentation.js +++ b/js/views/apis/documentation.js @@ -21,7 +21,8 @@ define([ 'views/apis/overview', 'models/method', 'views/modals/newresource', -], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, docsTemplate, ApiModel, MethodsCollection, ResourceListView, MethodDetailView, ResourceDetailView, ResourceModel, MethodModel, hljs, ResourceForm, Modal, OverView, Method, NewResource){ + 'text!templates/modals/newmethod.html' +], function($, _, Backbone, Router, Vm, Mustache, Qtip, Session, docsTemplate, ApiModel, MethodsCollection, ResourceListView, MethodDetailView, ResourceDetailView, ResourceModel, MethodModel, hljs, ResourceForm, Modal, OverView, Method, NewResource, newMethodDialog){ var NewApiPage = Backbone.View.extend({ el: '.api-page-container', initialize: function () { @@ -50,11 +51,53 @@ define([ this.modal = Modal.create({ inline : { + title : "Choose Resource", + savetext : "Create method", from : $('.resource-list-container'), cloneDOM : true } }); + var modalEl = this.modal.el, + modalForm = $('form.inline-edit', modalEl), + modalResourceAs = $('a[data-resource-id]', modalEl), + resourceInput = $(''); + + // hide stuff from the resource list we don't want to see + $('.notification', modalEl).remove(); + $('.modal-form-errors', modalEl).remove(); + + // slide method rows up to hide them + $('.resource-list-container', modalEl).css('height', 'auto'); + $('.resource-submenu', modalEl).slideUp('fast'); + + // add a hidden input for the resource ID and rebind resource row click events to it + modalForm.append(resourceInput); + modalResourceAs.removeClass('active').on('click', function() { + // store value for form submission + resourceInput.val($(this).data('resource-id')); + + // indicate current selection + modalResourceAs.removeClass('active'); + $(this).addClass('active'); + + $('.modal-confirm', modalEl).show(); // OK to show submit button now + $('.modal-title', modalEl).html("New Method"); // and change the title hint + + // show and position the secondary dialog element we've injected below + var topOffset = $(this).closest('li').position().top - parseInt($('.method-content', modalEl).css('padding-top')); + $('.method-content', modalEl).css('top', topOffset).show(); + + return false; + }); + + // inject the secondary dialog element for entering the method details + // :TODO: errordef + modalForm.append(Mustache.render(newMethodDialog, {}, {errorDef : ''})); + + // hide confirm button until we've picked a resource + $('.modal-confirm', modalEl).hide(); + return false; }, saveMethod: function (ev) { diff --git a/templates/modals/newmethod.html b/templates/modals/newmethod.html index 6501fdd..ea67984 100644 --- a/templates/modals/newmethod.html +++ b/templates/modals/newmethod.html @@ -1,11 +1,7 @@ -
    - - -