├── .gitignore
├── EBookPriceForDouBan
├── .gitignore
├── background.html
├── img
│ ├── books128.gif
│ ├── books16.gif
│ ├── books38.jpg
│ └── books48.png
├── js
│ ├── binder.js
│ ├── dependencies
│ │ ├── jquery-1.8.2.js
│ │ └── knockout-latest.debug.js
│ ├── injecter.js
│ ├── launcher.js
│ ├── searchers.js
│ └── searchers
│ │ ├── amazonSearcher.js
│ │ ├── dangdangSearcher.js
│ │ ├── duokanSearcher.js
│ │ ├── jingdongSearcher.js
│ │ ├── koboSearcher.js
│ │ ├── nookSearcher.js
│ │ ├── tangchaSearcher.js
│ │ ├── taobaoSearcher.js
│ │ └── utils.js
└── manifest.json
├── FizzBuzz
├── FizzBuzz.js
├── FizzBuzzRunner.html
├── FizzBuzzSpec.js
└── FizzBuzzUITest.html
├── README.md
├── RemoveItemsLambda
├── RemoveItemsLambda.js
├── RemoveItemsLambdaRunner.html
└── RemoveItemsLambdaSpec.js
├── RunnerTemplate.html
├── TryAngular
├── Try1
│ └── Try1.html
└── Try2
│ ├── Try2.html
│ ├── todo.css
│ └── todo.js
├── TryKnockout
├── EMail.html
├── EMail.js
├── Premium
│ ├── Premium.html
│ └── Premium.js
├── SimpleViewModel.html
├── SimpleViewModel.js
├── TWBooks
│ ├── .idea
│ │ ├── .name
│ │ ├── TWBooks.iml
│ │ ├── encodings.xml
│ │ ├── libraries
│ │ │ └── sass_stdlib.xml
│ │ ├── misc.xml
│ │ ├── modules.xml
│ │ ├── scopes
│ │ │ └── scope_settings.xml
│ │ └── vcs.xml
│ ├── Books.html
│ ├── Books.js
│ ├── BooksData.js
│ ├── StringSimilarity.js
│ └── knockout-latest.debug.js
├── UsingList.html
├── UsingList.js
├── knockout-latest.debug.js
├── ko.tmproj
└── web-server.js
├── TryRequireJs
├── jquery-1.8.2.js
├── myPage.html
├── scripts
│ ├── main.js
│ ├── require.js
│ ├── subDir1
│ │ └── util1.js
│ └── subDir2
│ │ └── util2.js
└── stick_price_tmp.js
├── dropdowndemo
├── css
│ └── bootstrap.css
├── dropdowndemo.html
└── js
│ ├── bootstrap.js
│ └── jquery.js
└── lib
└── jasmine-1.2.0
├── MIT.LICENSE
├── jasmine-html.js
├── jasmine.css
└── jasmine.js
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | RemoveItemsLambda/.DS_Store
3 |
4 | TryAngular/Try1/.DS_Store
5 |
6 | .DS_Store
7 | TryAngular
8 |
9 | .idea/libraries/sass_stdlib.xml
10 |
11 | TryKnockout/TWBooks/.idea/workspace.xml
12 |
13 | .idea/scopes/scope_settings.xml
14 |
15 | .idea/workspace.xml
16 |
17 | TryKnockout/TWBooks/.idea/workspace.xml
18 |
19 | *.iml
20 |
21 | .idea/encodings.xml
22 |
23 | .idea/misc.xml
24 |
25 | .idea/modules.xml
26 |
27 | .idea/vcs.xml
28 |
29 | TryKnockout/TWBooks/.idea/workspace.xml
30 |
31 | TryKnockout/TWBooks/.idea/workspace.xml
32 |
33 | TryKnockout/TWBooks/.idea/workspace.xml
34 |
--------------------------------------------------------------------------------
/EBookPriceForDouBan/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
--------------------------------------------------------------------------------
/EBookPriceForDouBan/background.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/EBookPriceForDouBan/img/books128.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuipengfei/JavaScript-Practice-Code/265c736f9475029d92600d80035d9b6c11811713/EBookPriceForDouBan/img/books128.gif
--------------------------------------------------------------------------------
/EBookPriceForDouBan/img/books16.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuipengfei/JavaScript-Practice-Code/265c736f9475029d92600d80035d9b6c11811713/EBookPriceForDouBan/img/books16.gif
--------------------------------------------------------------------------------
/EBookPriceForDouBan/img/books38.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuipengfei/JavaScript-Practice-Code/265c736f9475029d92600d80035d9b6c11811713/EBookPriceForDouBan/img/books38.jpg
--------------------------------------------------------------------------------
/EBookPriceForDouBan/img/books48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuipengfei/JavaScript-Practice-Code/265c736f9475029d92600d80035d9b6c11811713/EBookPriceForDouBan/img/books48.png
--------------------------------------------------------------------------------
/EBookPriceForDouBan/js/binder.js:
--------------------------------------------------------------------------------
1 | function bindSearchResultsToTemplate(searchResults) {
2 | ko.observableArray(searchResults);
3 | ko.applyBindings({searchResults: searchResults});
4 | }
--------------------------------------------------------------------------------
/EBookPriceForDouBan/js/injecter.js:
--------------------------------------------------------------------------------
1 | function injectEmptyTemplate() {
2 | var htmlTemplate = '' +
3 | '
' +
21 | '
' +
22 | '
' +
23 | '
支付宝扫码,打赏作者' +
24 | '

' +
25 | '
' +
26 | '
' +
27 | '
';
28 |
29 | $(".gray_ad").first().append($(htmlTemplate));
30 | }
--------------------------------------------------------------------------------
/EBookPriceForDouBan/js/launcher.js:
--------------------------------------------------------------------------------
1 | injectEmptyTemplate();
2 | var searchResults = searchForEBooks();
3 | bindSearchResultsToTemplate(searchResults);
--------------------------------------------------------------------------------
/EBookPriceForDouBan/js/searchers.js:
--------------------------------------------------------------------------------
1 | function SearchResult(provider, price, url, currencyType) {
2 | this.provider = provider;
3 | this.price = price;
4 | this.url = url;
5 | this.description = provider + ":" + price + (currencyType ? currencyType : "元");
6 | this.isPriceInNumber = !isNaN(price);
7 | }
8 | //todo: remove useless idx function params; fix nook problem when it has both paperbook and ebook.
9 | var searchers = [
10 | duokanSearcher,
11 | tangchaSearcher,
12 | amazonSearcher,
13 | //taobaoSearcher,//fuck taobao gbk
14 | jingdongSearcher,
15 | dangdangSearcher,
16 | nookSearcher,
17 | koboSearcher
18 | ];
19 |
20 | function doubanBookId() {
21 | var urlFragments = location.pathname.split("/");
22 | return urlFragments[urlFragments.length - 2];
23 | }
24 |
25 | function searchForEBooks() {
26 | var searchResults = ko.observableArray();
27 |
28 | $.ajax({
29 | url: "https://api.douban.com/v2/book/" + doubanBookId(), success: function (data) {
30 | var jsonResult = data;
31 |
32 | var bookTitle = jsonResult.title;
33 | var author = jsonResult.author[0];
34 | var isbn = jsonResult.isbn13;
35 |
36 | $.each(searchers, function (index, searcher) {
37 | //we give all parameters to every searcher, it's up to the searcher to decide whether to use them or ignore them.
38 | searcher.search({title: bookTitle, author: author, isbn: isbn, searchResults: searchResults});
39 | });
40 | }
41 | });
42 |
43 | return searchResults;
44 | }
45 |
--------------------------------------------------------------------------------
/EBookPriceForDouBan/js/searchers/amazonSearcher.js:
--------------------------------------------------------------------------------
1 | var amazonSearcher = {
2 | search: function (searchParameter) {
3 | var isbn = searchParameter.isbn;
4 | var searchResults = searchParameter.searchResults;
5 |
6 | var twoSites = [
7 | {
8 | searchUrl: "http://www.amazon.cn/s/ref=nb_sb_noss?url=node%3D116169071&field-keywords=" + isbn,
9 | name: "亚马逊(中国站)Kindle",
10 | currency: "元"
11 | },
12 | {
13 | searchUrl: "http://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Ddigital-text&field-keywords=" + isbn,
14 | name: "亚马逊(美国站)Kindle",
15 | currency: "美元"
16 | }
17 | ];
18 |
19 | $.each(twoSites, function (inx, site) {
20 | $.ajax({
21 | url: site.searchUrl, async: true, success: function (data) {
22 | var page = $(data);
23 | var resultsDiv = page.find("#resultsCol");
24 | var noResultsTip = page.find("#noResultsTitle");
25 | if (resultsDiv.length > 0 && noResultsTip.length == 0) {
26 | var price = resultsDiv.find(".a-color-price").first().text().replace("¥", "").replace("$", "");
27 | var url = resultsDiv.find(".s-access-detail-page").attr("href");
28 | searchResults.push(new SearchResult(site.name, price, url, site.currency));
29 | }
30 | }
31 | });
32 | });
33 | }
34 | };
--------------------------------------------------------------------------------
/EBookPriceForDouBan/js/searchers/dangdangSearcher.js:
--------------------------------------------------------------------------------
1 | var dangdangSearcher = {
2 | search: function (searchParameter) {
3 | var isbn = searchParameter.isbn;
4 | var searchResults = searchParameter.searchResults;
5 |
6 | var url = "http://search.dangdang.com/?key=" + isbn + "&category_path=98.00.00.00.00.00&type=98.00.00.00.00.00";
7 |
8 | $.ajax({
9 | url: url, async: true, success: function (data) {
10 | var page = $(data);
11 | if (isFound(page)) {
12 | var book = parseBookFrom(page);
13 | searchResults.push(new SearchResult("当当电子书", book.price, book.url));
14 | }
15 | }
16 | });
17 |
18 | function parseBookFrom(page) {
19 | var bookLi = $(page.find(".bigimg").find("li").first());
20 | var url = bookLi.find("a").attr("href");
21 | var price = bookLi.find(".search_now_price").text().replace("¥", "");
22 | return {url: url, price: price};
23 | }
24 |
25 | function isFound(page) {
26 | var notFound = page.find(".no_result_tips");
27 | return notFound.length === 0;
28 | }
29 | }
30 | };
--------------------------------------------------------------------------------
/EBookPriceForDouBan/js/searchers/duokanSearcher.js:
--------------------------------------------------------------------------------
1 | var duokanSearcher = {
2 | search: function (searchParameter) {
3 | var title = searchParameter.title;
4 | var searchResults = searchParameter.searchResults;
5 |
6 | var duokanSearchUrl = "http://book.duokan.com/store/v0/web/search?s=" + title;
7 | var duokanBookUrlTemplate = "http://www.duokan.com/book/";
8 |
9 | $.ajax({
10 | url: duokanSearchUrl, async: true, success: function (response) {
11 | var matchedBook = response.items.filter(function (item) {
12 | return item.title.indexOf(title) != -1 || title.indexOf(item.title) != -1;
13 | })[0];
14 | if (matchedBook) {
15 | var url = duokanBookUrlTemplate + matchedBook.sid;
16 | var price = matchedBook.new_price != undefined ? matchedBook.new_price : matchedBook.price;
17 | searchResults.push(new SearchResult("多看阅读", price, url));
18 | }
19 | }
20 | });
21 | }
22 | };
23 |
--------------------------------------------------------------------------------
/EBookPriceForDouBan/js/searchers/jingdongSearcher.js:
--------------------------------------------------------------------------------
1 | var jingdongSearcher = {
2 | search: function (searchParameter) {
3 | var isbn = searchParameter.isbn;
4 | var searchResults = searchParameter.searchResults;
5 |
6 | var jingdongSearchUrl = "http://search.e.jd.com/searchDigitalBookAjax?ajaxSearch=1&key=" + isbn;
7 |
8 | $.ajax({
9 | url: jingdongSearchUrl, async: true, dataType: "json", success: function (jsonResult) {
10 | if (jsonResult) {
11 | var wareID = jsonResult.Paragraph[0].wareid;
12 |
13 | var url = "http://e.jd.com/" + wareID + ".html";
14 | var price = jsonResult.Paragraph[0].hprice / 100;
15 |
16 | var jingdongSearchResult = new SearchResult("京东电子书", price, url);
17 | searchResults.push(jingdongSearchResult);
18 | }
19 | }
20 | });
21 | }
22 | };
--------------------------------------------------------------------------------
/EBookPriceForDouBan/js/searchers/koboSearcher.js:
--------------------------------------------------------------------------------
1 | var koboSearcher = {
2 | search: function (searchParameter) {
3 | var searchResults = searchParameter.searchResults;
4 |
5 | function searchWithMatchingISBN(matchingISBN) {
6 | var koboSearchUrl = "http://www.kobobooks.com/search/search.html?q=" + matchingISBN;
7 |
8 | $.ajax({
9 | url: koboSearchUrl, async: true, success: function (data) {
10 | var page = $(data);
11 | var notFoundMsg = page.find("ctl00_ctl00_ctl00_Body_Body_ContentBody_liNoResults");
12 | var priceTag = page.find(".KV2OurPrice");
13 |
14 | if (notFoundMsg.length === 0 && priceTag.length > 0) {
15 | var price = priceTag.find("strong").text().replace("$", "");
16 | var url = koboSearchUrl;
17 |
18 | var koboSearchResult = new SearchResult("Kobo电子书", price, url, "美元");
19 | searchResults.push(koboSearchResult);
20 | }
21 | }
22 | });
23 | }
24 |
25 | //kobo only sells ebook, and different from amazon and nook, searching with the paper book's ISBN does not work with kobo
26 | //so we have to find the paper book's counterpart from google and then seatch kobo
27 | getMatchingISBNsFromGoogle(searchParameter.title, searchParameter.author, searchWithMatchingISBN);
28 | }
29 | };
--------------------------------------------------------------------------------
/EBookPriceForDouBan/js/searchers/nookSearcher.js:
--------------------------------------------------------------------------------
1 | var nookSearcher = {
2 | search: function (searchParameter) {
3 | var isbn = searchParameter.isbn;
4 | var searchResults = searchParameter.searchResults;
5 |
6 | function searchWithISBN(isbn) {
7 | var nookSearchUrl = "http://www.barnesandnoble.com/s?keyword=" + isbn + "&store=ebook";
8 | $.ajax({
9 | url: nookSearchUrl, async: true, success: function (data) {
10 | var page = $(data);
11 | var notFoundMsg = page.find("#search-noresults-message-1");
12 | var nookDiv = page.find("#nook-price-1");
13 | if (notFoundMsg.length === 0 && nookDiv.length > 0) {
14 | var priceTag = nookDiv.find(".price");
15 | var price = priceTag.text().replace("$", "");
16 | var url = nookSearchUrl;
17 | var nookSearchResult = new SearchResult("Nook电子书", price, url, "美元");
18 | searchResults.push(nookSearchResult);
19 | }
20 | //sometimes nook barnes and noble has both ebook and paper book, searching with the paper books isbn
21 | //directly return the paperbook
22 | //so we need to find the paper book's ebook counterpart from google and search again.
23 | else {
24 | getMatchingISBNsFromGoogle(searchParameter.title, searchParameter.author, function (matchingISBN) {
25 | searchWithISBN(matchingISBN);
26 | });
27 | }
28 | }
29 | });
30 | }
31 |
32 | searchWithISBN(isbn);
33 | }
34 | };
--------------------------------------------------------------------------------
/EBookPriceForDouBan/js/searchers/tangchaSearcher.js:
--------------------------------------------------------------------------------
1 | var tangchaSearcher = {
2 | search: function (searchParameter) {
3 | var title = searchParameter.title;
4 | var searchResults = searchParameter.searchResults;
5 | var tangchaSearchUrl = "http://tangcha.tc/books/search/" + title + ".jsd";
6 | var tangchaBookUrlTemplate = "http://tangcha.tc/";
7 |
8 | $.ajax({
9 | url: tangchaSearchUrl, async: true, success: function (data) {
10 | eval(data);
11 | var div = $(html);
12 | var firstMatch = div.find("a").filter(function (index, a) {
13 | return $(a).attr("href").indexOf("books") != -1 && $(a).attr("href").indexOf("search") == -1;
14 | }).first();
15 | if (firstMatch.length > 0) {
16 | var bookUrl = tangchaBookUrlTemplate + firstMatch.attr("href");
17 | $.ajax({
18 | url: bookUrl, async: false, success: function (bookData) {
19 | var section = $(bookData);
20 | var price = section.find(".book-purchase").text();
21 |
22 | var tangchaSearchResult = new SearchResult("唐茶", price.replace("¥", ""), bookUrl.replace(".jsd", ""));
23 | searchResults.push(tangchaSearchResult);
24 | }
25 | });
26 | }
27 | }
28 | });
29 | }
30 | };
--------------------------------------------------------------------------------
/EBookPriceForDouBan/js/searchers/taobaoSearcher.js:
--------------------------------------------------------------------------------
1 | var taobaoSearcher = {
2 | search: function (searchParameter) {
3 | var title = searchParameter.title;
4 | var searchResults = searchParameter.searchResults;
5 |
6 | var taobaoSearchUrl = "http://shuzi.taobao.com/item/search.htm?q=" + encodeURIComponent(title) + "&isbook=ebook";
7 |
8 | $.ajax({
9 | url: taobaoSearchUrl, async: true, success: function (data) {
10 | var page = $(data);
11 | var resultList = page.find(".resultlist_pic.clr");
12 | var errorDiv = page.find(".msgBox.w758b1.mt10");
13 | if (errorDiv.length == 0) {
14 | var url = resultList.find("a").attr("href");
15 | var price = resultList.find(".hotbox_price").find("span").text()
16 |
17 | var taobaoSearchResult = new SearchResult("淘宝电子书", price, url);
18 | searchResults.push(taobaoSearchResult);
19 | }
20 | }
21 | });
22 | }
23 | };
--------------------------------------------------------------------------------
/EBookPriceForDouBan/js/searchers/utils.js:
--------------------------------------------------------------------------------
1 | function getMatchingISBNsFromGoogle(title, author, callBack) {
2 |
3 | var googleBookSearchUrl = "https://www.googleapis.com/books/v1/volumes?q=" + title + "+inauthor:" + author;
4 | $.ajax({
5 | url: googleBookSearchUrl, async: true, success: function (googleResultJson) {
6 | var matchingISBNs = googleResultJson.items.filter(function (item) {
7 | return item.volumeInfo.title === title;
8 | }).map(function (item) {
9 | return item.volumeInfo.industryIdentifiers[1].identifier;
10 | });
11 | if (matchingISBNs.length > 0) {
12 | $.each(matchingISBNs, function (idx, matchingISBN) {
13 | callBack(matchingISBN);
14 | });
15 | }
16 | }
17 | });
18 | }
--------------------------------------------------------------------------------
/EBookPriceForDouBan/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 2,
3 | "name": "豆瓣电子书比价",
4 | "description": "本插件帮您在浏览豆瓣上的书目时找到该书的电子版(正版,需付费)。现支持多看,亚马逊,京东,亚马逊,当当。",
5 | "version": "1.13",
6 | "background": {
7 | "persistent": false,
8 | "page": "background.html"
9 | },
10 | "icons": {
11 | "16": "img/books16.gif",
12 | "48": "img/books48.png",
13 | "128": "img/books128.gif"
14 | },
15 | "content_scripts": [
16 | {
17 | "matches": ["http://book.douban.com/subject/*"],
18 | "js": [
19 | "js/dependencies/jQuery-1.8.2.js",
20 | "js/dependencies/knockout-latest.debug.js",
21 | "js/injecter.js",
22 | "js/searchers/utils.js",
23 | "js/searchers/duokanSearcher.js",
24 | "js/searchers/tangchaSearcher.js",
25 | "js/searchers/amazonSearcher.js",
26 | "js/searchers/taobaoSearcher.js",
27 | "js/searchers/jingdongSearcher.js",
28 | "js/searchers/dangdangSearcher.js",
29 | "js/searchers/nookSearcher.js",
30 | "js/searchers/koboSearcher.js",
31 | "js/searchers.js",
32 | "js/binder.js",
33 | "js/launcher.js"
34 | ]
35 | }
36 | ],
37 | "permissions": [
38 | "http://book.duokan.com/",
39 | "http://tangcha.tc/",
40 | "http://www.amazon.cn/",
41 | "http://www.amazon.com/",
42 | "http://shuzi.taobao.com/",
43 | "http://search.e.jd.com/",
44 | "http://search.dangdang.com/",
45 | "http://www.barnesandnoble.com/",
46 | "http://search.barnesandnoble.com/",
47 | "http://www.kobobooks.com/",
48 | "https://www.googleapis.com/",
49 | "https://api.douban.com/"
50 | ],
51 | "page_action": {
52 | "default_icon": {
53 | "38": "img/books38.jpg"
54 | },
55 | "default_title": "EBook Price"
56 | }
57 | }
--------------------------------------------------------------------------------
/FizzBuzz/FizzBuzz.js:
--------------------------------------------------------------------------------
1 | function fizzBuzz (number)
2 | {
3 | var fizz = number % 3 == 0;
4 | var buzz = number % 5 == 0;
5 |
6 | if(fizz && buzz){return "fizz buzz";}
7 | if(fizz){return "fizz";}
8 | if(buzz){return "buzz";}
9 |
10 | return number;
11 | }
--------------------------------------------------------------------------------
/FizzBuzz/FizzBuzzRunner.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 | Jasmine Spec Runner for FizzBuzz
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/FizzBuzz/FizzBuzzSpec.js:
--------------------------------------------------------------------------------
1 | describe("Fizz Buzz",function(){
2 | it("should say fizz when passing in 3",function(){
3 | var result = fizzBuzz(3);
4 | expect(result).toEqual("fizz");
5 | });
6 |
7 | it("should say buzz when passing in 5",function(){
8 | var result = fizzBuzz(5);
9 | expect(result).toEqual("buzz");
10 | });
11 |
12 | it("should say fizz buzz when passing in 15",function(){
13 | var result = fizzBuzz(15);
14 | expect(result).toEqual("fizz buzz");
15 | });
16 |
17 | it("should say 17 when passing in 17",function(){
18 | var result = fizzBuzz(17);
19 | expect(result).toEqual(17);
20 | });
21 |
22 | it("should say the number itself when passing in a number that's can not be divided by neither 2 nor 5",function(){
23 | var numbers = [1, 2, 4, 7, 8, 11, 13, 14, 16, 17, 19];
24 | for (var i=0; i < numbers.length; i++) {
25 | var number = numbers[i];
26 | var result = fizzBuzz(number);
27 | expect(result).toEqual(number);
28 | };
29 | });
30 | });
--------------------------------------------------------------------------------
/FizzBuzz/FizzBuzzUITest.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | fizz buzz
4 |
5 |
6 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | JavaScript-Practice-Code
2 | ========================
3 |
4 | JS code
5 | push test
--------------------------------------------------------------------------------
/RemoveItemsLambda/RemoveItemsLambda.js:
--------------------------------------------------------------------------------
1 | function removeItemsFromArrayBase(rule) {
2 | return function(array) {
3 | return array.filter(function(i) {
4 | return rule(i);
5 | });
6 | };
7 | }
8 |
9 | var removeNumbersBiggerThan5 = removeItemsFromArrayBase(function(i) {
10 | return i < 5;
11 | });
12 |
13 | var removeOddNumbers = removeItemsFromArrayBase(function(i) {
14 | return i % 2 == 0;
15 | });
16 |
17 | var removeApples = removeItemsFromArrayBase(function(i) {
18 | return i != "apple";
19 | });
20 |
--------------------------------------------------------------------------------
/RemoveItemsLambda/RemoveItemsLambdaRunner.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 | Jasmine Spec Runner for FizzBuzz
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/RemoveItemsLambda/RemoveItemsLambdaSpec.js:
--------------------------------------------------------------------------------
1 | describe("remove numbers bigger than 5", function() {
2 | it("should remove 6789 from 123456789", function() {
3 | var result = removeNumbersBiggerThan5([1, 2, 3, 4, 5, 6, 7, 8, 9]);
4 |
5 | expect(result).toContain(1);
6 | expect(result).toContain(2);
7 | expect(result).toContain(3);
8 | expect(result).toContain(4);
9 |
10 | expect(result).not.toContain(5);
11 | expect(result).not.toContain(6);
12 | expect(result).not.toContain(7);
13 | expect(result).not.toContain(8);
14 | expect(result).not.toContain(9);
15 | });
16 | });
17 |
18 | describe("remove odd numbers", function() {
19 | it("should remove 135 from 123456", function() {
20 | var result = removeOddNumbers([1, 2, 3, 4, 5, 6]);
21 |
22 | expect(result).toContain(2);
23 | expect(result).toContain(4);
24 | expect(result).toContain(6);
25 |
26 | expect(result).not.toContain(1);
27 | expect(result).not.toContain(3);
28 | expect(result).not.toContain(5);
29 | });
30 | });
31 |
32 | describe("remove apples", function() {
33 | it("should remove apples 1apple2apple3", function() {
34 | var result = removeApples(["1", "apple", "2", "apple", "3"]);
35 |
36 | expect(result).toContain("1");
37 | expect(result).toContain("2");
38 | expect(result).toContain("3");
39 |
40 | expect(result).not.toContain("apple");
41 | });
42 | });
43 |
44 | describe("removeItemsFromArrayBase", function() {
45 | it("should return a function", function() {
46 | var result = removeItemsFromArrayBase(function(i){return true;});
47 |
48 | expect(typeof result).toEqual("function");
49 | });
50 | });
--------------------------------------------------------------------------------
/RunnerTemplate.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 | Jasmine Spec Runner for FizzBuzz
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/TryAngular/Try1/Try1.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Hello {{yourName}}!
12 |
13 |
14 |
--------------------------------------------------------------------------------
/TryAngular/Try2/Try2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | My todo list
10 |
11 |
{{remaining()}} of {{todos.length}} remaining
12 | [
archive ]
13 |
19 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/TryAngular/Try2/todo.css:
--------------------------------------------------------------------------------
1 | .done-true {
2 | text-decoration: line-through;
3 | color: grey;
4 | }
--------------------------------------------------------------------------------
/TryAngular/Try2/todo.js:
--------------------------------------------------------------------------------
1 | function TodoController($scope) {
2 | $scope.todos = [{
3 | text: 'item1',
4 | done: true
5 | }, {
6 | text: 'item2',
7 | done: false
8 | }];
9 |
10 | $scope.addTodo = function() {
11 | $scope.todos.push({
12 | text: $scope.todoText,
13 | done: false
14 | });
15 | $scope.todoText = '';
16 | };
17 |
18 | $scope.remaining = function() {
19 | return getRemainingToDoItems().length;
20 | };
21 |
22 | $scope.archive = function() {
23 | $scope.todos = getRemainingToDoItems();
24 | };
25 |
26 | function getRemainingToDoItems() {
27 | return $scope.todos.filter(function(item) {
28 | return !item.done
29 | });
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/TryKnockout/EMail.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | using list
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
16 |
17 |
18 |
19 |
20 |
21 | From |
22 | To |
23 | Subject |
24 | Date |
25 |
26 |
27 |
28 |
29 | |
30 | |
31 | |
32 | |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
:
42 |
:
43 |
:
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/TryKnockout/EMail.js:
--------------------------------------------------------------------------------
1 | function WebmailViewModel() {
2 | // Data
3 | var self = this;
4 | self.folders = ['Inbox', 'Archive', 'Sent', 'Spam'];
5 |
6 | self.chosenFolderId = ko.observable();
7 |
8 | // Behaviours
9 | self.goToFolder = function(folder) {
10 | self.chosenFolderId(folder);
11 | //self.chosenMailData(null); // Stop showing a mail
12 | $.get('http://learn.knockoutjs.com/mail', {
13 | folder: folder
14 | }, self.chosenFolderData);
15 |
16 | };
17 |
18 | self.goToMail = function(mail) {
19 | self.chosenFolderId(mail.folder);
20 | self.chosenFolderData(null); // hide folder
21 | $.get("http://learn.knockoutjs.com/mail", {
22 | mailId: mail.id
23 | }, self.chosenMailData);
24 | };
25 |
26 | self.chosenFolderData = ko.observable();
27 | self.chosenMailData = ko.observable();
28 | // Show inbox by default
29 | self.goToFolder('Inbox');
30 | };
31 |
32 | function onload() {
33 | ko.applyBindings(new WebmailViewModel());
34 | }
35 |
--------------------------------------------------------------------------------
/TryKnockout/Premium/Premium.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | QSP
4 |
5 |
6 |
7 |
8 | Your Premium is:
9 | dollars.
10 |
11 |
12 | Discount:
13 |
15 |
17 |
18 |
19 | Campaign:
20 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/TryKnockout/Premium/Premium.js:
--------------------------------------------------------------------------------
1 | function PremiumViewModel() {
2 | var self = this;
3 | var initPremium = 500;
4 |
5 | self.premium = ko.observable(initPremium);
6 | self.discount = ko.observable(0);
7 |
8 | self.campaignCodes = [{
9 | campaignID: "default",
10 | campaignText: "please select a campaign code"
11 | }, {
12 | campaignID: "campID01",
13 | campaignText: "25% off"
14 | }, {
15 | campaignID: "campID02",
16 | campaignText: "$50 off"
17 | }];
18 |
19 | self.selectedCampaignCode = ko.observable(self.campaignCodes[0]);
20 |
21 | self.applyDiscount = function() {
22 | self.premium(initPremium - self.discount());
23 | }
24 |
25 | self.noCampaignApplied = ko.computed(function() {
26 | return self.selectedCampaignCode().campaignID == "default";
27 | });
28 |
29 | self.noDiscountApplied = ko.computed(function() {
30 | return self.discount() == 0;
31 | });
32 | }
33 |
34 | function onload() {
35 | ko.applyBindings(new PremiumViewModel());
36 | }
37 |
--------------------------------------------------------------------------------
/TryKnockout/SimpleViewModel.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | try knockout
4 |
5 |
6 |
7 |
8 | First name:
9 | Last name:
10 |
11 | First name:
12 | Last name:
13 |
14 | Full name:
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/TryKnockout/SimpleViewModel.js:
--------------------------------------------------------------------------------
1 | function AppViewModel() {
2 | this.firstName = ko.observable("Bert");
3 | this.lastName = ko.observable("Bertington");
4 |
5 | this.fullName = ko.computed(function() {
6 | return this.firstName() + " " + this.lastName();
7 | }, this);
8 |
9 | this.capitalizeLastName = function() {
10 | var currentVal = this.lastName(); // Read the current value
11 | this.lastName(currentVal.toUpperCase()); // Write back a modified value
12 | };
13 | }
14 |
15 | function clickEventHandler() {
16 | var model = new AppViewModel();
17 | // Activates knockout.js
18 | ko.applyBindings(model);
19 | }
20 |
--------------------------------------------------------------------------------
/TryKnockout/TWBooks/.idea/.name:
--------------------------------------------------------------------------------
1 | TWBooks
--------------------------------------------------------------------------------
/TryKnockout/TWBooks/.idea/TWBooks.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/TryKnockout/TWBooks/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/TryKnockout/TWBooks/.idea/libraries/sass_stdlib.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/TryKnockout/TWBooks/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $APPLICATION_HOME_DIR$/lib/webide.jar!/resources/html5-schema/html5.rnc
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/TryKnockout/TWBooks/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/TryKnockout/TWBooks/.idea/scopes/scope_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/TryKnockout/TWBooks/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/TryKnockout/TWBooks/Books.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | TW Books
5 |
6 |
7 |
8 |
9 |
24 |
25 |
26 | Which books are the most popular?
27 |
28 |
29 |
30 | Book name |
31 | How many people bought this book? |
32 | Who bought this book? |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
42 | |
43 | |
44 |
45 |
48 | |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/TryKnockout/TWBooks/Books.js:
--------------------------------------------------------------------------------
1 | var group = function (arr, by, initGroups) {
2 | function tryGetPerfectMatch() {
3 | var groupItem = initGroups.filter(function (grp) {
4 | return grp.groupNames.filter(function (grpN) {
5 | return grpN.groupName === key;
6 | }).length != 0;
7 | })[0];
8 | return groupItem;
9 | }
10 |
11 | function tryGetFuzzyMatch() {
12 | groupItem = initGroups.filter(function (grp) {
13 | return levenshteinenator(grp.groupNames[0].groupName, key) === 1;
14 | })[0];
15 | }
16 |
17 | function createNewGroup() {
18 | groupItem = {groupNames:[], groupItems:[]};
19 | initGroups.push(groupItem);
20 | }
21 |
22 | for (var i = 0; i < arr.length; i++) {
23 | var item = arr[i];
24 | var key = by(item);
25 |
26 | var perfectMatch = true;
27 | var groupItem = tryGetPerfectMatch();
28 |
29 | if (!groupItem) {
30 | perfectMatch = false;
31 | tryGetFuzzyMatch();
32 | }
33 |
34 | if (!groupItem) {
35 | createNewGroup();
36 | }
37 |
38 | if (!perfectMatch) {
39 | groupItem.groupNames.push({groupName:key});
40 | }
41 |
42 | groupItem.groupItems.push(item);
43 | }
44 |
45 | return initGroups;
46 | }
47 |
48 | function onload() {
49 | //prepare data
50 | (function () {
51 | booksDataArray.forEach(function (item) {
52 | item.BookName = item.BookName.replace(" ", "");
53 | });
54 | booksDataArray = booksDataArray.filter(function (item) {
55 | return item.BookName.length > 1;
56 | });
57 | }());
58 |
59 | var groups = [];
60 | group(booksDataArray, function (item) {
61 | return item.BookName;
62 | }, groups);
63 |
64 | groups.sort(function (grp1, grp2) {
65 | return grp2.groupItems.length - grp1.groupItems.length;
66 | })
67 |
68 | ko.observableArray(groups);
69 | ko.applyBindings({groups:groups});
70 | }
--------------------------------------------------------------------------------
/TryKnockout/TWBooks/StringSimilarity.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (c) 2006. All Rights reserved.
4 |
5 | If you use this script, please email me and let me know, thanks!
6 |
7 | Andrew Hedges
8 | andrew (at) hedges (dot) name
9 |
10 | If you want to hire me to write JavaScript for you, see my resume.
11 |
12 | http://andrew.hedges.name/resume/
13 |
14 | */
15 |
16 | // calculate the Levenshtein distance between a and b, fob = form object, passed to the function
17 | levenshteinenator = function (a, b) {
18 | var cost;
19 |
20 | // get values
21 |
22 | var m = a.length;
23 |
24 | var n = b.length;
25 |
26 | // make sure a.length >= b.length to use O(min(n,m)) space, whatever that is
27 | if (m < n) {
28 | var c = a;
29 | a = b;
30 | b = c;
31 | var o = m;
32 | m = n;
33 | n = o;
34 | }
35 |
36 | var r = new Array();
37 | r[0] = new Array();
38 | for (var c = 0; c < n + 1; c++) {
39 | r[0][c] = c;
40 | }
41 |
42 | for (var i = 1; i < m + 1; i++) {
43 | r[i] = new Array();
44 | r[i][0] = i;
45 | for (var j = 1; j < n + 1; j++) {
46 | cost = (a.charAt(i - 1) == b.charAt(j - 1)) ? 0 : 1;
47 | r[i][j] = minimator(r[i - 1][j] + 1, r[i][j - 1] + 1, r[i - 1][j - 1] + cost);
48 | }
49 | }
50 |
51 | return r[m][n];
52 | }
53 |
54 | // return the smallest of the three values passed in
55 | minimator = function (x, y, z) {
56 | if (x < y && x < z) return x;
57 | if (y < x && y < z) return y;
58 | return z;
59 | }
--------------------------------------------------------------------------------
/TryKnockout/UsingList.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | using list
4 |
5 |
6 |
7 |
8 | Your seat reservations ()
9 |
10 |
28 |
29 |
30 |
31 |
32 | Total surcharge: $
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/TryKnockout/UsingList.js:
--------------------------------------------------------------------------------
1 | // Class to represent a row in the seat reservations grid
2 |
3 |
4 | function SeatReservation(name, initialMeal) {
5 | var self = this;
6 |
7 | self.name = name;
8 |
9 | self.meal = ko.observable(initialMeal);
10 |
11 | self.formattedPrice = ko.computed(function() {
12 | var price = self.meal().price;
13 | return price ? "$" + price.toFixed(2) : "None";
14 | });
15 | }
16 |
17 | // Overall viewmodel for this screen, along with initial state
18 |
19 |
20 | function ReservationsViewModel() {
21 | var self = this;
22 |
23 | // Non-editable catalog data - would come from the server
24 | self.availableMeals = [{
25 | mealName: "Standard (sandwich)",
26 | price: 0
27 | }, {
28 | mealName: "Premium (lobster)",
29 | price: 34.95
30 | }, {
31 | mealName: "Ultimate (whole zebra)",
32 | price: 290
33 | }];
34 |
35 | // Editable data
36 | self.seats = ko.observableArray([
37 | new SeatReservation("Steve", self.availableMeals[0]), new SeatReservation("Bert", self.availableMeals[0])]);
38 |
39 | // Operations
40 | self.addSeat = function() {
41 | self.seats.push(new SeatReservation("new guy", self.availableMeals[1]));
42 | };
43 |
44 | self.removeSeat = function(seat) {
45 | self.seats.remove(seat)
46 | };
47 |
48 | self.totalSurcharge = ko.computed(function() {
49 | var total = 0;
50 | for (var i = 0; i < self.seats().length; i++)
51 | total += self.seats()[i].meal().price;
52 | return total;
53 | });
54 |
55 | }
56 |
57 | function onload() {
58 | ko.applyBindings(new ReservationsViewModel());
59 | }
60 |
--------------------------------------------------------------------------------
/TryKnockout/ko.tmproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | currentDocument
6 | EMail.html
7 | documents
8 |
9 |
10 | expanded
11 |
12 | name
13 | TryKnockout
14 | regexFolderFilter
15 | !.*/(\.[^/]*|CVS|_darcs|_MTN|\{arch\}|blib|.*~\.nib|.*\.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle))$
16 | sourceDirectory
17 |
18 |
19 |
20 | fileHierarchyDrawerWidth
21 | 214
22 | metaData
23 |
24 | EMail.html
25 |
26 | caret
27 |
28 | column
29 | 74
30 | line
31 | 4
32 |
33 | firstVisibleColumn
34 | 0
35 | firstVisibleLine
36 | 1
37 |
38 | EMail.js
39 |
40 | caret
41 |
42 | column
43 | 21
44 | line
45 | 13
46 |
47 | columnSelection
48 |
49 | firstVisibleColumn
50 | 0
51 | firstVisibleLine
52 | 0
53 | selectFrom
54 |
55 | column
56 | 10
57 | line
58 | 13
59 |
60 | selectTo
61 |
62 | column
63 | 26
64 | line
65 | 13
66 |
67 |
68 |
69 | openDocuments
70 |
71 | EMail.html
72 | EMail.js
73 |
74 | showFileHierarchyDrawer
75 |
76 | windowFrame
77 | {{217, 4}, {1216, 874}}
78 |
79 |
80 |
--------------------------------------------------------------------------------
/TryKnockout/web-server.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var sys = require('sys'),
4 | http = require('http'),
5 | fs = require('fs'),
6 | url = require('url'),
7 | events = require('events');
8 |
9 | var DEFAULT_PORT = 8000;
10 |
11 | function main(argv) {
12 | new HttpServer({
13 | 'GET': createServlet(StaticServlet),
14 | 'HEAD': createServlet(StaticServlet)
15 | }).start(Number(argv[2]) || DEFAULT_PORT);
16 | }
17 |
18 | function escapeHtml(value) {
19 | return value.toString().
20 | replace('<', '<').
21 | replace('>', '>').
22 | replace('"', '"');
23 | }
24 |
25 | function createServlet(Class) {
26 | var servlet = new Class();
27 | return servlet.handleRequest.bind(servlet);
28 | }
29 |
30 | /**
31 | * An Http server implementation that uses a map of methods to decide
32 | * action routing.
33 | *
34 | * @param {Object} Map of method => Handler function
35 | */
36 | function HttpServer(handlers) {
37 | this.handlers = handlers;
38 | this.server = http.createServer(this.handleRequest_.bind(this));
39 | }
40 |
41 | HttpServer.prototype.start = function(port) {
42 | this.port = port;
43 | this.server.listen(port);
44 | sys.puts('Http Server running at http://localhost:' + port + '/');
45 | };
46 |
47 | HttpServer.prototype.parseUrl_ = function(urlString) {
48 | var parsed = url.parse(urlString);
49 | parsed.pathname = url.resolve('/', parsed.pathname);
50 | return url.parse(url.format(parsed), true);
51 | };
52 |
53 | HttpServer.prototype.handleRequest_ = function(req, res) {
54 | var logEntry = req.method + ' ' + req.url;
55 | if (req.headers['user-agent']) {
56 | logEntry += ' ' + req.headers['user-agent'];
57 | }
58 | sys.puts(logEntry);
59 | req.url = this.parseUrl_(req.url);
60 | var handler = this.handlers[req.method];
61 | if (!handler) {
62 | res.writeHead(501);
63 | res.end();
64 | } else {
65 | handler.call(this, req, res);
66 | }
67 | };
68 |
69 | /**
70 | * Handles static content.
71 | */
72 | function StaticServlet() {}
73 |
74 | StaticServlet.MimeMap = {
75 | 'txt': 'text/plain',
76 | 'html': 'text/html',
77 | 'css': 'text/css',
78 | 'xml': 'application/xml',
79 | 'json': 'application/json',
80 | 'js': 'application/javascript',
81 | 'jpg': 'image/jpeg',
82 | 'jpeg': 'image/jpeg',
83 | 'gif': 'image/gif',
84 | 'png': 'image/png'
85 | };
86 |
87 | StaticServlet.prototype.handleRequest = function(req, res) {
88 | var self = this;
89 | var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/, function(match, hex){
90 | return String.fromCharCode(parseInt(hex, 16));
91 | });
92 | var parts = path.split('/');
93 | if (parts[parts.length-1].charAt(0) === '.')
94 | return self.sendForbidden_(req, res, path);
95 | fs.stat(path, function(err, stat) {
96 | if (err)
97 | return self.sendMissing_(req, res, path);
98 | if (stat.isDirectory())
99 | return self.sendDirectory_(req, res, path);
100 | return self.sendFile_(req, res, path);
101 | });
102 | }
103 |
104 | StaticServlet.prototype.sendError_ = function(req, res, error) {
105 | res.writeHead(500, {
106 | 'Content-Type': 'text/html'
107 | });
108 | res.write('\n');
109 | res.write('Internal Server Error\n');
110 | res.write('Internal Server Error
');
111 | res.write('' + escapeHtml(sys.inspect(error)) + '
');
112 | sys.puts('500 Internal Server Error');
113 | sys.puts(sys.inspect(error));
114 | };
115 |
116 | StaticServlet.prototype.sendMissing_ = function(req, res, path) {
117 | path = path.substring(1);
118 | res.writeHead(404, {
119 | 'Content-Type': 'text/html'
120 | });
121 | res.write('\n');
122 | res.write('404 Not Found\n');
123 | res.write('Not Found
');
124 | res.write(
125 | 'The requested URL ' +
126 | escapeHtml(path) +
127 | ' was not found on this server.
'
128 | );
129 | res.end();
130 | sys.puts('404 Not Found: ' + path);
131 | };
132 |
133 | StaticServlet.prototype.sendForbidden_ = function(req, res, path) {
134 | path = path.substring(1);
135 | res.writeHead(403, {
136 | 'Content-Type': 'text/html'
137 | });
138 | res.write('\n');
139 | res.write('403 Forbidden\n');
140 | res.write('Forbidden
');
141 | res.write(
142 | 'You do not have permission to access ' +
143 | escapeHtml(path) + ' on this server.
'
144 | );
145 | res.end();
146 | sys.puts('403 Forbidden: ' + path);
147 | };
148 |
149 | StaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) {
150 | res.writeHead(301, {
151 | 'Content-Type': 'text/html',
152 | 'Location': redirectUrl
153 | });
154 | res.write('\n');
155 | res.write('301 Moved Permanently\n');
156 | res.write('Moved Permanently
');
157 | res.write(
158 | 'The document has moved here.
'
161 | );
162 | res.end();
163 | sys.puts('301 Moved Permanently: ' + redirectUrl);
164 | };
165 |
166 | StaticServlet.prototype.sendFile_ = function(req, res, path) {
167 | var self = this;
168 | var file = fs.createReadStream(path);
169 | res.writeHead(200, {
170 | 'Content-Type': StaticServlet.
171 | MimeMap[path.split('.').pop()] || 'text/plain'
172 | });
173 | if (req.method === 'HEAD') {
174 | res.end();
175 | } else {
176 | file.on('data', res.write.bind(res));
177 | file.on('close', function() {
178 | res.end();
179 | });
180 | file.on('error', function(error) {
181 | self.sendError_(req, res, error);
182 | });
183 | }
184 | };
185 |
186 | StaticServlet.prototype.sendDirectory_ = function(req, res, path) {
187 | var self = this;
188 | if (path.match(/[^\/]$/)) {
189 | req.url.pathname += '/';
190 | var redirectUrl = url.format(url.parse(url.format(req.url)));
191 | return self.sendRedirect_(req, res, redirectUrl);
192 | }
193 | fs.readdir(path, function(err, files) {
194 | if (err)
195 | return self.sendError_(req, res, error);
196 |
197 | if (!files.length)
198 | return self.writeDirectoryIndex_(req, res, path, []);
199 |
200 | var remaining = files.length;
201 | files.forEach(function(fileName, index) {
202 | fs.stat(path + '/' + fileName, function(err, stat) {
203 | if (err)
204 | return self.sendError_(req, res, err);
205 | if (stat.isDirectory()) {
206 | files[index] = fileName + '/';
207 | }
208 | if (!(--remaining))
209 | return self.writeDirectoryIndex_(req, res, path, files);
210 | });
211 | });
212 | });
213 | };
214 |
215 | StaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) {
216 | path = path.substring(1);
217 | res.writeHead(200, {
218 | 'Content-Type': 'text/html'
219 | });
220 | if (req.method === 'HEAD') {
221 | res.end();
222 | return;
223 | }
224 | res.write('\n');
225 | res.write('' + escapeHtml(path) + '\n');
226 | res.write('\n');
229 | res.write('Directory: ' + escapeHtml(path) + '
');
230 | res.write('');
231 | files.forEach(function(fileName) {
232 | if (fileName.charAt(0) !== '.') {
233 | res.write('- ' +
235 | escapeHtml(fileName) + '
');
236 | }
237 | });
238 | res.write('
');
239 | res.end();
240 | };
241 |
242 | // Must be last,
243 | main(process.argv);
244 |
--------------------------------------------------------------------------------
/TryRequireJs/myPage.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | My Sample Project
5 |
7 |
8 |
9 |
10 |
11 | My Sample Project
12 | hello
13 |
14 |
15 |
--------------------------------------------------------------------------------
/TryRequireJs/scripts/main.js:
--------------------------------------------------------------------------------
1 | //main.js是入口点
2 | require(["subDir1/util1"], function(util1) {
3 | alert("util1 loaded!");
4 | });
5 |
--------------------------------------------------------------------------------
/TryRequireJs/scripts/subDir1/util1.js:
--------------------------------------------------------------------------------
1 | alert("i am util1");
2 |
3 | //main加载util1,然后util1加载util2,util2是一个module
4 | //util2返回一个JSON对象,该对象包含下面调到的两个function
5 | require(["subDir2/util2"], function(util2) {
6 | util2.alertUtil("using a function from util2, util2 is a module now, its functions are not global");
7 | util2.changeP();
8 | });
--------------------------------------------------------------------------------
/TryRequireJs/scripts/subDir2/util2.js:
--------------------------------------------------------------------------------
1 | //util2 define一个module,返回一个包含两个function的json
2 | define(function(){
3 | function util2AlertHelper(param){
4 | alert(param);
5 | }
6 | function changePElement(){
7 | var p = document.getElementById("container");
8 | p.innerText = "i am util2";
9 | }
10 | return {alertUtil:util2AlertHelper, changeP:changePElement};
11 | })
--------------------------------------------------------------------------------
/TryRequireJs/stick_price_tmp.js:
--------------------------------------------------------------------------------
1 | var priceArray = [
2 | {length:1, averagePrice:3 / 1},
3 | {length:2, averagePrice:2 / 2},
4 | {length:3, averagePrice:5 / 3},
5 | {length:4, averagePrice:4 / 4}
6 | ];
7 |
8 | var sortedPriceArray = priceArray.sort(function (item1, item2) {
9 | return item2.averagePrice - item1.averagePrice;
10 | });
11 |
12 | var index = 0;
13 | var stickLength = 4;
14 | var max = sortedPriceArray[0];
15 | var totalPrice = 0;
16 |
17 | function calculate() {
18 | while (stickLength >= max.length) {
19 | stickLength = stickLength - max.length;
20 | totalPrice = totalPrice + max.length * max.averagePrice;
21 | }
22 |
23 | if (index != sortedPriceArray.length && stickLength > 0) {
24 | index = index + 1;
25 | max = sortedPriceArray[index];
26 | calculate();
27 | }
28 | };
29 |
30 | calculate();
31 |
32 | console.log(totalPrice);
--------------------------------------------------------------------------------
/dropdowndemo/dropdowndemo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Bootstrap, from Twitter
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/dropdowndemo/js/bootstrap.js:
--------------------------------------------------------------------------------
1 | /* ===================================================
2 | * bootstrap-transition.js v2.2.2
3 | * http://twitter.github.com/bootstrap/javascript.html#transitions
4 | * ===================================================
5 | * Copyright 2012 Twitter, Inc.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | * ========================================================== */
19 |
20 |
21 | !function ($) {
22 |
23 | "use strict"; // jshint ;_;
24 |
25 |
26 | /* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
27 | * ======================================================= */
28 |
29 | $(function () {
30 |
31 | $.support.transition = (function () {
32 |
33 | var transitionEnd = (function () {
34 |
35 | var el = document.createElement('bootstrap')
36 | , transEndEventNames = {
37 | 'WebkitTransition' : 'webkitTransitionEnd'
38 | , 'MozTransition' : 'transitionend'
39 | , 'OTransition' : 'oTransitionEnd otransitionend'
40 | , 'transition' : 'transitionend'
41 | }
42 | , name
43 |
44 | for (name in transEndEventNames){
45 | if (el.style[name] !== undefined) {
46 | return transEndEventNames[name]
47 | }
48 | }
49 |
50 | }())
51 |
52 | return transitionEnd && {
53 | end: transitionEnd
54 | }
55 |
56 | })()
57 |
58 | })
59 |
60 | }(window.jQuery);
61 | /* =========================================================
62 | * bootstrap-modal.js v2.2.2
63 | * http://twitter.github.com/bootstrap/javascript.html#modals
64 | * =========================================================
65 | * Copyright 2012 Twitter, Inc.
66 | *
67 | * Licensed under the Apache License, Version 2.0 (the "License");
68 | * you may not use this file except in compliance with the License.
69 | * You may obtain a copy of the License at
70 | *
71 | * http://www.apache.org/licenses/LICENSE-2.0
72 | *
73 | * Unless required by applicable law or agreed to in writing, software
74 | * distributed under the License is distributed on an "AS IS" BASIS,
75 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
76 | * See the License for the specific language governing permissions and
77 | * limitations under the License.
78 | * ========================================================= */
79 |
80 |
81 | !function ($) {
82 |
83 | "use strict"; // jshint ;_;
84 |
85 |
86 | /* MODAL CLASS DEFINITION
87 | * ====================== */
88 |
89 | var Modal = function (element, options) {
90 | this.options = options
91 | this.$element = $(element)
92 | .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
93 | this.options.remote && this.$element.find('.modal-body').load(this.options.remote)
94 | }
95 |
96 | Modal.prototype = {
97 |
98 | constructor: Modal
99 |
100 | , toggle: function () {
101 | return this[!this.isShown ? 'show' : 'hide']()
102 | }
103 |
104 | , show: function () {
105 | var that = this
106 | , e = $.Event('show')
107 |
108 | this.$element.trigger(e)
109 |
110 | if (this.isShown || e.isDefaultPrevented()) return
111 |
112 | this.isShown = true
113 |
114 | this.escape()
115 |
116 | this.backdrop(function () {
117 | var transition = $.support.transition && that.$element.hasClass('fade')
118 |
119 | if (!that.$element.parent().length) {
120 | that.$element.appendTo(document.body) //don't move modals dom position
121 | }
122 |
123 | that.$element
124 | .show()
125 |
126 | if (transition) {
127 | that.$element[0].offsetWidth // force reflow
128 | }
129 |
130 | that.$element
131 | .addClass('in')
132 | .attr('aria-hidden', false)
133 |
134 | that.enforceFocus()
135 |
136 | transition ?
137 | that.$element.one($.support.transition.end, function () { that.$element.focus().trigger('shown') }) :
138 | that.$element.focus().trigger('shown')
139 |
140 | })
141 | }
142 |
143 | , hide: function (e) {
144 | e && e.preventDefault()
145 |
146 | var that = this
147 |
148 | e = $.Event('hide')
149 |
150 | this.$element.trigger(e)
151 |
152 | if (!this.isShown || e.isDefaultPrevented()) return
153 |
154 | this.isShown = false
155 |
156 | this.escape()
157 |
158 | $(document).off('focusin.modal')
159 |
160 | this.$element
161 | .removeClass('in')
162 | .attr('aria-hidden', true)
163 |
164 | $.support.transition && this.$element.hasClass('fade') ?
165 | this.hideWithTransition() :
166 | this.hideModal()
167 | }
168 |
169 | , enforceFocus: function () {
170 | var that = this
171 | $(document).on('focusin.modal', function (e) {
172 | if (that.$element[0] !== e.target && !that.$element.has(e.target).length) {
173 | that.$element.focus()
174 | }
175 | })
176 | }
177 |
178 | , escape: function () {
179 | var that = this
180 | if (this.isShown && this.options.keyboard) {
181 | this.$element.on('keyup.dismiss.modal', function ( e ) {
182 | e.which == 27 && that.hide()
183 | })
184 | } else if (!this.isShown) {
185 | this.$element.off('keyup.dismiss.modal')
186 | }
187 | }
188 |
189 | , hideWithTransition: function () {
190 | var that = this
191 | , timeout = setTimeout(function () {
192 | that.$element.off($.support.transition.end)
193 | that.hideModal()
194 | }, 500)
195 |
196 | this.$element.one($.support.transition.end, function () {
197 | clearTimeout(timeout)
198 | that.hideModal()
199 | })
200 | }
201 |
202 | , hideModal: function (that) {
203 | this.$element
204 | .hide()
205 | .trigger('hidden')
206 |
207 | this.backdrop()
208 | }
209 |
210 | , removeBackdrop: function () {
211 | this.$backdrop.remove()
212 | this.$backdrop = null
213 | }
214 |
215 | , backdrop: function (callback) {
216 | var that = this
217 | , animate = this.$element.hasClass('fade') ? 'fade' : ''
218 |
219 | if (this.isShown && this.options.backdrop) {
220 | var doAnimate = $.support.transition && animate
221 |
222 | this.$backdrop = $('')
223 | .appendTo(document.body)
224 |
225 | this.$backdrop.click(
226 | this.options.backdrop == 'static' ?
227 | $.proxy(this.$element[0].focus, this.$element[0])
228 | : $.proxy(this.hide, this)
229 | )
230 |
231 | if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
232 |
233 | this.$backdrop.addClass('in')
234 |
235 | doAnimate ?
236 | this.$backdrop.one($.support.transition.end, callback) :
237 | callback()
238 |
239 | } else if (!this.isShown && this.$backdrop) {
240 | this.$backdrop.removeClass('in')
241 |
242 | $.support.transition && this.$element.hasClass('fade')?
243 | this.$backdrop.one($.support.transition.end, $.proxy(this.removeBackdrop, this)) :
244 | this.removeBackdrop()
245 |
246 | } else if (callback) {
247 | callback()
248 | }
249 | }
250 | }
251 |
252 |
253 | /* MODAL PLUGIN DEFINITION
254 | * ======================= */
255 |
256 | var old = $.fn.modal
257 |
258 | $.fn.modal = function (option) {
259 | return this.each(function () {
260 | var $this = $(this)
261 | , data = $this.data('modal')
262 | , options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)
263 | if (!data) $this.data('modal', (data = new Modal(this, options)))
264 | if (typeof option == 'string') data[option]()
265 | else if (options.show) data.show()
266 | })
267 | }
268 |
269 | $.fn.modal.defaults = {
270 | backdrop: true
271 | , keyboard: true
272 | , show: true
273 | }
274 |
275 | $.fn.modal.Constructor = Modal
276 |
277 |
278 | /* MODAL NO CONFLICT
279 | * ================= */
280 |
281 | $.fn.modal.noConflict = function () {
282 | $.fn.modal = old
283 | return this
284 | }
285 |
286 |
287 | /* MODAL DATA-API
288 | * ============== */
289 |
290 | $(document).on('click.modal.data-api', '[data-toggle="modal"]', function (e) {
291 | var $this = $(this)
292 | , href = $this.attr('href')
293 | , $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
294 | , option = $target.data('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())
295 |
296 | e.preventDefault()
297 |
298 | $target
299 | .modal(option)
300 | .one('hide', function () {
301 | $this.focus()
302 | })
303 | })
304 |
305 | }(window.jQuery);
306 |
307 | /* ============================================================
308 | * bootstrap-dropdown.js v2.2.2
309 | * http://twitter.github.com/bootstrap/javascript.html#dropdowns
310 | * ============================================================
311 | * Copyright 2012 Twitter, Inc.
312 | *
313 | * Licensed under the Apache License, Version 2.0 (the "License");
314 | * you may not use this file except in compliance with the License.
315 | * You may obtain a copy of the License at
316 | *
317 | * http://www.apache.org/licenses/LICENSE-2.0
318 | *
319 | * Unless required by applicable law or agreed to in writing, software
320 | * distributed under the License is distributed on an "AS IS" BASIS,
321 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
322 | * See the License for the specific language governing permissions and
323 | * limitations under the License.
324 | * ============================================================ */
325 |
326 |
327 | !function ($) {
328 |
329 | "use strict"; // jshint ;_;
330 |
331 |
332 | /* DROPDOWN CLASS DEFINITION
333 | * ========================= */
334 |
335 | var toggle = '[data-toggle=dropdown]'
336 | , Dropdown = function (element) {
337 | var $el = $(element).on('click.dropdown.data-api', this.toggle)
338 | $('html').on('click.dropdown.data-api', function () {
339 | $el.parent().removeClass('open')
340 | })
341 | }
342 |
343 | Dropdown.prototype = {
344 |
345 | constructor: Dropdown
346 |
347 | , toggle: function (e) {
348 | var $this = $(this)
349 | , $parent
350 | , isActive
351 |
352 | if ($this.is('.disabled, :disabled')) return
353 |
354 | $parent = getParent($this)
355 |
356 | isActive = $parent.hasClass('open')
357 |
358 | clearMenus()
359 |
360 | if (!isActive) {
361 | $parent.toggleClass('open')
362 | }
363 |
364 | $this.focus()
365 |
366 | return false
367 | }
368 |
369 | , keydown: function (e) {
370 | var $this
371 | , $items
372 | , $active
373 | , $parent
374 | , isActive
375 | , index
376 |
377 | if (!/(38|40|27)/.test(e.keyCode)) return
378 |
379 | $this = $(this)
380 |
381 | e.preventDefault()
382 | e.stopPropagation()
383 |
384 | if ($this.is('.disabled, :disabled')) return
385 |
386 | $parent = getParent($this)
387 |
388 | isActive = $parent.hasClass('open')
389 |
390 | if (!isActive || (isActive && e.keyCode == 27)) return $this.click()
391 |
392 | $items = $('[role=menu] li:not(.divider):visible a', $parent)
393 |
394 | if (!$items.length) return
395 |
396 | index = $items.index($items.filter(':focus'))
397 |
398 | if (e.keyCode == 38 && index > 0) index-- // up
399 | if (e.keyCode == 40 && index < $items.length - 1) index++ // down
400 | if (!~index) index = 0
401 |
402 | $items
403 | .eq(index)
404 | .focus()
405 | }
406 |
407 | }
408 |
409 | function clearMenus() {
410 | $(toggle).each(function () {
411 | getParent($(this)).removeClass('open')
412 | })
413 | }
414 |
415 | function getParent($this) {
416 | var selector = $this.attr('data-target')
417 | , $parent
418 |
419 | if (!selector) {
420 | selector = $this.attr('href')
421 | selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
422 | }
423 |
424 | $parent = $(selector)
425 | $parent.length || ($parent = $this.parent())
426 |
427 | return $parent
428 | }
429 |
430 |
431 | /* DROPDOWN PLUGIN DEFINITION
432 | * ========================== */
433 |
434 | var old = $.fn.dropdown
435 |
436 | $.fn.dropdown = function (option) {
437 | return this.each(function () {
438 | var $this = $(this)
439 | , data = $this.data('dropdown')
440 | if (!data) $this.data('dropdown', (data = new Dropdown(this)))
441 | if (typeof option == 'string') data[option].call($this)
442 | })
443 | }
444 |
445 | $.fn.dropdown.Constructor = Dropdown
446 |
447 |
448 | /* DROPDOWN NO CONFLICT
449 | * ==================== */
450 |
451 | $.fn.dropdown.noConflict = function () {
452 | $.fn.dropdown = old
453 | return this
454 | }
455 |
456 |
457 | /* APPLY TO STANDARD DROPDOWN ELEMENTS
458 | * =================================== */
459 |
460 | $(document)
461 | .on('click.dropdown.data-api touchstart.dropdown.data-api', clearMenus)
462 | .on('click.dropdown touchstart.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
463 | .on('touchstart.dropdown.data-api', '.dropdown-menu', function (e) { e.stopPropagation() })
464 | .on('click.dropdown.data-api touchstart.dropdown.data-api' , toggle, Dropdown.prototype.toggle)
465 | .on('keydown.dropdown.data-api touchstart.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
466 |
467 | }(window.jQuery);
468 | /* =============================================================
469 | * bootstrap-scrollspy.js v2.2.2
470 | * http://twitter.github.com/bootstrap/javascript.html#scrollspy
471 | * =============================================================
472 | * Copyright 2012 Twitter, Inc.
473 | *
474 | * Licensed under the Apache License, Version 2.0 (the "License");
475 | * you may not use this file except in compliance with the License.
476 | * You may obtain a copy of the License at
477 | *
478 | * http://www.apache.org/licenses/LICENSE-2.0
479 | *
480 | * Unless required by applicable law or agreed to in writing, software
481 | * distributed under the License is distributed on an "AS IS" BASIS,
482 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
483 | * See the License for the specific language governing permissions and
484 | * limitations under the License.
485 | * ============================================================== */
486 |
487 |
488 | !function ($) {
489 |
490 | "use strict"; // jshint ;_;
491 |
492 |
493 | /* SCROLLSPY CLASS DEFINITION
494 | * ========================== */
495 |
496 | function ScrollSpy(element, options) {
497 | var process = $.proxy(this.process, this)
498 | , $element = $(element).is('body') ? $(window) : $(element)
499 | , href
500 | this.options = $.extend({}, $.fn.scrollspy.defaults, options)
501 | this.$scrollElement = $element.on('scroll.scroll-spy.data-api', process)
502 | this.selector = (this.options.target
503 | || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
504 | || '') + ' .nav li > a'
505 | this.$body = $('body')
506 | this.refresh()
507 | this.process()
508 | }
509 |
510 | ScrollSpy.prototype = {
511 |
512 | constructor: ScrollSpy
513 |
514 | , refresh: function () {
515 | var self = this
516 | , $targets
517 |
518 | this.offsets = $([])
519 | this.targets = $([])
520 |
521 | $targets = this.$body
522 | .find(this.selector)
523 | .map(function () {
524 | var $el = $(this)
525 | , href = $el.data('target') || $el.attr('href')
526 | , $href = /^#\w/.test(href) && $(href)
527 | return ( $href
528 | && $href.length
529 | && [[ $href.position().top + self.$scrollElement.scrollTop(), href ]] ) || null
530 | })
531 | .sort(function (a, b) { return a[0] - b[0] })
532 | .each(function () {
533 | self.offsets.push(this[0])
534 | self.targets.push(this[1])
535 | })
536 | }
537 |
538 | , process: function () {
539 | var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
540 | , scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight
541 | , maxScroll = scrollHeight - this.$scrollElement.height()
542 | , offsets = this.offsets
543 | , targets = this.targets
544 | , activeTarget = this.activeTarget
545 | , i
546 |
547 | if (scrollTop >= maxScroll) {
548 | return activeTarget != (i = targets.last()[0])
549 | && this.activate ( i )
550 | }
551 |
552 | for (i = offsets.length; i--;) {
553 | activeTarget != targets[i]
554 | && scrollTop >= offsets[i]
555 | && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
556 | && this.activate( targets[i] )
557 | }
558 | }
559 |
560 | , activate: function (target) {
561 | var active
562 | , selector
563 |
564 | this.activeTarget = target
565 |
566 | $(this.selector)
567 | .parent('.active')
568 | .removeClass('active')
569 |
570 | selector = this.selector
571 | + '[data-target="' + target + '"],'
572 | + this.selector + '[href="' + target + '"]'
573 |
574 | active = $(selector)
575 | .parent('li')
576 | .addClass('active')
577 |
578 | if (active.parent('.dropdown-menu').length) {
579 | active = active.closest('li.dropdown').addClass('active')
580 | }
581 |
582 | active.trigger('activate')
583 | }
584 |
585 | }
586 |
587 |
588 | /* SCROLLSPY PLUGIN DEFINITION
589 | * =========================== */
590 |
591 | var old = $.fn.scrollspy
592 |
593 | $.fn.scrollspy = function (option) {
594 | return this.each(function () {
595 | var $this = $(this)
596 | , data = $this.data('scrollspy')
597 | , options = typeof option == 'object' && option
598 | if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))
599 | if (typeof option == 'string') data[option]()
600 | })
601 | }
602 |
603 | $.fn.scrollspy.Constructor = ScrollSpy
604 |
605 | $.fn.scrollspy.defaults = {
606 | offset: 10
607 | }
608 |
609 |
610 | /* SCROLLSPY NO CONFLICT
611 | * ===================== */
612 |
613 | $.fn.scrollspy.noConflict = function () {
614 | $.fn.scrollspy = old
615 | return this
616 | }
617 |
618 |
619 | /* SCROLLSPY DATA-API
620 | * ================== */
621 |
622 | $(window).on('load', function () {
623 | $('[data-spy="scroll"]').each(function () {
624 | var $spy = $(this)
625 | $spy.scrollspy($spy.data())
626 | })
627 | })
628 |
629 | }(window.jQuery);
630 | /* ========================================================
631 | * bootstrap-tab.js v2.2.2
632 | * http://twitter.github.com/bootstrap/javascript.html#tabs
633 | * ========================================================
634 | * Copyright 2012 Twitter, Inc.
635 | *
636 | * Licensed under the Apache License, Version 2.0 (the "License");
637 | * you may not use this file except in compliance with the License.
638 | * You may obtain a copy of the License at
639 | *
640 | * http://www.apache.org/licenses/LICENSE-2.0
641 | *
642 | * Unless required by applicable law or agreed to in writing, software
643 | * distributed under the License is distributed on an "AS IS" BASIS,
644 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
645 | * See the License for the specific language governing permissions and
646 | * limitations under the License.
647 | * ======================================================== */
648 |
649 |
650 | !function ($) {
651 |
652 | "use strict"; // jshint ;_;
653 |
654 |
655 | /* TAB CLASS DEFINITION
656 | * ==================== */
657 |
658 | var Tab = function (element) {
659 | this.element = $(element)
660 | }
661 |
662 | Tab.prototype = {
663 |
664 | constructor: Tab
665 |
666 | , show: function () {
667 | var $this = this.element
668 | , $ul = $this.closest('ul:not(.dropdown-menu)')
669 | , selector = $this.attr('data-target')
670 | , previous
671 | , $target
672 | , e
673 |
674 | if (!selector) {
675 | selector = $this.attr('href')
676 | selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
677 | }
678 |
679 | if ( $this.parent('li').hasClass('active') ) return
680 |
681 | previous = $ul.find('.active:last a')[0]
682 |
683 | e = $.Event('show', {
684 | relatedTarget: previous
685 | })
686 |
687 | $this.trigger(e)
688 |
689 | if (e.isDefaultPrevented()) return
690 |
691 | $target = $(selector)
692 |
693 | this.activate($this.parent('li'), $ul)
694 | this.activate($target, $target.parent(), function () {
695 | $this.trigger({
696 | type: 'shown'
697 | , relatedTarget: previous
698 | })
699 | })
700 | }
701 |
702 | , activate: function ( element, container, callback) {
703 | var $active = container.find('> .active')
704 | , transition = callback
705 | && $.support.transition
706 | && $active.hasClass('fade')
707 |
708 | function next() {
709 | $active
710 | .removeClass('active')
711 | .find('> .dropdown-menu > .active')
712 | .removeClass('active')
713 |
714 | element.addClass('active')
715 |
716 | if (transition) {
717 | element[0].offsetWidth // reflow for transition
718 | element.addClass('in')
719 | } else {
720 | element.removeClass('fade')
721 | }
722 |
723 | if ( element.parent('.dropdown-menu') ) {
724 | element.closest('li.dropdown').addClass('active')
725 | }
726 |
727 | callback && callback()
728 | }
729 |
730 | transition ?
731 | $active.one($.support.transition.end, next) :
732 | next()
733 |
734 | $active.removeClass('in')
735 | }
736 | }
737 |
738 |
739 | /* TAB PLUGIN DEFINITION
740 | * ===================== */
741 |
742 | var old = $.fn.tab
743 |
744 | $.fn.tab = function ( option ) {
745 | return this.each(function () {
746 | var $this = $(this)
747 | , data = $this.data('tab')
748 | if (!data) $this.data('tab', (data = new Tab(this)))
749 | if (typeof option == 'string') data[option]()
750 | })
751 | }
752 |
753 | $.fn.tab.Constructor = Tab
754 |
755 |
756 | /* TAB NO CONFLICT
757 | * =============== */
758 |
759 | $.fn.tab.noConflict = function () {
760 | $.fn.tab = old
761 | return this
762 | }
763 |
764 |
765 | /* TAB DATA-API
766 | * ============ */
767 |
768 | $(document).on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
769 | e.preventDefault()
770 | $(this).tab('show')
771 | })
772 |
773 | }(window.jQuery);
774 | /* ===========================================================
775 | * bootstrap-tooltip.js v2.2.2
776 | * http://twitter.github.com/bootstrap/javascript.html#tooltips
777 | * Inspired by the original jQuery.tipsy by Jason Frame
778 | * ===========================================================
779 | * Copyright 2012 Twitter, Inc.
780 | *
781 | * Licensed under the Apache License, Version 2.0 (the "License");
782 | * you may not use this file except in compliance with the License.
783 | * You may obtain a copy of the License at
784 | *
785 | * http://www.apache.org/licenses/LICENSE-2.0
786 | *
787 | * Unless required by applicable law or agreed to in writing, software
788 | * distributed under the License is distributed on an "AS IS" BASIS,
789 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
790 | * See the License for the specific language governing permissions and
791 | * limitations under the License.
792 | * ========================================================== */
793 |
794 |
795 | !function ($) {
796 |
797 | "use strict"; // jshint ;_;
798 |
799 |
800 | /* TOOLTIP PUBLIC CLASS DEFINITION
801 | * =============================== */
802 |
803 | var Tooltip = function (element, options) {
804 | this.init('tooltip', element, options)
805 | }
806 |
807 | Tooltip.prototype = {
808 |
809 | constructor: Tooltip
810 |
811 | , init: function (type, element, options) {
812 | var eventIn
813 | , eventOut
814 |
815 | this.type = type
816 | this.$element = $(element)
817 | this.options = this.getOptions(options)
818 | this.enabled = true
819 |
820 | if (this.options.trigger == 'click') {
821 | this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
822 | } else if (this.options.trigger != 'manual') {
823 | eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
824 | eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
825 | this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
826 | this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
827 | }
828 |
829 | this.options.selector ?
830 | (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
831 | this.fixTitle()
832 | }
833 |
834 | , getOptions: function (options) {
835 | options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data())
836 |
837 | if (options.delay && typeof options.delay == 'number') {
838 | options.delay = {
839 | show: options.delay
840 | , hide: options.delay
841 | }
842 | }
843 |
844 | return options
845 | }
846 |
847 | , enter: function (e) {
848 | var self = $(e.currentTarget)[this.type](this._options).data(this.type)
849 |
850 | if (!self.options.delay || !self.options.delay.show) return self.show()
851 |
852 | clearTimeout(this.timeout)
853 | self.hoverState = 'in'
854 | this.timeout = setTimeout(function() {
855 | if (self.hoverState == 'in') self.show()
856 | }, self.options.delay.show)
857 | }
858 |
859 | , leave: function (e) {
860 | var self = $(e.currentTarget)[this.type](this._options).data(this.type)
861 |
862 | if (this.timeout) clearTimeout(this.timeout)
863 | if (!self.options.delay || !self.options.delay.hide) return self.hide()
864 |
865 | self.hoverState = 'out'
866 | this.timeout = setTimeout(function() {
867 | if (self.hoverState == 'out') self.hide()
868 | }, self.options.delay.hide)
869 | }
870 |
871 | , show: function () {
872 | var $tip
873 | , inside
874 | , pos
875 | , actualWidth
876 | , actualHeight
877 | , placement
878 | , tp
879 |
880 | if (this.hasContent() && this.enabled) {
881 | $tip = this.tip()
882 | this.setContent()
883 |
884 | if (this.options.animation) {
885 | $tip.addClass('fade')
886 | }
887 |
888 | placement = typeof this.options.placement == 'function' ?
889 | this.options.placement.call(this, $tip[0], this.$element[0]) :
890 | this.options.placement
891 |
892 | inside = /in/.test(placement)
893 |
894 | $tip
895 | .detach()
896 | .css({ top: 0, left: 0, display: 'block' })
897 | .insertAfter(this.$element)
898 |
899 | pos = this.getPosition(inside)
900 |
901 | actualWidth = $tip[0].offsetWidth
902 | actualHeight = $tip[0].offsetHeight
903 |
904 | switch (inside ? placement.split(' ')[1] : placement) {
905 | case 'bottom':
906 | tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
907 | break
908 | case 'top':
909 | tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
910 | break
911 | case 'left':
912 | tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
913 | break
914 | case 'right':
915 | tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
916 | break
917 | }
918 |
919 | $tip
920 | .offset(tp)
921 | .addClass(placement)
922 | .addClass('in')
923 | }
924 | }
925 |
926 | , setContent: function () {
927 | var $tip = this.tip()
928 | , title = this.getTitle()
929 |
930 | $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
931 | $tip.removeClass('fade in top bottom left right')
932 | }
933 |
934 | , hide: function () {
935 | var that = this
936 | , $tip = this.tip()
937 |
938 | $tip.removeClass('in')
939 |
940 | function removeWithAnimation() {
941 | var timeout = setTimeout(function () {
942 | $tip.off($.support.transition.end).detach()
943 | }, 500)
944 |
945 | $tip.one($.support.transition.end, function () {
946 | clearTimeout(timeout)
947 | $tip.detach()
948 | })
949 | }
950 |
951 | $.support.transition && this.$tip.hasClass('fade') ?
952 | removeWithAnimation() :
953 | $tip.detach()
954 |
955 | return this
956 | }
957 |
958 | , fixTitle: function () {
959 | var $e = this.$element
960 | if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
961 | $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')
962 | }
963 | }
964 |
965 | , hasContent: function () {
966 | return this.getTitle()
967 | }
968 |
969 | , getPosition: function (inside) {
970 | return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), {
971 | width: this.$element[0].offsetWidth
972 | , height: this.$element[0].offsetHeight
973 | })
974 | }
975 |
976 | , getTitle: function () {
977 | var title
978 | , $e = this.$element
979 | , o = this.options
980 |
981 | title = $e.attr('data-original-title')
982 | || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
983 |
984 | return title
985 | }
986 |
987 | , tip: function () {
988 | return this.$tip = this.$tip || $(this.options.template)
989 | }
990 |
991 | , validate: function () {
992 | if (!this.$element[0].parentNode) {
993 | this.hide()
994 | this.$element = null
995 | this.options = null
996 | }
997 | }
998 |
999 | , enable: function () {
1000 | this.enabled = true
1001 | }
1002 |
1003 | , disable: function () {
1004 | this.enabled = false
1005 | }
1006 |
1007 | , toggleEnabled: function () {
1008 | this.enabled = !this.enabled
1009 | }
1010 |
1011 | , toggle: function (e) {
1012 | var self = $(e.currentTarget)[this.type](this._options).data(this.type)
1013 | self[self.tip().hasClass('in') ? 'hide' : 'show']()
1014 | }
1015 |
1016 | , destroy: function () {
1017 | this.hide().$element.off('.' + this.type).removeData(this.type)
1018 | }
1019 |
1020 | }
1021 |
1022 |
1023 | /* TOOLTIP PLUGIN DEFINITION
1024 | * ========================= */
1025 |
1026 | var old = $.fn.tooltip
1027 |
1028 | $.fn.tooltip = function ( option ) {
1029 | return this.each(function () {
1030 | var $this = $(this)
1031 | , data = $this.data('tooltip')
1032 | , options = typeof option == 'object' && option
1033 | if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
1034 | if (typeof option == 'string') data[option]()
1035 | })
1036 | }
1037 |
1038 | $.fn.tooltip.Constructor = Tooltip
1039 |
1040 | $.fn.tooltip.defaults = {
1041 | animation: true
1042 | , placement: 'top'
1043 | , selector: false
1044 | , template: ''
1045 | , trigger: 'hover'
1046 | , title: ''
1047 | , delay: 0
1048 | , html: false
1049 | }
1050 |
1051 |
1052 | /* TOOLTIP NO CONFLICT
1053 | * =================== */
1054 |
1055 | $.fn.tooltip.noConflict = function () {
1056 | $.fn.tooltip = old
1057 | return this
1058 | }
1059 |
1060 | }(window.jQuery);
1061 | /* ===========================================================
1062 | * bootstrap-popover.js v2.2.2
1063 | * http://twitter.github.com/bootstrap/javascript.html#popovers
1064 | * ===========================================================
1065 | * Copyright 2012 Twitter, Inc.
1066 | *
1067 | * Licensed under the Apache License, Version 2.0 (the "License");
1068 | * you may not use this file except in compliance with the License.
1069 | * You may obtain a copy of the License at
1070 | *
1071 | * http://www.apache.org/licenses/LICENSE-2.0
1072 | *
1073 | * Unless required by applicable law or agreed to in writing, software
1074 | * distributed under the License is distributed on an "AS IS" BASIS,
1075 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1076 | * See the License for the specific language governing permissions and
1077 | * limitations under the License.
1078 | * =========================================================== */
1079 |
1080 |
1081 | !function ($) {
1082 |
1083 | "use strict"; // jshint ;_;
1084 |
1085 |
1086 | /* POPOVER PUBLIC CLASS DEFINITION
1087 | * =============================== */
1088 |
1089 | var Popover = function (element, options) {
1090 | this.init('popover', element, options)
1091 | }
1092 |
1093 |
1094 | /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
1095 | ========================================== */
1096 |
1097 | Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
1098 |
1099 | constructor: Popover
1100 |
1101 | , setContent: function () {
1102 | var $tip = this.tip()
1103 | , title = this.getTitle()
1104 | , content = this.getContent()
1105 |
1106 | $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
1107 | $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)
1108 |
1109 | $tip.removeClass('fade top bottom left right in')
1110 | }
1111 |
1112 | , hasContent: function () {
1113 | return this.getTitle() || this.getContent()
1114 | }
1115 |
1116 | , getContent: function () {
1117 | var content
1118 | , $e = this.$element
1119 | , o = this.options
1120 |
1121 | content = $e.attr('data-content')
1122 | || (typeof o.content == 'function' ? o.content.call($e[0]) : o.content)
1123 |
1124 | return content
1125 | }
1126 |
1127 | , tip: function () {
1128 | if (!this.$tip) {
1129 | this.$tip = $(this.options.template)
1130 | }
1131 | return this.$tip
1132 | }
1133 |
1134 | , destroy: function () {
1135 | this.hide().$element.off('.' + this.type).removeData(this.type)
1136 | }
1137 |
1138 | })
1139 |
1140 |
1141 | /* POPOVER PLUGIN DEFINITION
1142 | * ======================= */
1143 |
1144 | var old = $.fn.popover
1145 |
1146 | $.fn.popover = function (option) {
1147 | return this.each(function () {
1148 | var $this = $(this)
1149 | , data = $this.data('popover')
1150 | , options = typeof option == 'object' && option
1151 | if (!data) $this.data('popover', (data = new Popover(this, options)))
1152 | if (typeof option == 'string') data[option]()
1153 | })
1154 | }
1155 |
1156 | $.fn.popover.Constructor = Popover
1157 |
1158 | $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
1159 | placement: 'right'
1160 | , trigger: 'click'
1161 | , content: ''
1162 | , template: ''
1163 | })
1164 |
1165 |
1166 | /* POPOVER NO CONFLICT
1167 | * =================== */
1168 |
1169 | $.fn.popover.noConflict = function () {
1170 | $.fn.popover = old
1171 | return this
1172 | }
1173 |
1174 | }(window.jQuery);
1175 | /* ==========================================================
1176 | * bootstrap-affix.js v2.2.2
1177 | * http://twitter.github.com/bootstrap/javascript.html#affix
1178 | * ==========================================================
1179 | * Copyright 2012 Twitter, Inc.
1180 | *
1181 | * Licensed under the Apache License, Version 2.0 (the "License");
1182 | * you may not use this file except in compliance with the License.
1183 | * You may obtain a copy of the License at
1184 | *
1185 | * http://www.apache.org/licenses/LICENSE-2.0
1186 | *
1187 | * Unless required by applicable law or agreed to in writing, software
1188 | * distributed under the License is distributed on an "AS IS" BASIS,
1189 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1190 | * See the License for the specific language governing permissions and
1191 | * limitations under the License.
1192 | * ========================================================== */
1193 |
1194 |
1195 | !function ($) {
1196 |
1197 | "use strict"; // jshint ;_;
1198 |
1199 |
1200 | /* AFFIX CLASS DEFINITION
1201 | * ====================== */
1202 |
1203 | var Affix = function (element, options) {
1204 | this.options = $.extend({}, $.fn.affix.defaults, options)
1205 | this.$window = $(window)
1206 | .on('scroll.affix.data-api', $.proxy(this.checkPosition, this))
1207 | .on('click.affix.data-api', $.proxy(function () { setTimeout($.proxy(this.checkPosition, this), 1) }, this))
1208 | this.$element = $(element)
1209 | this.checkPosition()
1210 | }
1211 |
1212 | Affix.prototype.checkPosition = function () {
1213 | if (!this.$element.is(':visible')) return
1214 |
1215 | var scrollHeight = $(document).height()
1216 | , scrollTop = this.$window.scrollTop()
1217 | , position = this.$element.offset()
1218 | , offset = this.options.offset
1219 | , offsetBottom = offset.bottom
1220 | , offsetTop = offset.top
1221 | , reset = 'affix affix-top affix-bottom'
1222 | , affix
1223 |
1224 | if (typeof offset != 'object') offsetBottom = offsetTop = offset
1225 | if (typeof offsetTop == 'function') offsetTop = offset.top()
1226 | if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()
1227 |
1228 | affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ?
1229 | false : offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ?
1230 | 'bottom' : offsetTop != null && scrollTop <= offsetTop ?
1231 | 'top' : false
1232 |
1233 | if (this.affixed === affix) return
1234 |
1235 | this.affixed = affix
1236 | this.unpin = affix == 'bottom' ? position.top - scrollTop : null
1237 |
1238 | this.$element.removeClass(reset).addClass('affix' + (affix ? '-' + affix : ''))
1239 | }
1240 |
1241 |
1242 | /* AFFIX PLUGIN DEFINITION
1243 | * ======================= */
1244 |
1245 | var old = $.fn.affix
1246 |
1247 | $.fn.affix = function (option) {
1248 | return this.each(function () {
1249 | var $this = $(this)
1250 | , data = $this.data('affix')
1251 | , options = typeof option == 'object' && option
1252 | if (!data) $this.data('affix', (data = new Affix(this, options)))
1253 | if (typeof option == 'string') data[option]()
1254 | })
1255 | }
1256 |
1257 | $.fn.affix.Constructor = Affix
1258 |
1259 | $.fn.affix.defaults = {
1260 | offset: 0
1261 | }
1262 |
1263 |
1264 | /* AFFIX NO CONFLICT
1265 | * ================= */
1266 |
1267 | $.fn.affix.noConflict = function () {
1268 | $.fn.affix = old
1269 | return this
1270 | }
1271 |
1272 |
1273 | /* AFFIX DATA-API
1274 | * ============== */
1275 |
1276 | $(window).on('load', function () {
1277 | $('[data-spy="affix"]').each(function () {
1278 | var $spy = $(this)
1279 | , data = $spy.data()
1280 |
1281 | data.offset = data.offset || {}
1282 |
1283 | data.offsetBottom && (data.offset.bottom = data.offsetBottom)
1284 | data.offsetTop && (data.offset.top = data.offsetTop)
1285 |
1286 | $spy.affix(data)
1287 | })
1288 | })
1289 |
1290 |
1291 | }(window.jQuery);
1292 | /* ==========================================================
1293 | * bootstrap-alert.js v2.2.2
1294 | * http://twitter.github.com/bootstrap/javascript.html#alerts
1295 | * ==========================================================
1296 | * Copyright 2012 Twitter, Inc.
1297 | *
1298 | * Licensed under the Apache License, Version 2.0 (the "License");
1299 | * you may not use this file except in compliance with the License.
1300 | * You may obtain a copy of the License at
1301 | *
1302 | * http://www.apache.org/licenses/LICENSE-2.0
1303 | *
1304 | * Unless required by applicable law or agreed to in writing, software
1305 | * distributed under the License is distributed on an "AS IS" BASIS,
1306 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1307 | * See the License for the specific language governing permissions and
1308 | * limitations under the License.
1309 | * ========================================================== */
1310 |
1311 |
1312 | !function ($) {
1313 |
1314 | "use strict"; // jshint ;_;
1315 |
1316 |
1317 | /* ALERT CLASS DEFINITION
1318 | * ====================== */
1319 |
1320 | var dismiss = '[data-dismiss="alert"]'
1321 | , Alert = function (el) {
1322 | $(el).on('click', dismiss, this.close)
1323 | }
1324 |
1325 | Alert.prototype.close = function (e) {
1326 | var $this = $(this)
1327 | , selector = $this.attr('data-target')
1328 | , $parent
1329 |
1330 | if (!selector) {
1331 | selector = $this.attr('href')
1332 | selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
1333 | }
1334 |
1335 | $parent = $(selector)
1336 |
1337 | e && e.preventDefault()
1338 |
1339 | $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())
1340 |
1341 | $parent.trigger(e = $.Event('close'))
1342 |
1343 | if (e.isDefaultPrevented()) return
1344 |
1345 | $parent.removeClass('in')
1346 |
1347 | function removeElement() {
1348 | $parent
1349 | .trigger('closed')
1350 | .remove()
1351 | }
1352 |
1353 | $.support.transition && $parent.hasClass('fade') ?
1354 | $parent.on($.support.transition.end, removeElement) :
1355 | removeElement()
1356 | }
1357 |
1358 |
1359 | /* ALERT PLUGIN DEFINITION
1360 | * ======================= */
1361 |
1362 | var old = $.fn.alert
1363 |
1364 | $.fn.alert = function (option) {
1365 | return this.each(function () {
1366 | var $this = $(this)
1367 | , data = $this.data('alert')
1368 | if (!data) $this.data('alert', (data = new Alert(this)))
1369 | if (typeof option == 'string') data[option].call($this)
1370 | })
1371 | }
1372 |
1373 | $.fn.alert.Constructor = Alert
1374 |
1375 |
1376 | /* ALERT NO CONFLICT
1377 | * ================= */
1378 |
1379 | $.fn.alert.noConflict = function () {
1380 | $.fn.alert = old
1381 | return this
1382 | }
1383 |
1384 |
1385 | /* ALERT DATA-API
1386 | * ============== */
1387 |
1388 | $(document).on('click.alert.data-api', dismiss, Alert.prototype.close)
1389 |
1390 | }(window.jQuery);
1391 | /* ============================================================
1392 | * bootstrap-button.js v2.2.2
1393 | * http://twitter.github.com/bootstrap/javascript.html#buttons
1394 | * ============================================================
1395 | * Copyright 2012 Twitter, Inc.
1396 | *
1397 | * Licensed under the Apache License, Version 2.0 (the "License");
1398 | * you may not use this file except in compliance with the License.
1399 | * You may obtain a copy of the License at
1400 | *
1401 | * http://www.apache.org/licenses/LICENSE-2.0
1402 | *
1403 | * Unless required by applicable law or agreed to in writing, software
1404 | * distributed under the License is distributed on an "AS IS" BASIS,
1405 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1406 | * See the License for the specific language governing permissions and
1407 | * limitations under the License.
1408 | * ============================================================ */
1409 |
1410 |
1411 | !function ($) {
1412 |
1413 | "use strict"; // jshint ;_;
1414 |
1415 |
1416 | /* BUTTON PUBLIC CLASS DEFINITION
1417 | * ============================== */
1418 |
1419 | var Button = function (element, options) {
1420 | this.$element = $(element)
1421 | this.options = $.extend({}, $.fn.button.defaults, options)
1422 | }
1423 |
1424 | Button.prototype.setState = function (state) {
1425 | var d = 'disabled'
1426 | , $el = this.$element
1427 | , data = $el.data()
1428 | , val = $el.is('input') ? 'val' : 'html'
1429 |
1430 | state = state + 'Text'
1431 | data.resetText || $el.data('resetText', $el[val]())
1432 |
1433 | $el[val](data[state] || this.options[state])
1434 |
1435 | // push to event loop to allow forms to submit
1436 | setTimeout(function () {
1437 | state == 'loadingText' ?
1438 | $el.addClass(d).attr(d, d) :
1439 | $el.removeClass(d).removeAttr(d)
1440 | }, 0)
1441 | }
1442 |
1443 | Button.prototype.toggle = function () {
1444 | var $parent = this.$element.closest('[data-toggle="buttons-radio"]')
1445 |
1446 | $parent && $parent
1447 | .find('.active')
1448 | .removeClass('active')
1449 |
1450 | this.$element.toggleClass('active')
1451 | }
1452 |
1453 |
1454 | /* BUTTON PLUGIN DEFINITION
1455 | * ======================== */
1456 |
1457 | var old = $.fn.button
1458 |
1459 | $.fn.button = function (option) {
1460 | return this.each(function () {
1461 | var $this = $(this)
1462 | , data = $this.data('button')
1463 | , options = typeof option == 'object' && option
1464 | if (!data) $this.data('button', (data = new Button(this, options)))
1465 | if (option == 'toggle') data.toggle()
1466 | else if (option) data.setState(option)
1467 | })
1468 | }
1469 |
1470 | $.fn.button.defaults = {
1471 | loadingText: 'loading...'
1472 | }
1473 |
1474 | $.fn.button.Constructor = Button
1475 |
1476 |
1477 | /* BUTTON NO CONFLICT
1478 | * ================== */
1479 |
1480 | $.fn.button.noConflict = function () {
1481 | $.fn.button = old
1482 | return this
1483 | }
1484 |
1485 |
1486 | /* BUTTON DATA-API
1487 | * =============== */
1488 |
1489 | $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) {
1490 | var $btn = $(e.target)
1491 | if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
1492 | $btn.button('toggle')
1493 | })
1494 |
1495 | }(window.jQuery);
1496 | /* =============================================================
1497 | * bootstrap-collapse.js v2.2.2
1498 | * http://twitter.github.com/bootstrap/javascript.html#collapse
1499 | * =============================================================
1500 | * Copyright 2012 Twitter, Inc.
1501 | *
1502 | * Licensed under the Apache License, Version 2.0 (the "License");
1503 | * you may not use this file except in compliance with the License.
1504 | * You may obtain a copy of the License at
1505 | *
1506 | * http://www.apache.org/licenses/LICENSE-2.0
1507 | *
1508 | * Unless required by applicable law or agreed to in writing, software
1509 | * distributed under the License is distributed on an "AS IS" BASIS,
1510 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1511 | * See the License for the specific language governing permissions and
1512 | * limitations under the License.
1513 | * ============================================================ */
1514 |
1515 |
1516 | !function ($) {
1517 |
1518 | "use strict"; // jshint ;_;
1519 |
1520 |
1521 | /* COLLAPSE PUBLIC CLASS DEFINITION
1522 | * ================================ */
1523 |
1524 | var Collapse = function (element, options) {
1525 | this.$element = $(element)
1526 | this.options = $.extend({}, $.fn.collapse.defaults, options)
1527 |
1528 | if (this.options.parent) {
1529 | this.$parent = $(this.options.parent)
1530 | }
1531 |
1532 | this.options.toggle && this.toggle()
1533 | }
1534 |
1535 | Collapse.prototype = {
1536 |
1537 | constructor: Collapse
1538 |
1539 | , dimension: function () {
1540 | var hasWidth = this.$element.hasClass('width')
1541 | return hasWidth ? 'width' : 'height'
1542 | }
1543 |
1544 | , show: function () {
1545 | var dimension
1546 | , scroll
1547 | , actives
1548 | , hasData
1549 |
1550 | if (this.transitioning) return
1551 |
1552 | dimension = this.dimension()
1553 | scroll = $.camelCase(['scroll', dimension].join('-'))
1554 | actives = this.$parent && this.$parent.find('> .accordion-group > .in')
1555 |
1556 | if (actives && actives.length) {
1557 | hasData = actives.data('collapse')
1558 | if (hasData && hasData.transitioning) return
1559 | actives.collapse('hide')
1560 | hasData || actives.data('collapse', null)
1561 | }
1562 |
1563 | this.$element[dimension](0)
1564 | this.transition('addClass', $.Event('show'), 'shown')
1565 | $.support.transition && this.$element[dimension](this.$element[0][scroll])
1566 | }
1567 |
1568 | , hide: function () {
1569 | var dimension
1570 | if (this.transitioning) return
1571 | dimension = this.dimension()
1572 | this.reset(this.$element[dimension]())
1573 | this.transition('removeClass', $.Event('hide'), 'hidden')
1574 | this.$element[dimension](0)
1575 | }
1576 |
1577 | , reset: function (size) {
1578 | var dimension = this.dimension()
1579 |
1580 | this.$element
1581 | .removeClass('collapse')
1582 | [dimension](size || 'auto')
1583 | [0].offsetWidth
1584 |
1585 | this.$element[size !== null ? 'addClass' : 'removeClass']('collapse')
1586 |
1587 | return this
1588 | }
1589 |
1590 | , transition: function (method, startEvent, completeEvent) {
1591 | var that = this
1592 | , complete = function () {
1593 | if (startEvent.type == 'show') that.reset()
1594 | that.transitioning = 0
1595 | that.$element.trigger(completeEvent)
1596 | }
1597 |
1598 | this.$element.trigger(startEvent)
1599 |
1600 | if (startEvent.isDefaultPrevented()) return
1601 |
1602 | this.transitioning = 1
1603 |
1604 | this.$element[method]('in')
1605 |
1606 | $.support.transition && this.$element.hasClass('collapse') ?
1607 | this.$element.one($.support.transition.end, complete) :
1608 | complete()
1609 | }
1610 |
1611 | , toggle: function () {
1612 | this[this.$element.hasClass('in') ? 'hide' : 'show']()
1613 | }
1614 |
1615 | }
1616 |
1617 |
1618 | /* COLLAPSE PLUGIN DEFINITION
1619 | * ========================== */
1620 |
1621 | var old = $.fn.collapse
1622 |
1623 | $.fn.collapse = function (option) {
1624 | return this.each(function () {
1625 | var $this = $(this)
1626 | , data = $this.data('collapse')
1627 | , options = typeof option == 'object' && option
1628 | if (!data) $this.data('collapse', (data = new Collapse(this, options)))
1629 | if (typeof option == 'string') data[option]()
1630 | })
1631 | }
1632 |
1633 | $.fn.collapse.defaults = {
1634 | toggle: true
1635 | }
1636 |
1637 | $.fn.collapse.Constructor = Collapse
1638 |
1639 |
1640 | /* COLLAPSE NO CONFLICT
1641 | * ==================== */
1642 |
1643 | $.fn.collapse.noConflict = function () {
1644 | $.fn.collapse = old
1645 | return this
1646 | }
1647 |
1648 |
1649 | /* COLLAPSE DATA-API
1650 | * ================= */
1651 |
1652 | $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) {
1653 | var $this = $(this), href
1654 | , target = $this.attr('data-target')
1655 | || e.preventDefault()
1656 | || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
1657 | , option = $(target).data('collapse') ? 'toggle' : $this.data()
1658 | $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
1659 | $(target).collapse(option)
1660 | })
1661 |
1662 | }(window.jQuery);
1663 | /* ==========================================================
1664 | * bootstrap-carousel.js v2.2.2
1665 | * http://twitter.github.com/bootstrap/javascript.html#carousel
1666 | * ==========================================================
1667 | * Copyright 2012 Twitter, Inc.
1668 | *
1669 | * Licensed under the Apache License, Version 2.0 (the "License");
1670 | * you may not use this file except in compliance with the License.
1671 | * You may obtain a copy of the License at
1672 | *
1673 | * http://www.apache.org/licenses/LICENSE-2.0
1674 | *
1675 | * Unless required by applicable law or agreed to in writing, software
1676 | * distributed under the License is distributed on an "AS IS" BASIS,
1677 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1678 | * See the License for the specific language governing permissions and
1679 | * limitations under the License.
1680 | * ========================================================== */
1681 |
1682 |
1683 | !function ($) {
1684 |
1685 | "use strict"; // jshint ;_;
1686 |
1687 |
1688 | /* CAROUSEL CLASS DEFINITION
1689 | * ========================= */
1690 |
1691 | var Carousel = function (element, options) {
1692 | this.$element = $(element)
1693 | this.options = options
1694 | this.options.pause == 'hover' && this.$element
1695 | .on('mouseenter', $.proxy(this.pause, this))
1696 | .on('mouseleave', $.proxy(this.cycle, this))
1697 | }
1698 |
1699 | Carousel.prototype = {
1700 |
1701 | cycle: function (e) {
1702 | if (!e) this.paused = false
1703 | this.options.interval
1704 | && !this.paused
1705 | && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
1706 | return this
1707 | }
1708 |
1709 | , to: function (pos) {
1710 | var $active = this.$element.find('.item.active')
1711 | , children = $active.parent().children()
1712 | , activePos = children.index($active)
1713 | , that = this
1714 |
1715 | if (pos > (children.length - 1) || pos < 0) return
1716 |
1717 | if (this.sliding) {
1718 | return this.$element.one('slid', function () {
1719 | that.to(pos)
1720 | })
1721 | }
1722 |
1723 | if (activePos == pos) {
1724 | return this.pause().cycle()
1725 | }
1726 |
1727 | return this.slide(pos > activePos ? 'next' : 'prev', $(children[pos]))
1728 | }
1729 |
1730 | , pause: function (e) {
1731 | if (!e) this.paused = true
1732 | if (this.$element.find('.next, .prev').length && $.support.transition.end) {
1733 | this.$element.trigger($.support.transition.end)
1734 | this.cycle()
1735 | }
1736 | clearInterval(this.interval)
1737 | this.interval = null
1738 | return this
1739 | }
1740 |
1741 | , next: function () {
1742 | if (this.sliding) return
1743 | return this.slide('next')
1744 | }
1745 |
1746 | , prev: function () {
1747 | if (this.sliding) return
1748 | return this.slide('prev')
1749 | }
1750 |
1751 | , slide: function (type, next) {
1752 | var $active = this.$element.find('.item.active')
1753 | , $next = next || $active[type]()
1754 | , isCycling = this.interval
1755 | , direction = type == 'next' ? 'left' : 'right'
1756 | , fallback = type == 'next' ? 'first' : 'last'
1757 | , that = this
1758 | , e
1759 |
1760 | this.sliding = true
1761 |
1762 | isCycling && this.pause()
1763 |
1764 | $next = $next.length ? $next : this.$element.find('.item')[fallback]()
1765 |
1766 | e = $.Event('slide', {
1767 | relatedTarget: $next[0]
1768 | })
1769 |
1770 | if ($next.hasClass('active')) return
1771 |
1772 | if ($.support.transition && this.$element.hasClass('slide')) {
1773 | this.$element.trigger(e)
1774 | if (e.isDefaultPrevented()) return
1775 | $next.addClass(type)
1776 | $next[0].offsetWidth // force reflow
1777 | $active.addClass(direction)
1778 | $next.addClass(direction)
1779 | this.$element.one($.support.transition.end, function () {
1780 | $next.removeClass([type, direction].join(' ')).addClass('active')
1781 | $active.removeClass(['active', direction].join(' '))
1782 | that.sliding = false
1783 | setTimeout(function () { that.$element.trigger('slid') }, 0)
1784 | })
1785 | } else {
1786 | this.$element.trigger(e)
1787 | if (e.isDefaultPrevented()) return
1788 | $active.removeClass('active')
1789 | $next.addClass('active')
1790 | this.sliding = false
1791 | this.$element.trigger('slid')
1792 | }
1793 |
1794 | isCycling && this.cycle()
1795 |
1796 | return this
1797 | }
1798 |
1799 | }
1800 |
1801 |
1802 | /* CAROUSEL PLUGIN DEFINITION
1803 | * ========================== */
1804 |
1805 | var old = $.fn.carousel
1806 |
1807 | $.fn.carousel = function (option) {
1808 | return this.each(function () {
1809 | var $this = $(this)
1810 | , data = $this.data('carousel')
1811 | , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option)
1812 | , action = typeof option == 'string' ? option : options.slide
1813 | if (!data) $this.data('carousel', (data = new Carousel(this, options)))
1814 | if (typeof option == 'number') data.to(option)
1815 | else if (action) data[action]()
1816 | else if (options.interval) data.cycle()
1817 | })
1818 | }
1819 |
1820 | $.fn.carousel.defaults = {
1821 | interval: 5000
1822 | , pause: 'hover'
1823 | }
1824 |
1825 | $.fn.carousel.Constructor = Carousel
1826 |
1827 |
1828 | /* CAROUSEL NO CONFLICT
1829 | * ==================== */
1830 |
1831 | $.fn.carousel.noConflict = function () {
1832 | $.fn.carousel = old
1833 | return this
1834 | }
1835 |
1836 | /* CAROUSEL DATA-API
1837 | * ================= */
1838 |
1839 | $(document).on('click.carousel.data-api', '[data-slide]', function (e) {
1840 | var $this = $(this), href
1841 | , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
1842 | , options = $.extend({}, $target.data(), $this.data())
1843 | $target.carousel(options)
1844 | e.preventDefault()
1845 | })
1846 |
1847 | }(window.jQuery);
1848 | /* =============================================================
1849 | * bootstrap-typeahead.js v2.2.2
1850 | * http://twitter.github.com/bootstrap/javascript.html#typeahead
1851 | * =============================================================
1852 | * Copyright 2012 Twitter, Inc.
1853 | *
1854 | * Licensed under the Apache License, Version 2.0 (the "License");
1855 | * you may not use this file except in compliance with the License.
1856 | * You may obtain a copy of the License at
1857 | *
1858 | * http://www.apache.org/licenses/LICENSE-2.0
1859 | *
1860 | * Unless required by applicable law or agreed to in writing, software
1861 | * distributed under the License is distributed on an "AS IS" BASIS,
1862 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1863 | * See the License for the specific language governing permissions and
1864 | * limitations under the License.
1865 | * ============================================================ */
1866 |
1867 |
1868 | !function($){
1869 |
1870 | "use strict"; // jshint ;_;
1871 |
1872 |
1873 | /* TYPEAHEAD PUBLIC CLASS DEFINITION
1874 | * ================================= */
1875 |
1876 | var Typeahead = function (element, options) {
1877 | this.$element = $(element)
1878 | this.options = $.extend({}, $.fn.typeahead.defaults, options)
1879 | this.matcher = this.options.matcher || this.matcher
1880 | this.sorter = this.options.sorter || this.sorter
1881 | this.highlighter = this.options.highlighter || this.highlighter
1882 | this.updater = this.options.updater || this.updater
1883 | this.source = this.options.source
1884 | this.$menu = $(this.options.menu)
1885 | this.shown = false
1886 | this.listen()
1887 | }
1888 |
1889 | Typeahead.prototype = {
1890 |
1891 | constructor: Typeahead
1892 |
1893 | , select: function () {
1894 | var val = this.$menu.find('.active').attr('data-value')
1895 | this.$element
1896 | .val(this.updater(val))
1897 | .change()
1898 | return this.hide()
1899 | }
1900 |
1901 | , updater: function (item) {
1902 | return item
1903 | }
1904 |
1905 | , show: function () {
1906 | var pos = $.extend({}, this.$element.position(), {
1907 | height: this.$element[0].offsetHeight
1908 | })
1909 |
1910 | this.$menu
1911 | .insertAfter(this.$element)
1912 | .css({
1913 | top: pos.top + pos.height
1914 | , left: pos.left
1915 | })
1916 | .show()
1917 |
1918 | this.shown = true
1919 | return this
1920 | }
1921 |
1922 | , hide: function () {
1923 | this.$menu.hide()
1924 | this.shown = false
1925 | return this
1926 | }
1927 |
1928 | , lookup: function (event) {
1929 | var items
1930 |
1931 | this.query = this.$element.val()
1932 |
1933 | if (!this.query || this.query.length < this.options.minLength) {
1934 | return this.shown ? this.hide() : this
1935 | }
1936 |
1937 | items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source
1938 |
1939 | return items ? this.process(items) : this
1940 | }
1941 |
1942 | , process: function (items) {
1943 | var that = this
1944 |
1945 | items = $.grep(items, function (item) {
1946 | return that.matcher(item)
1947 | })
1948 |
1949 | items = this.sorter(items)
1950 |
1951 | if (!items.length) {
1952 | return this.shown ? this.hide() : this
1953 | }
1954 |
1955 | return this.render(items.slice(0, this.options.items)).show()
1956 | }
1957 |
1958 | , matcher: function (item) {
1959 | return ~item.toLowerCase().indexOf(this.query.toLowerCase())
1960 | }
1961 |
1962 | , sorter: function (items) {
1963 | var beginswith = []
1964 | , caseSensitive = []
1965 | , caseInsensitive = []
1966 | , item
1967 |
1968 | while (item = items.shift()) {
1969 | if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
1970 | else if (~item.indexOf(this.query)) caseSensitive.push(item)
1971 | else caseInsensitive.push(item)
1972 | }
1973 |
1974 | return beginswith.concat(caseSensitive, caseInsensitive)
1975 | }
1976 |
1977 | , highlighter: function (item) {
1978 | var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
1979 | return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
1980 | return '' + match + ''
1981 | })
1982 | }
1983 |
1984 | , render: function (items) {
1985 | var that = this
1986 |
1987 | items = $(items).map(function (i, item) {
1988 | i = $(that.options.item).attr('data-value', item)
1989 | i.find('a').html(that.highlighter(item))
1990 | return i[0]
1991 | })
1992 |
1993 | items.first().addClass('active')
1994 | this.$menu.html(items)
1995 | return this
1996 | }
1997 |
1998 | , next: function (event) {
1999 | var active = this.$menu.find('.active').removeClass('active')
2000 | , next = active.next()
2001 |
2002 | if (!next.length) {
2003 | next = $(this.$menu.find('li')[0])
2004 | }
2005 |
2006 | next.addClass('active')
2007 | }
2008 |
2009 | , prev: function (event) {
2010 | var active = this.$menu.find('.active').removeClass('active')
2011 | , prev = active.prev()
2012 |
2013 | if (!prev.length) {
2014 | prev = this.$menu.find('li').last()
2015 | }
2016 |
2017 | prev.addClass('active')
2018 | }
2019 |
2020 | , listen: function () {
2021 | this.$element
2022 | .on('blur', $.proxy(this.blur, this))
2023 | .on('keypress', $.proxy(this.keypress, this))
2024 | .on('keyup', $.proxy(this.keyup, this))
2025 |
2026 | if (this.eventSupported('keydown')) {
2027 | this.$element.on('keydown', $.proxy(this.keydown, this))
2028 | }
2029 |
2030 | this.$menu
2031 | .on('click', $.proxy(this.click, this))
2032 | .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
2033 | }
2034 |
2035 | , eventSupported: function(eventName) {
2036 | var isSupported = eventName in this.$element
2037 | if (!isSupported) {
2038 | this.$element.setAttribute(eventName, 'return;')
2039 | isSupported = typeof this.$element[eventName] === 'function'
2040 | }
2041 | return isSupported
2042 | }
2043 |
2044 | , move: function (e) {
2045 | if (!this.shown) return
2046 |
2047 | switch(e.keyCode) {
2048 | case 9: // tab
2049 | case 13: // enter
2050 | case 27: // escape
2051 | e.preventDefault()
2052 | break
2053 |
2054 | case 38: // up arrow
2055 | e.preventDefault()
2056 | this.prev()
2057 | break
2058 |
2059 | case 40: // down arrow
2060 | e.preventDefault()
2061 | this.next()
2062 | break
2063 | }
2064 |
2065 | e.stopPropagation()
2066 | }
2067 |
2068 | , keydown: function (e) {
2069 | this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27])
2070 | this.move(e)
2071 | }
2072 |
2073 | , keypress: function (e) {
2074 | if (this.suppressKeyPressRepeat) return
2075 | this.move(e)
2076 | }
2077 |
2078 | , keyup: function (e) {
2079 | switch(e.keyCode) {
2080 | case 40: // down arrow
2081 | case 38: // up arrow
2082 | case 16: // shift
2083 | case 17: // ctrl
2084 | case 18: // alt
2085 | break
2086 |
2087 | case 9: // tab
2088 | case 13: // enter
2089 | if (!this.shown) return
2090 | this.select()
2091 | break
2092 |
2093 | case 27: // escape
2094 | if (!this.shown) return
2095 | this.hide()
2096 | break
2097 |
2098 | default:
2099 | this.lookup()
2100 | }
2101 |
2102 | e.stopPropagation()
2103 | e.preventDefault()
2104 | }
2105 |
2106 | , blur: function (e) {
2107 | var that = this
2108 | setTimeout(function () { that.hide() }, 150)
2109 | }
2110 |
2111 | , click: function (e) {
2112 | e.stopPropagation()
2113 | e.preventDefault()
2114 | this.select()
2115 | }
2116 |
2117 | , mouseenter: function (e) {
2118 | this.$menu.find('.active').removeClass('active')
2119 | $(e.currentTarget).addClass('active')
2120 | }
2121 |
2122 | }
2123 |
2124 |
2125 | /* TYPEAHEAD PLUGIN DEFINITION
2126 | * =========================== */
2127 |
2128 | var old = $.fn.typeahead
2129 |
2130 | $.fn.typeahead = function (option) {
2131 | return this.each(function () {
2132 | var $this = $(this)
2133 | , data = $this.data('typeahead')
2134 | , options = typeof option == 'object' && option
2135 | if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))
2136 | if (typeof option == 'string') data[option]()
2137 | })
2138 | }
2139 |
2140 | $.fn.typeahead.defaults = {
2141 | source: []
2142 | , items: 8
2143 | , menu: ''
2144 | , item: ''
2145 | , minLength: 1
2146 | }
2147 |
2148 | $.fn.typeahead.Constructor = Typeahead
2149 |
2150 |
2151 | /* TYPEAHEAD NO CONFLICT
2152 | * =================== */
2153 |
2154 | $.fn.typeahead.noConflict = function () {
2155 | $.fn.typeahead = old
2156 | return this
2157 | }
2158 |
2159 |
2160 | /* TYPEAHEAD DATA-API
2161 | * ================== */
2162 |
2163 | $(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
2164 | var $this = $(this)
2165 | if ($this.data('typeahead')) return
2166 | e.preventDefault()
2167 | $this.typeahead($this.data())
2168 | })
2169 |
2170 | }(window.jQuery);
2171 |
--------------------------------------------------------------------------------
/lib/jasmine-1.2.0/MIT.LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2008-2011 Pivotal Labs
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/lib/jasmine-1.2.0/jasmine-html.js:
--------------------------------------------------------------------------------
1 | jasmine.HtmlReporterHelpers = {};
2 |
3 | jasmine.HtmlReporterHelpers.createDom = function(type, attrs, childrenVarArgs) {
4 | var el = document.createElement(type);
5 |
6 | for (var i = 2; i < arguments.length; i++) {
7 | var child = arguments[i];
8 |
9 | if (typeof child === 'string') {
10 | el.appendChild(document.createTextNode(child));
11 | } else {
12 | if (child) {
13 | el.appendChild(child);
14 | }
15 | }
16 | }
17 |
18 | for (var attr in attrs) {
19 | if (attr == "className") {
20 | el[attr] = attrs[attr];
21 | } else {
22 | el.setAttribute(attr, attrs[attr]);
23 | }
24 | }
25 |
26 | return el;
27 | };
28 |
29 | jasmine.HtmlReporterHelpers.getSpecStatus = function(child) {
30 | var results = child.results();
31 | var status = results.passed() ? 'passed' : 'failed';
32 | if (results.skipped) {
33 | status = 'skipped';
34 | }
35 |
36 | return status;
37 | };
38 |
39 | jasmine.HtmlReporterHelpers.appendToSummary = function(child, childElement) {
40 | var parentDiv = this.dom.summary;
41 | var parentSuite = (typeof child.parentSuite == 'undefined') ? 'suite' : 'parentSuite';
42 | var parent = child[parentSuite];
43 |
44 | if (parent) {
45 | if (typeof this.views.suites[parent.id] == 'undefined') {
46 | this.views.suites[parent.id] = new jasmine.HtmlReporter.SuiteView(parent, this.dom, this.views);
47 | }
48 | parentDiv = this.views.suites[parent.id].element;
49 | }
50 |
51 | parentDiv.appendChild(childElement);
52 | };
53 |
54 |
55 | jasmine.HtmlReporterHelpers.addHelpers = function(ctor) {
56 | for(var fn in jasmine.HtmlReporterHelpers) {
57 | ctor.prototype[fn] = jasmine.HtmlReporterHelpers[fn];
58 | }
59 | };
60 |
61 | jasmine.HtmlReporter = function(_doc) {
62 | var self = this;
63 | var doc = _doc || window.document;
64 |
65 | var reporterView;
66 |
67 | var dom = {};
68 |
69 | // Jasmine Reporter Public Interface
70 | self.logRunningSpecs = false;
71 |
72 | self.reportRunnerStarting = function(runner) {
73 | var specs = runner.specs() || [];
74 |
75 | if (specs.length == 0) {
76 | return;
77 | }
78 |
79 | createReporterDom(runner.env.versionString());
80 | doc.body.appendChild(dom.reporter);
81 |
82 | reporterView = new jasmine.HtmlReporter.ReporterView(dom);
83 | reporterView.addSpecs(specs, self.specFilter);
84 | };
85 |
86 | self.reportRunnerResults = function(runner) {
87 | reporterView && reporterView.complete();
88 | };
89 |
90 | self.reportSuiteResults = function(suite) {
91 | reporterView.suiteComplete(suite);
92 | };
93 |
94 | self.reportSpecStarting = function(spec) {
95 | if (self.logRunningSpecs) {
96 | self.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
97 | }
98 | };
99 |
100 | self.reportSpecResults = function(spec) {
101 | reporterView.specComplete(spec);
102 | };
103 |
104 | self.log = function() {
105 | var console = jasmine.getGlobal().console;
106 | if (console && console.log) {
107 | if (console.log.apply) {
108 | console.log.apply(console, arguments);
109 | } else {
110 | console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
111 | }
112 | }
113 | };
114 |
115 | self.specFilter = function(spec) {
116 | if (!focusedSpecName()) {
117 | return true;
118 | }
119 |
120 | return spec.getFullName().indexOf(focusedSpecName()) === 0;
121 | };
122 |
123 | return self;
124 |
125 | function focusedSpecName() {
126 | var specName;
127 |
128 | (function memoizeFocusedSpec() {
129 | if (specName) {
130 | return;
131 | }
132 |
133 | var paramMap = [];
134 | var params = doc.location.search.substring(1).split('&');
135 |
136 | for (var i = 0; i < params.length; i++) {
137 | var p = params[i].split('=');
138 | paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
139 | }
140 |
141 | specName = paramMap.spec;
142 | })();
143 |
144 | return specName;
145 | }
146 |
147 | function createReporterDom(version) {
148 | dom.reporter = self.createDom('div', { id: 'HTMLReporter', className: 'jasmine_reporter' },
149 | dom.banner = self.createDom('div', { className: 'banner' },
150 | self.createDom('span', { className: 'title' }, "Jasmine "),
151 | self.createDom('span', { className: 'version' }, version)),
152 |
153 | dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}),
154 | dom.alert = self.createDom('div', {className: 'alert'}),
155 | dom.results = self.createDom('div', {className: 'results'},
156 | dom.summary = self.createDom('div', { className: 'summary' }),
157 | dom.details = self.createDom('div', { id: 'details' }))
158 | );
159 | }
160 | };
161 | jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);jasmine.HtmlReporter.ReporterView = function(dom) {
162 | this.startedAt = new Date();
163 | this.runningSpecCount = 0;
164 | this.completeSpecCount = 0;
165 | this.passedCount = 0;
166 | this.failedCount = 0;
167 | this.skippedCount = 0;
168 |
169 | this.createResultsMenu = function() {
170 | this.resultsMenu = this.createDom('span', {className: 'resultsMenu bar'},
171 | this.summaryMenuItem = this.createDom('a', {className: 'summaryMenuItem', href: "#"}, '0 specs'),
172 | ' | ',
173 | this.detailsMenuItem = this.createDom('a', {className: 'detailsMenuItem', href: "#"}, '0 failing'));
174 |
175 | this.summaryMenuItem.onclick = function() {
176 | dom.reporter.className = dom.reporter.className.replace(/ showDetails/g, '');
177 | };
178 |
179 | this.detailsMenuItem.onclick = function() {
180 | showDetails();
181 | };
182 | };
183 |
184 | this.addSpecs = function(specs, specFilter) {
185 | this.totalSpecCount = specs.length;
186 |
187 | this.views = {
188 | specs: {},
189 | suites: {}
190 | };
191 |
192 | for (var i = 0; i < specs.length; i++) {
193 | var spec = specs[i];
194 | this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom, this.views);
195 | if (specFilter(spec)) {
196 | this.runningSpecCount++;
197 | }
198 | }
199 | };
200 |
201 | this.specComplete = function(spec) {
202 | this.completeSpecCount++;
203 |
204 | if (isUndefined(this.views.specs[spec.id])) {
205 | this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom);
206 | }
207 |
208 | var specView = this.views.specs[spec.id];
209 |
210 | switch (specView.status()) {
211 | case 'passed':
212 | this.passedCount++;
213 | break;
214 |
215 | case 'failed':
216 | this.failedCount++;
217 | break;
218 |
219 | case 'skipped':
220 | this.skippedCount++;
221 | break;
222 | }
223 |
224 | specView.refresh();
225 | this.refresh();
226 | };
227 |
228 | this.suiteComplete = function(suite) {
229 | var suiteView = this.views.suites[suite.id];
230 | if (isUndefined(suiteView)) {
231 | return;
232 | }
233 | suiteView.refresh();
234 | };
235 |
236 | this.refresh = function() {
237 |
238 | if (isUndefined(this.resultsMenu)) {
239 | this.createResultsMenu();
240 | }
241 |
242 | // currently running UI
243 | if (isUndefined(this.runningAlert)) {
244 | this.runningAlert = this.createDom('a', {href: "?", className: "runningAlert bar"});
245 | dom.alert.appendChild(this.runningAlert);
246 | }
247 | this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount);
248 |
249 | // skipped specs UI
250 | if (isUndefined(this.skippedAlert)) {
251 | this.skippedAlert = this.createDom('a', {href: "?", className: "skippedAlert bar"});
252 | }
253 |
254 | this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
255 |
256 | if (this.skippedCount === 1 && isDefined(dom.alert)) {
257 | dom.alert.appendChild(this.skippedAlert);
258 | }
259 |
260 | // passing specs UI
261 | if (isUndefined(this.passedAlert)) {
262 | this.passedAlert = this.createDom('span', {href: "?", className: "passingAlert bar"});
263 | }
264 | this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount);
265 |
266 | // failing specs UI
267 | if (isUndefined(this.failedAlert)) {
268 | this.failedAlert = this.createDom('span', {href: "?", className: "failingAlert bar"});
269 | }
270 | this.failedAlert.innerHTML = "Failing " + specPluralizedFor(this.failedCount);
271 |
272 | if (this.failedCount === 1 && isDefined(dom.alert)) {
273 | dom.alert.appendChild(this.failedAlert);
274 | dom.alert.appendChild(this.resultsMenu);
275 | }
276 |
277 | // summary info
278 | this.summaryMenuItem.innerHTML = "" + specPluralizedFor(this.runningSpecCount);
279 | this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing";
280 | };
281 |
282 | this.complete = function() {
283 | dom.alert.removeChild(this.runningAlert);
284 |
285 | this.skippedAlert.innerHTML = "Ran " + this.runningSpecCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
286 |
287 | if (this.failedCount === 0) {
288 | dom.alert.appendChild(this.createDom('span', {className: 'passingAlert bar'}, "Passing " + specPluralizedFor(this.passedCount)));
289 | } else {
290 | showDetails();
291 | }
292 |
293 | dom.banner.appendChild(this.createDom('span', {className: 'duration'}, "finished in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"));
294 | };
295 |
296 | return this;
297 |
298 | function showDetails() {
299 | if (dom.reporter.className.search(/showDetails/) === -1) {
300 | dom.reporter.className += " showDetails";
301 | }
302 | }
303 |
304 | function isUndefined(obj) {
305 | return typeof obj === 'undefined';
306 | }
307 |
308 | function isDefined(obj) {
309 | return !isUndefined(obj);
310 | }
311 |
312 | function specPluralizedFor(count) {
313 | var str = count + " spec";
314 | if (count > 1) {
315 | str += "s"
316 | }
317 | return str;
318 | }
319 |
320 | };
321 |
322 | jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.ReporterView);
323 |
324 |
325 | jasmine.HtmlReporter.SpecView = function(spec, dom, views) {
326 | this.spec = spec;
327 | this.dom = dom;
328 | this.views = views;
329 |
330 | this.symbol = this.createDom('li', { className: 'pending' });
331 | this.dom.symbolSummary.appendChild(this.symbol);
332 |
333 | this.summary = this.createDom('div', { className: 'specSummary' },
334 | this.createDom('a', {
335 | className: 'description',
336 | href: '?spec=' + encodeURIComponent(this.spec.getFullName()),
337 | title: this.spec.getFullName()
338 | }, this.spec.description)
339 | );
340 |
341 | this.detail = this.createDom('div', { className: 'specDetail' },
342 | this.createDom('a', {
343 | className: 'description',
344 | href: '?spec=' + encodeURIComponent(this.spec.getFullName()),
345 | title: this.spec.getFullName()
346 | }, this.spec.getFullName())
347 | );
348 | };
349 |
350 | jasmine.HtmlReporter.SpecView.prototype.status = function() {
351 | return this.getSpecStatus(this.spec);
352 | };
353 |
354 | jasmine.HtmlReporter.SpecView.prototype.refresh = function() {
355 | this.symbol.className = this.status();
356 |
357 | switch (this.status()) {
358 | case 'skipped':
359 | break;
360 |
361 | case 'passed':
362 | this.appendSummaryToSuiteDiv();
363 | break;
364 |
365 | case 'failed':
366 | this.appendSummaryToSuiteDiv();
367 | this.appendFailureDetail();
368 | break;
369 | }
370 | };
371 |
372 | jasmine.HtmlReporter.SpecView.prototype.appendSummaryToSuiteDiv = function() {
373 | this.summary.className += ' ' + this.status();
374 | this.appendToSummary(this.spec, this.summary);
375 | };
376 |
377 | jasmine.HtmlReporter.SpecView.prototype.appendFailureDetail = function() {
378 | this.detail.className += ' ' + this.status();
379 |
380 | var resultItems = this.spec.results().getItems();
381 | var messagesDiv = this.createDom('div', { className: 'messages' });
382 |
383 | for (var i = 0; i < resultItems.length; i++) {
384 | var result = resultItems[i];
385 |
386 | if (result.type == 'log') {
387 | messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
388 | } else if (result.type == 'expect' && result.passed && !result.passed()) {
389 | messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
390 |
391 | if (result.trace.stack) {
392 | messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
393 | }
394 | }
395 | }
396 |
397 | if (messagesDiv.childNodes.length > 0) {
398 | this.detail.appendChild(messagesDiv);
399 | this.dom.details.appendChild(this.detail);
400 | }
401 | };
402 |
403 | jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);jasmine.HtmlReporter.SuiteView = function(suite, dom, views) {
404 | this.suite = suite;
405 | this.dom = dom;
406 | this.views = views;
407 |
408 | this.element = this.createDom('div', { className: 'suite' },
409 | this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(this.suite.getFullName()) }, this.suite.description)
410 | );
411 |
412 | this.appendToSummary(this.suite, this.element);
413 | };
414 |
415 | jasmine.HtmlReporter.SuiteView.prototype.status = function() {
416 | return this.getSpecStatus(this.suite);
417 | };
418 |
419 | jasmine.HtmlReporter.SuiteView.prototype.refresh = function() {
420 | this.element.className += " " + this.status();
421 | };
422 |
423 | jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SuiteView);
424 |
425 | /* @deprecated Use jasmine.HtmlReporter instead
426 | */
427 | jasmine.TrivialReporter = function(doc) {
428 | this.document = doc || document;
429 | this.suiteDivs = {};
430 | this.logRunningSpecs = false;
431 | };
432 |
433 | jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
434 | var el = document.createElement(type);
435 |
436 | for (var i = 2; i < arguments.length; i++) {
437 | var child = arguments[i];
438 |
439 | if (typeof child === 'string') {
440 | el.appendChild(document.createTextNode(child));
441 | } else {
442 | if (child) { el.appendChild(child); }
443 | }
444 | }
445 |
446 | for (var attr in attrs) {
447 | if (attr == "className") {
448 | el[attr] = attrs[attr];
449 | } else {
450 | el.setAttribute(attr, attrs[attr]);
451 | }
452 | }
453 |
454 | return el;
455 | };
456 |
457 | jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
458 | var showPassed, showSkipped;
459 |
460 | this.outerDiv = this.createDom('div', { id: 'TrivialReporter', className: 'jasmine_reporter' },
461 | this.createDom('div', { className: 'banner' },
462 | this.createDom('div', { className: 'logo' },
463 | this.createDom('span', { className: 'title' }, "Jasmine"),
464 | this.createDom('span', { className: 'version' }, runner.env.versionString())),
465 | this.createDom('div', { className: 'options' },
466 | "Show ",
467 | showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
468 | this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
469 | showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
470 | this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
471 | )
472 | ),
473 |
474 | this.runnerDiv = this.createDom('div', { className: 'runner running' },
475 | this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
476 | this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
477 | this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
478 | );
479 |
480 | this.document.body.appendChild(this.outerDiv);
481 |
482 | var suites = runner.suites();
483 | for (var i = 0; i < suites.length; i++) {
484 | var suite = suites[i];
485 | var suiteDiv = this.createDom('div', { className: 'suite' },
486 | this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
487 | this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
488 | this.suiteDivs[suite.id] = suiteDiv;
489 | var parentDiv = this.outerDiv;
490 | if (suite.parentSuite) {
491 | parentDiv = this.suiteDivs[suite.parentSuite.id];
492 | }
493 | parentDiv.appendChild(suiteDiv);
494 | }
495 |
496 | this.startedAt = new Date();
497 |
498 | var self = this;
499 | showPassed.onclick = function(evt) {
500 | if (showPassed.checked) {
501 | self.outerDiv.className += ' show-passed';
502 | } else {
503 | self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
504 | }
505 | };
506 |
507 | showSkipped.onclick = function(evt) {
508 | if (showSkipped.checked) {
509 | self.outerDiv.className += ' show-skipped';
510 | } else {
511 | self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
512 | }
513 | };
514 | };
515 |
516 | jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
517 | var results = runner.results();
518 | var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
519 | this.runnerDiv.setAttribute("class", className);
520 | //do it twice for IE
521 | this.runnerDiv.setAttribute("className", className);
522 | var specs = runner.specs();
523 | var specCount = 0;
524 | for (var i = 0; i < specs.length; i++) {
525 | if (this.specFilter(specs[i])) {
526 | specCount++;
527 | }
528 | }
529 | var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
530 | message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
531 | this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
532 |
533 | this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
534 | };
535 |
536 | jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
537 | var results = suite.results();
538 | var status = results.passed() ? 'passed' : 'failed';
539 | if (results.totalCount === 0) { // todo: change this to check results.skipped
540 | status = 'skipped';
541 | }
542 | this.suiteDivs[suite.id].className += " " + status;
543 | };
544 |
545 | jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
546 | if (this.logRunningSpecs) {
547 | this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
548 | }
549 | };
550 |
551 | jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
552 | var results = spec.results();
553 | var status = results.passed() ? 'passed' : 'failed';
554 | if (results.skipped) {
555 | status = 'skipped';
556 | }
557 | var specDiv = this.createDom('div', { className: 'spec ' + status },
558 | this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
559 | this.createDom('a', {
560 | className: 'description',
561 | href: '?spec=' + encodeURIComponent(spec.getFullName()),
562 | title: spec.getFullName()
563 | }, spec.description));
564 |
565 |
566 | var resultItems = results.getItems();
567 | var messagesDiv = this.createDom('div', { className: 'messages' });
568 | for (var i = 0; i < resultItems.length; i++) {
569 | var result = resultItems[i];
570 |
571 | if (result.type == 'log') {
572 | messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
573 | } else if (result.type == 'expect' && result.passed && !result.passed()) {
574 | messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
575 |
576 | if (result.trace.stack) {
577 | messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
578 | }
579 | }
580 | }
581 |
582 | if (messagesDiv.childNodes.length > 0) {
583 | specDiv.appendChild(messagesDiv);
584 | }
585 |
586 | this.suiteDivs[spec.suite.id].appendChild(specDiv);
587 | };
588 |
589 | jasmine.TrivialReporter.prototype.log = function() {
590 | var console = jasmine.getGlobal().console;
591 | if (console && console.log) {
592 | if (console.log.apply) {
593 | console.log.apply(console, arguments);
594 | } else {
595 | console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
596 | }
597 | }
598 | };
599 |
600 | jasmine.TrivialReporter.prototype.getLocation = function() {
601 | return this.document.location;
602 | };
603 |
604 | jasmine.TrivialReporter.prototype.specFilter = function(spec) {
605 | var paramMap = {};
606 | var params = this.getLocation().search.substring(1).split('&');
607 | for (var i = 0; i < params.length; i++) {
608 | var p = params[i].split('=');
609 | paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
610 | }
611 |
612 | if (!paramMap.spec) {
613 | return true;
614 | }
615 | return spec.getFullName().indexOf(paramMap.spec) === 0;
616 | };
617 |
--------------------------------------------------------------------------------
/lib/jasmine-1.2.0/jasmine.css:
--------------------------------------------------------------------------------
1 | body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
2 |
3 | #HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
4 | #HTMLReporter a { text-decoration: none; }
5 | #HTMLReporter a:hover { text-decoration: underline; }
6 | #HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; }
7 | #HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; }
8 | #HTMLReporter #jasmine_content { position: fixed; right: 100%; }
9 | #HTMLReporter .version { color: #aaaaaa; }
10 | #HTMLReporter .banner { margin-top: 14px; }
11 | #HTMLReporter .duration { color: #aaaaaa; float: right; }
12 | #HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; }
13 | #HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; }
14 | #HTMLReporter .symbolSummary li.passed { font-size: 14px; }
15 | #HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; }
16 | #HTMLReporter .symbolSummary li.failed { line-height: 9px; }
17 | #HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; }
18 | #HTMLReporter .symbolSummary li.skipped { font-size: 14px; }
19 | #HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; }
20 | #HTMLReporter .symbolSummary li.pending { line-height: 11px; }
21 | #HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; }
22 | #HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
23 | #HTMLReporter .runningAlert { background-color: #666666; }
24 | #HTMLReporter .skippedAlert { background-color: #aaaaaa; }
25 | #HTMLReporter .skippedAlert:first-child { background-color: #333333; }
26 | #HTMLReporter .skippedAlert:hover { text-decoration: none; color: white; text-decoration: underline; }
27 | #HTMLReporter .passingAlert { background-color: #a6b779; }
28 | #HTMLReporter .passingAlert:first-child { background-color: #5e7d00; }
29 | #HTMLReporter .failingAlert { background-color: #cf867e; }
30 | #HTMLReporter .failingAlert:first-child { background-color: #b03911; }
31 | #HTMLReporter .results { margin-top: 14px; }
32 | #HTMLReporter #details { display: none; }
33 | #HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; }
34 | #HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; }
35 | #HTMLReporter.showDetails .summaryMenuItem:hover { text-decoration: underline; }
36 | #HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; }
37 | #HTMLReporter.showDetails .summary { display: none; }
38 | #HTMLReporter.showDetails #details { display: block; }
39 | #HTMLReporter .summaryMenuItem { font-weight: bold; text-decoration: underline; }
40 | #HTMLReporter .summary { margin-top: 14px; }
41 | #HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; }
42 | #HTMLReporter .summary .specSummary.passed a { color: #5e7d00; }
43 | #HTMLReporter .summary .specSummary.failed a { color: #b03911; }
44 | #HTMLReporter .description + .suite { margin-top: 0; }
45 | #HTMLReporter .suite { margin-top: 14px; }
46 | #HTMLReporter .suite a { color: #333333; }
47 | #HTMLReporter #details .specDetail { margin-bottom: 28px; }
48 | #HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; }
49 | #HTMLReporter .resultMessage { padding-top: 14px; color: #333333; }
50 | #HTMLReporter .resultMessage span.result { display: block; }
51 | #HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; }
52 |
53 | #TrivialReporter { padding: 8px 13px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ }
54 | #TrivialReporter a:visited, #TrivialReporter a { color: #303; }
55 | #TrivialReporter a:hover, #TrivialReporter a:active { color: blue; }
56 | #TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; }
57 | #TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; }
58 | #TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; }
59 | #TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; }
60 | #TrivialReporter .runner.running { background-color: yellow; }
61 | #TrivialReporter .options { text-align: right; font-size: .8em; }
62 | #TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; }
63 | #TrivialReporter .suite .suite { margin: 5px; }
64 | #TrivialReporter .suite.passed { background-color: #dfd; }
65 | #TrivialReporter .suite.failed { background-color: #fdd; }
66 | #TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; }
67 | #TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; }
68 | #TrivialReporter .spec.failed { background-color: #fbb; border-color: red; }
69 | #TrivialReporter .spec.passed { background-color: #bfb; border-color: green; }
70 | #TrivialReporter .spec.skipped { background-color: #bbb; }
71 | #TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; }
72 | #TrivialReporter .passed { background-color: #cfc; display: none; }
73 | #TrivialReporter .failed { background-color: #fbb; }
74 | #TrivialReporter .skipped { color: #777; background-color: #eee; display: none; }
75 | #TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; }
76 | #TrivialReporter .resultMessage .mismatch { color: black; }
77 | #TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; }
78 | #TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; }
79 | #TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; }
80 | #TrivialReporter #jasmine_content { position: fixed; right: 100%; }
81 | #TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; }
82 |
--------------------------------------------------------------------------------