diff --git a/Makefile b/Makefile deleted file mode 100644 index 656c040..0000000 --- a/Makefile +++ /dev/null @@ -1,57 +0,0 @@ -# -# This file is part of the digital testament management program -# DigiProof. -# -# By accessing this software, DigiProof, you are duly informed -# of and agree to be bound by the conditions described below in this -# notice: -# -# This software product, DigiProof, is developed by T. Linden and -# copyrighted (C) 2013 by T. Linden, with all rights reserved. -# -# There is no charge for DigiProof software. You can redistribute -# it and/or modify it under the terms of the GNU General Public -# License, which is incorporated by reference herein. -# -# DigiProof is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, -# OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that -# the use of it will not infringe on any third party's intellectual -# property rights. -# -# You should have received a copy of the GNU General Public License -# along with DigiProof. Copies can also be obtained from: -# -# http://www.gnu.org/licenses/gpl-2.0.html -# -# or by writing to: -# -# Free Software Foundation, Inc. -# Inc., 51 Franklin Street, Fifth Floor -# Boston, MA 02110-1301 -# USA -# -# Or contact: -# -# "T. Linden" -# -# The sourcecode can be found on: -# -# https://codeberg.org/scip/digiproof -# - -ts != date +"%Y-%m-%d-%H%M%S" -dst = .backup/$(ts) -src = js *.html css -vers = js/libs/version.js - -all: backup - @echo var VERSION = \"$(ts)\" > $(vers); - ./mksingleton.pl prod index.html - ./mksingleton.pl dev index.html - -backup: - mkdir -p $(dst) - cp -pRP $(src) $(dst)/ - - - diff --git a/README.md b/README.md index 8ca3e18..b7422b7 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +> [!CAUTION] +> This software is now being maintained on [Codeberg](https://codeberg.org/scip/digiproof/). + + DigiProof ========= diff --git a/TODO b/TODO deleted file mode 100644 index e69de29..0000000 diff --git a/css/bootstrap-fileupload.css b/css/bootstrap-fileupload.css deleted file mode 100644 index eec90a7..0000000 --- a/css/bootstrap-fileupload.css +++ /dev/null @@ -1,132 +0,0 @@ -/*! - * Bootstrap v2.3.1-j6 - * - * Copyright 2012 Twitter, Inc - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world by @mdo and @fat, extended by @ArnoldDaniels. - */ -.clearfix { - *zoom: 1; -} -.clearfix:before, -.clearfix:after { - display: table; - content: ""; - line-height: 0; -} -.clearfix:after { - clear: both; -} -.hide-text { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} -.input-block-level { - display: block; - width: 100%; - min-height: 30px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -.btn-file { - overflow: hidden; - position: relative; - vertical-align: middle; -} -.btn-file > input { - position: absolute; - top: 0; - right: 0; - margin: 0; - opacity: 0; - filter: alpha(opacity=0); - transform: translate(-300px, 0) scale(4); - font-size: 23px; - direction: ltr; - cursor: pointer; -} -.fileupload { - margin-bottom: 9px; -} -.fileupload .uneditable-input { - display: inline-block; - margin-bottom: 0px; - vertical-align: middle; - cursor: text; -} -.fileupload .thumbnail { - overflow: hidden; - display: inline-block; - margin-bottom: 5px; - vertical-align: middle; - text-align: center; -} -.fileupload .thumbnail > img { - display: inline-block; - vertical-align: middle; - max-height: 100%; -} -.fileupload .btn { - vertical-align: middle; -} -.fileupload-exists .fileupload-new, -.fileupload-new .fileupload-exists { - display: none; -} -.fileupload-inline .fileupload-controls { - display: inline; -} -.fileupload-new .input-append .btn-file { - -webkit-border-radius: 0 3px 3px 0; - -moz-border-radius: 0 3px 3px 0; - border-radius: 0 3px 3px 0; -} -.thumbnail-borderless .thumbnail { - border: none; - padding: 0; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} -.fileupload-new.thumbnail-borderless .thumbnail { - border: 1px solid #ddd; -} -.control-group.warning .fileupload .uneditable-input { - color: #a47e3c; - border-color: #a47e3c; -} -.control-group.warning .fileupload .fileupload-preview { - color: #a47e3c; -} -.control-group.warning .fileupload .thumbnail { - border-color: #a47e3c; -} -.control-group.error .fileupload .uneditable-input { - color: #b94a48; - border-color: #b94a48; -} -.control-group.error .fileupload .fileupload-preview { - color: #b94a48; -} -.control-group.error .fileupload .thumbnail { - border-color: #b94a48; -} -.control-group.success .fileupload .uneditable-input { - color: #468847; - border-color: #468847; -} -.control-group.success .fileupload .fileupload-preview { - color: #468847; -} -.control-group.success .fileupload .thumbnail { - border-color: #468847; -} diff --git a/css/bootstrap-responsive.css b/css/bootstrap-responsive.css deleted file mode 100755 index fcd72f7..0000000 --- a/css/bootstrap-responsive.css +++ /dev/null @@ -1,1109 +0,0 @@ -/*! - * Bootstrap Responsive v2.3.1 - * - * Copyright 2012 Twitter, Inc - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world @twitter by @mdo and @fat. - */ - -.clearfix { - *zoom: 1; -} - -.clearfix:before, -.clearfix:after { - display: table; - line-height: 0; - content: ""; -} - -.clearfix:after { - clear: both; -} - -.hide-text { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} - -.input-block-level { - display: block; - width: 100%; - min-height: 30px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -@-ms-viewport { - width: device-width; -} - -.hidden { - display: none; - visibility: hidden; -} - -.visible-phone { - display: none !important; -} - -.visible-tablet { - display: none !important; -} - -.hidden-desktop { - display: none !important; -} - -.visible-desktop { - display: inherit !important; -} - -@media (min-width: 768px) and (max-width: 979px) { - .hidden-desktop { - display: inherit !important; - } - .visible-desktop { - display: none !important ; - } - .visible-tablet { - display: inherit !important; - } - .hidden-tablet { - display: none !important; - } -} - -@media (max-width: 767px) { - .hidden-desktop { - display: inherit !important; - } - .visible-desktop { - display: none !important; - } - .visible-phone { - display: inherit !important; - } - .hidden-phone { - display: none !important; - } -} - -.visible-print { - display: none !important; -} - -@media print { - .visible-print { - display: inherit !important; - } - .hidden-print { - display: none !important; - } -} - -@media (min-width: 1200px) { - .row { - margin-left: -30px; - *zoom: 1; - } - .row:before, - .row:after { - display: table; - line-height: 0; - content: ""; - } - .row:after { - clear: both; - } - [class*="span"] { - float: left; - min-height: 1px; - margin-left: 30px; - } - .container, - .navbar-static-top .container, - .navbar-fixed-top .container, - .navbar-fixed-bottom .container { - width: 1170px; - } - .span12 { - width: 1170px; - } - .span11 { - width: 1070px; - } - .span10 { - width: 970px; - } - .span9 { - width: 870px; - } - .span8 { - width: 770px; - } - .span7 { - width: 670px; - } - .span6 { - width: 570px; - } - .span5 { - width: 470px; - } - .span4 { - width: 370px; - } - .span3 { - width: 270px; - } - .span2 { - width: 170px; - } - .span1 { - width: 70px; - } - .offset12 { - margin-left: 1230px; - } - .offset11 { - margin-left: 1130px; - } - .offset10 { - margin-left: 1030px; - } - .offset9 { - margin-left: 930px; - } - .offset8 { - margin-left: 830px; - } - .offset7 { - margin-left: 730px; - } - .offset6 { - margin-left: 630px; - } - .offset5 { - margin-left: 530px; - } - .offset4 { - margin-left: 430px; - } - .offset3 { - margin-left: 330px; - } - .offset2 { - margin-left: 230px; - } - .offset1 { - margin-left: 130px; - } - .row-fluid { - width: 100%; - *zoom: 1; - } - .row-fluid:before, - .row-fluid:after { - display: table; - line-height: 0; - content: ""; - } - .row-fluid:after { - clear: both; - } - .row-fluid [class*="span"] { - display: block; - float: left; - width: 100%; - min-height: 30px; - margin-left: 2.564102564102564%; - *margin-left: 2.5109110747408616%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - } - .row-fluid [class*="span"]:first-child { - margin-left: 0; - } - .row-fluid .controls-row [class*="span"] + [class*="span"] { - margin-left: 2.564102564102564%; - } - .row-fluid .span12 { - width: 100%; - *width: 99.94680851063829%; - } - .row-fluid .span11 { - width: 91.45299145299145%; - *width: 91.39979996362975%; - } - .row-fluid .span10 { - width: 82.90598290598291%; - *width: 82.8527914166212%; - } - .row-fluid .span9 { - width: 74.35897435897436%; - *width: 74.30578286961266%; - } - .row-fluid .span8 { - width: 65.81196581196582%; - *width: 65.75877432260411%; - } - .row-fluid .span7 { - width: 57.26495726495726%; - *width: 57.21176577559556%; - } - .row-fluid .span6 { - width: 48.717948717948715%; - *width: 48.664757228587014%; - } - .row-fluid .span5 { - width: 40.17094017094017%; - *width: 40.11774868157847%; - } - .row-fluid .span4 { - width: 31.623931623931625%; - *width: 31.570740134569924%; - } - .row-fluid .span3 { - width: 23.076923076923077%; - *width: 23.023731587561375%; - } - .row-fluid .span2 { - width: 14.52991452991453%; - *width: 14.476723040552828%; - } - .row-fluid .span1 { - width: 5.982905982905983%; - *width: 5.929714493544281%; - } - .row-fluid .offset12 { - margin-left: 105.12820512820512%; - *margin-left: 105.02182214948171%; - } - .row-fluid .offset12:first-child { - margin-left: 102.56410256410257%; - *margin-left: 102.45771958537915%; - } - .row-fluid .offset11 { - margin-left: 96.58119658119658%; - *margin-left: 96.47481360247316%; - } - .row-fluid .offset11:first-child { - margin-left: 94.01709401709402%; - *margin-left: 93.91071103837061%; - } - .row-fluid .offset10 { - margin-left: 88.03418803418803%; - *margin-left: 87.92780505546462%; - } - .row-fluid .offset10:first-child { - margin-left: 85.47008547008548%; - *margin-left: 85.36370249136206%; - } - .row-fluid .offset9 { - margin-left: 79.48717948717949%; - *margin-left: 79.38079650845607%; - } - .row-fluid .offset9:first-child { - margin-left: 76.92307692307693%; - *margin-left: 76.81669394435352%; - } - .row-fluid .offset8 { - margin-left: 70.94017094017094%; - *margin-left: 70.83378796144753%; - } - .row-fluid .offset8:first-child { - margin-left: 68.37606837606839%; - *margin-left: 68.26968539734497%; - } - .row-fluid .offset7 { - margin-left: 62.393162393162385%; - *margin-left: 62.28677941443899%; - } - .row-fluid .offset7:first-child { - margin-left: 59.82905982905982%; - *margin-left: 59.72267685033642%; - } - .row-fluid .offset6 { - margin-left: 53.84615384615384%; - *margin-left: 53.739770867430444%; - } - .row-fluid .offset6:first-child { - margin-left: 51.28205128205128%; - *margin-left: 51.175668303327875%; - } - .row-fluid .offset5 { - margin-left: 45.299145299145295%; - *margin-left: 45.1927623204219%; - } - .row-fluid .offset5:first-child { - margin-left: 42.73504273504273%; - *margin-left: 42.62865975631933%; - } - .row-fluid .offset4 { - margin-left: 36.75213675213675%; - *margin-left: 36.645753773413354%; - } - .row-fluid .offset4:first-child { - margin-left: 34.18803418803419%; - *margin-left: 34.081651209310785%; - } - .row-fluid .offset3 { - margin-left: 28.205128205128204%; - *margin-left: 28.0987452264048%; - } - .row-fluid .offset3:first-child { - margin-left: 25.641025641025642%; - *margin-left: 25.53464266230224%; - } - .row-fluid .offset2 { - margin-left: 19.65811965811966%; - *margin-left: 19.551736679396257%; - } - .row-fluid .offset2:first-child { - margin-left: 17.094017094017094%; - *margin-left: 16.98763411529369%; - } - .row-fluid .offset1 { - margin-left: 11.11111111111111%; - *margin-left: 11.004728132387708%; - } - .row-fluid .offset1:first-child { - margin-left: 8.547008547008547%; - *margin-left: 8.440625568285142%; - } - input, - textarea, - .uneditable-input { - margin-left: 0; - } - .controls-row [class*="span"] + [class*="span"] { - margin-left: 30px; - } - input.span12, - textarea.span12, - .uneditable-input.span12 { - width: 1156px; - } - input.span11, - textarea.span11, - .uneditable-input.span11 { - width: 1056px; - } - input.span10, - textarea.span10, - .uneditable-input.span10 { - width: 956px; - } - input.span9, - textarea.span9, - .uneditable-input.span9 { - width: 856px; - } - input.span8, - textarea.span8, - .uneditable-input.span8 { - width: 756px; - } - input.span7, - textarea.span7, - .uneditable-input.span7 { - width: 656px; - } - input.span6, - textarea.span6, - .uneditable-input.span6 { - width: 556px; - } - input.span5, - textarea.span5, - .uneditable-input.span5 { - width: 456px; - } - input.span4, - textarea.span4, - .uneditable-input.span4 { - width: 356px; - } - input.span3, - textarea.span3, - .uneditable-input.span3 { - width: 256px; - } - input.span2, - textarea.span2, - .uneditable-input.span2 { - width: 156px; - } - input.span1, - textarea.span1, - .uneditable-input.span1 { - width: 56px; - } - .thumbnails { - margin-left: -30px; - } - .thumbnails > li { - margin-left: 30px; - } - .row-fluid .thumbnails { - margin-left: 0; - } -} - -@media (min-width: 768px) and (max-width: 979px) { - .row { - margin-left: -20px; - *zoom: 1; - } - .row:before, - .row:after { - display: table; - line-height: 0; - content: ""; - } - .row:after { - clear: both; - } - [class*="span"] { - float: left; - min-height: 1px; - margin-left: 20px; - } - .container, - .navbar-static-top .container, - .navbar-fixed-top .container, - .navbar-fixed-bottom .container { - width: 724px; - } - .span12 { - width: 724px; - } - .span11 { - width: 662px; - } - .span10 { - width: 600px; - } - .span9 { - width: 538px; - } - .span8 { - width: 476px; - } - .span7 { - width: 414px; - } - .span6 { - width: 352px; - } - .span5 { - width: 290px; - } - .span4 { - width: 228px; - } - .span3 { - width: 166px; - } - .span2 { - width: 104px; - } - .span1 { - width: 42px; - } - .offset12 { - margin-left: 764px; - } - .offset11 { - margin-left: 702px; - } - .offset10 { - margin-left: 640px; - } - .offset9 { - margin-left: 578px; - } - .offset8 { - margin-left: 516px; - } - .offset7 { - margin-left: 454px; - } - .offset6 { - margin-left: 392px; - } - .offset5 { - margin-left: 330px; - } - .offset4 { - margin-left: 268px; - } - .offset3 { - margin-left: 206px; - } - .offset2 { - margin-left: 144px; - } - .offset1 { - margin-left: 82px; - } - .row-fluid { - width: 100%; - *zoom: 1; - } - .row-fluid:before, - .row-fluid:after { - display: table; - line-height: 0; - content: ""; - } - .row-fluid:after { - clear: both; - } - .row-fluid [class*="span"] { - display: block; - float: left; - width: 100%; - min-height: 30px; - margin-left: 2.7624309392265194%; - *margin-left: 2.709239449864817%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - } - .row-fluid [class*="span"]:first-child { - margin-left: 0; - } - .row-fluid .controls-row [class*="span"] + [class*="span"] { - margin-left: 2.7624309392265194%; - } - .row-fluid .span12 { - width: 100%; - *width: 99.94680851063829%; - } - .row-fluid .span11 { - width: 91.43646408839778%; - *width: 91.38327259903608%; - } - .row-fluid .span10 { - width: 82.87292817679558%; - *width: 82.81973668743387%; - } - .row-fluid .span9 { - width: 74.30939226519337%; - *width: 74.25620077583166%; - } - .row-fluid .span8 { - width: 65.74585635359117%; - *width: 65.69266486422946%; - } - .row-fluid .span7 { - width: 57.18232044198895%; - *width: 57.12912895262725%; - } - .row-fluid .span6 { - width: 48.61878453038674%; - *width: 48.56559304102504%; - } - .row-fluid .span5 { - width: 40.05524861878453%; - *width: 40.00205712942283%; - } - .row-fluid .span4 { - width: 31.491712707182323%; - *width: 31.43852121782062%; - } - .row-fluid .span3 { - width: 22.92817679558011%; - *width: 22.87498530621841%; - } - .row-fluid .span2 { - width: 14.3646408839779%; - *width: 14.311449394616199%; - } - .row-fluid .span1 { - width: 5.801104972375691%; - *width: 5.747913483013988%; - } - .row-fluid .offset12 { - margin-left: 105.52486187845304%; - *margin-left: 105.41847889972962%; - } - .row-fluid .offset12:first-child { - margin-left: 102.76243093922652%; - *margin-left: 102.6560479605031%; - } - .row-fluid .offset11 { - margin-left: 96.96132596685082%; - *margin-left: 96.8549429881274%; - } - .row-fluid .offset11:first-child { - margin-left: 94.1988950276243%; - *margin-left: 94.09251204890089%; - } - .row-fluid .offset10 { - margin-left: 88.39779005524862%; - *margin-left: 88.2914070765252%; - } - .row-fluid .offset10:first-child { - margin-left: 85.6353591160221%; - *margin-left: 85.52897613729868%; - } - .row-fluid .offset9 { - margin-left: 79.8342541436464%; - *margin-left: 79.72787116492299%; - } - .row-fluid .offset9:first-child { - margin-left: 77.07182320441989%; - *margin-left: 76.96544022569647%; - } - .row-fluid .offset8 { - margin-left: 71.2707182320442%; - *margin-left: 71.16433525332079%; - } - .row-fluid .offset8:first-child { - margin-left: 68.50828729281768%; - *margin-left: 68.40190431409427%; - } - .row-fluid .offset7 { - margin-left: 62.70718232044199%; - *margin-left: 62.600799341718584%; - } - .row-fluid .offset7:first-child { - margin-left: 59.94475138121547%; - *margin-left: 59.838368402492065%; - } - .row-fluid .offset6 { - margin-left: 54.14364640883978%; - *margin-left: 54.037263430116376%; - } - .row-fluid .offset6:first-child { - margin-left: 51.38121546961326%; - *margin-left: 51.27483249088986%; - } - .row-fluid .offset5 { - margin-left: 45.58011049723757%; - *margin-left: 45.47372751851417%; - } - .row-fluid .offset5:first-child { - margin-left: 42.81767955801105%; - *margin-left: 42.71129657928765%; - } - .row-fluid .offset4 { - margin-left: 37.01657458563536%; - *margin-left: 36.91019160691196%; - } - .row-fluid .offset4:first-child { - margin-left: 34.25414364640884%; - *margin-left: 34.14776066768544%; - } - .row-fluid .offset3 { - margin-left: 28.45303867403315%; - *margin-left: 28.346655695309746%; - } - .row-fluid .offset3:first-child { - margin-left: 25.69060773480663%; - *margin-left: 25.584224756083227%; - } - .row-fluid .offset2 { - margin-left: 19.88950276243094%; - *margin-left: 19.783119783707537%; - } - .row-fluid .offset2:first-child { - margin-left: 17.12707182320442%; - *margin-left: 17.02068884448102%; - } - .row-fluid .offset1 { - margin-left: 11.32596685082873%; - *margin-left: 11.219583872105325%; - } - .row-fluid .offset1:first-child { - margin-left: 8.56353591160221%; - *margin-left: 8.457152932878806%; - } - input, - textarea, - .uneditable-input { - margin-left: 0; - } - .controls-row [class*="span"] + [class*="span"] { - margin-left: 20px; - } - input.span12, - textarea.span12, - .uneditable-input.span12 { - width: 710px; - } - input.span11, - textarea.span11, - .uneditable-input.span11 { - width: 648px; - } - input.span10, - textarea.span10, - .uneditable-input.span10 { - width: 586px; - } - input.span9, - textarea.span9, - .uneditable-input.span9 { - width: 524px; - } - input.span8, - textarea.span8, - .uneditable-input.span8 { - width: 462px; - } - input.span7, - textarea.span7, - .uneditable-input.span7 { - width: 400px; - } - input.span6, - textarea.span6, - .uneditable-input.span6 { - width: 338px; - } - input.span5, - textarea.span5, - .uneditable-input.span5 { - width: 276px; - } - input.span4, - textarea.span4, - .uneditable-input.span4 { - width: 214px; - } - input.span3, - textarea.span3, - .uneditable-input.span3 { - width: 152px; - } - input.span2, - textarea.span2, - .uneditable-input.span2 { - width: 90px; - } - input.span1, - textarea.span1, - .uneditable-input.span1 { - width: 28px; - } -} - -@media (max-width: 767px) { - body { - padding-right: 20px; - padding-left: 20px; - } - .navbar-fixed-top, - .navbar-fixed-bottom, - .navbar-static-top { - margin-right: -20px; - margin-left: -20px; - } - .container-fluid { - padding: 0; - } - .dl-horizontal dt { - float: none; - width: auto; - clear: none; - text-align: left; - } - .dl-horizontal dd { - margin-left: 0; - } - .container { - width: auto; - } - .row-fluid { - width: 100%; - } - .row, - .thumbnails { - margin-left: 0; - } - .thumbnails > li { - float: none; - margin-left: 0; - } - [class*="span"], - .uneditable-input[class*="span"], - .row-fluid [class*="span"] { - display: block; - float: none; - width: 100%; - margin-left: 0; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - } - .span12, - .row-fluid .span12 { - width: 100%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - } - .row-fluid [class*="offset"]:first-child { - margin-left: 0; - } - .input-large, - .input-xlarge, - .input-xxlarge, - input[class*="span"], - select[class*="span"], - textarea[class*="span"], - .uneditable-input { - display: block; - width: 100%; - min-height: 30px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - } - .input-prepend input, - .input-append input, - .input-prepend input[class*="span"], - .input-append input[class*="span"] { - display: inline-block; - width: auto; - } - .controls-row [class*="span"] + [class*="span"] { - margin-left: 0; - } - .modal { - position: fixed; - top: 20px; - right: 20px; - left: 20px; - width: auto; - margin: 0; - } - .modal.fade { - top: -100px; - } - .modal.fade.in { - top: 20px; - } -} - -@media (max-width: 480px) { - .nav-collapse { - -webkit-transform: translate3d(0, 0, 0); - } - .page-header h1 small { - display: block; - line-height: 20px; - } - input[type="checkbox"], - input[type="radio"] { - border: 1px solid #ccc; - } - .form-horizontal .control-label { - float: none; - width: auto; - padding-top: 0; - text-align: left; - } - .form-horizontal .controls { - margin-left: 0; - } - .form-horizontal .control-list { - padding-top: 0; - } - .form-horizontal .form-actions { - padding-right: 10px; - padding-left: 10px; - } - .media .pull-left, - .media .pull-right { - display: block; - float: none; - margin-bottom: 10px; - } - .media-object { - margin-right: 0; - margin-left: 0; - } - .modal { - top: 10px; - right: 10px; - left: 10px; - } - .modal-header .close { - padding: 10px; - margin: -10px; - } - .carousel-caption { - position: static; - } -} - -@media (max-width: 979px) { - body { - padding-top: 0; - } - .navbar-fixed-top, - .navbar-fixed-bottom { - position: static; - } - .navbar-fixed-top { - margin-bottom: 20px; - } - .navbar-fixed-bottom { - margin-top: 20px; - } - .navbar-fixed-top .navbar-inner, - .navbar-fixed-bottom .navbar-inner { - padding: 5px; - } - .navbar .container { - width: auto; - padding: 0; - } - .navbar .brand { - padding-right: 10px; - padding-left: 10px; - margin: 0 0 0 -5px; - } - .nav-collapse { - clear: both; - } - .nav-collapse .nav { - float: none; - margin: 0 0 10px; - } - .nav-collapse .nav > li { - float: none; - } - .nav-collapse .nav > li > a { - margin-bottom: 2px; - } - .nav-collapse .nav > .divider-vertical { - display: none; - } - .nav-collapse .nav .nav-header { - color: #777777; - text-shadow: none; - } - .nav-collapse .nav > li > a, - .nav-collapse .dropdown-menu a { - padding: 9px 15px; - font-weight: bold; - color: #777777; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - } - .nav-collapse .btn { - padding: 4px 10px 4px; - font-weight: normal; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - } - .nav-collapse .dropdown-menu li + li a { - margin-bottom: 2px; - } - .nav-collapse .nav > li > a:hover, - .nav-collapse .nav > li > a:focus, - .nav-collapse .dropdown-menu a:hover, - .nav-collapse .dropdown-menu a:focus { - background-color: #f2f2f2; - } - .navbar-inverse .nav-collapse .nav > li > a, - .navbar-inverse .nav-collapse .dropdown-menu a { - color: #999999; - } - .navbar-inverse .nav-collapse .nav > li > a:hover, - .navbar-inverse .nav-collapse .nav > li > a:focus, - .navbar-inverse .nav-collapse .dropdown-menu a:hover, - .navbar-inverse .nav-collapse .dropdown-menu a:focus { - background-color: #111111; - } - .nav-collapse.in .btn-group { - padding: 0; - margin-top: 5px; - } - .nav-collapse .dropdown-menu { - position: static; - top: auto; - left: auto; - display: none; - float: none; - max-width: none; - padding: 0; - margin: 0 15px; - background-color: transparent; - border: none; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; - } - .nav-collapse .open > .dropdown-menu { - display: block; - } - .nav-collapse .dropdown-menu:before, - .nav-collapse .dropdown-menu:after { - display: none; - } - .nav-collapse .dropdown-menu .divider { - display: none; - } - .nav-collapse .nav > li > .dropdown-menu:before, - .nav-collapse .nav > li > .dropdown-menu:after { - display: none; - } - .nav-collapse .navbar-form, - .nav-collapse .navbar-search { - float: none; - padding: 10px 15px; - margin: 10px 0; - border-top: 1px solid #f2f2f2; - border-bottom: 1px solid #f2f2f2; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); - } - .navbar-inverse .nav-collapse .navbar-form, - .navbar-inverse .nav-collapse .navbar-search { - border-top-color: #111111; - border-bottom-color: #111111; - } - .navbar .nav-collapse .nav.pull-right { - float: none; - margin-left: 0; - } - .nav-collapse, - .nav-collapse.collapse { - height: 0; - overflow: hidden; - } - .navbar .btn-navbar { - display: block; - } - .navbar-static .navbar-inner { - padding-right: 10px; - padding-left: 10px; - } -} - -@media (min-width: 980px) { - .nav-collapse.collapse { - height: auto !important; - overflow: visible !important; - } -} diff --git a/css/bootstrap.css b/css/bootstrap.css deleted file mode 100755 index e103b63..0000000 --- a/css/bootstrap.css +++ /dev/null @@ -1,6160 +0,0 @@ -/*! - * Bootstrap v2.3.1 - * - * Copyright 2012 Twitter, Inc - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world @twitter by @mdo and @fat. - */ - -.clearfix { - *zoom: 1; -} - -.clearfix:before, -.clearfix:after { - display: table; - line-height: 0; - content: ""; -} - -.clearfix:after { - clear: both; -} - -.hide-text { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} - -.input-block-level { - display: block; - width: 100%; - min-height: 30px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -nav, -section { - display: block; -} - -audio, -canvas, -video { - display: inline-block; - *display: inline; - *zoom: 1; -} - -audio:not([controls]) { - display: none; -} - -html { - font-size: 100%; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} - -a:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -a:hover, -a:active { - outline: 0; -} - -sub, -sup { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; -} - -sup { - top: -0.5em; -} - -sub { - bottom: -0.25em; -} - -img { - width: auto\9; - height: auto; - max-width: 100%; - vertical-align: middle; - border: 0; - -ms-interpolation-mode: bicubic; -} - -#map_canvas img, -.google-maps img { - max-width: none; -} - -button, -input, -select, -textarea { - margin: 0; - font-size: 100%; - vertical-align: middle; -} - -button, -input { - *overflow: visible; - line-height: normal; -} - -button::-moz-focus-inner, -input::-moz-focus-inner { - padding: 0; - border: 0; -} - -button, -html input[type="button"], -input[type="reset"], -input[type="submit"] { - cursor: pointer; - -webkit-appearance: button; -} - -label, -select, -button, -input[type="button"], -input[type="reset"], -input[type="submit"], -input[type="radio"], -input[type="checkbox"] { - cursor: pointer; -} - -input[type="search"] { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; - -webkit-appearance: textfield; -} - -input[type="search"]::-webkit-search-decoration, -input[type="search"]::-webkit-search-cancel-button { - -webkit-appearance: none; -} - -textarea { - overflow: auto; - vertical-align: top; -} - -@media print { - * { - color: #000 !important; - text-shadow: none !important; - background: transparent !important; - box-shadow: none !important; - } - a, - a:visited { - text-decoration: underline; - } - a[href]:after { - content: " (" attr(href) ")"; - } - abbr[title]:after { - content: " (" attr(title) ")"; - } - .ir a:after, - a[href^="javascript:"]:after, - a[href^="#"]:after { - content: ""; - } - pre, - blockquote { - border: 1px solid #999; - page-break-inside: avoid; - } - thead { - display: table-header-group; - } - tr, - img { - page-break-inside: avoid; - } - img { - max-width: 100% !important; - } - @page { - margin: 0.5cm; - } - p, - h2, - h3 { - orphans: 3; - widows: 3; - } - h2, - h3 { - page-break-after: avoid; - } -} - -body { - margin: 0; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 20px; - color: #333333; - background-color: #ffffff; -} - -a { - color: #0088cc; - text-decoration: none; -} - -a:hover, -a:focus { - color: #005580; - text-decoration: underline; -} - -.img-rounded { - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.img-polaroid { - padding: 4px; - background-color: #fff; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -} - -.img-circle { - -webkit-border-radius: 500px; - -moz-border-radius: 500px; - border-radius: 500px; -} - -.row { - margin-left: -20px; - *zoom: 1; -} - -.row:before, -.row:after { - display: table; - line-height: 0; - content: ""; -} - -.row:after { - clear: both; -} - -[class*="span"] { - float: left; - min-height: 1px; - margin-left: 20px; -} - -.container, -.navbar-static-top .container, -.navbar-fixed-top .container, -.navbar-fixed-bottom .container { - width: 940px; -} - -.span12 { - width: 940px; -} - -.span11 { - width: 860px; -} - -.span10 { - width: 780px; -} - -.span9 { - width: 700px; -} - -.span8 { - width: 620px; -} - -.span7 { - width: 540px; -} - -.span6 { - width: 460px; -} - -.span5 { - width: 380px; -} - -.span4 { - width: 300px; -} - -.span3 { - width: 220px; -} - -.span2 { - width: 140px; -} - -.span1 { - width: 60px; -} - -.offset12 { - margin-left: 980px; -} - -.offset11 { - margin-left: 900px; -} - -.offset10 { - margin-left: 820px; -} - -.offset9 { - margin-left: 740px; -} - -.offset8 { - margin-left: 660px; -} - -.offset7 { - margin-left: 580px; -} - -.offset6 { - margin-left: 500px; -} - -.offset5 { - margin-left: 420px; -} - -.offset4 { - margin-left: 340px; -} - -.offset3 { - margin-left: 260px; -} - -.offset2 { - margin-left: 180px; -} - -.offset1 { - margin-left: 100px; -} - -.row-fluid { - width: 100%; - *zoom: 1; -} - -.row-fluid:before, -.row-fluid:after { - display: table; - line-height: 0; - content: ""; -} - -.row-fluid:after { - clear: both; -} - -.row-fluid [class*="span"] { - display: block; - float: left; - width: 100%; - min-height: 30px; - margin-left: 2.127659574468085%; - *margin-left: 2.074468085106383%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.row-fluid [class*="span"]:first-child { - margin-left: 0; -} - -.row-fluid .controls-row [class*="span"] + [class*="span"] { - margin-left: 2.127659574468085%; -} - -.row-fluid .span12 { - width: 100%; - *width: 99.94680851063829%; -} - -.row-fluid .span11 { - width: 91.48936170212765%; - *width: 91.43617021276594%; -} - -.row-fluid .span10 { - width: 82.97872340425532%; - *width: 82.92553191489361%; -} - -.row-fluid .span9 { - width: 74.46808510638297%; - *width: 74.41489361702126%; -} - -.row-fluid .span8 { - width: 65.95744680851064%; - *width: 65.90425531914893%; -} - -.row-fluid .span7 { - width: 57.44680851063829%; - *width: 57.39361702127659%; -} - -.row-fluid .span6 { - width: 48.93617021276595%; - *width: 48.88297872340425%; -} - -.row-fluid .span5 { - width: 40.42553191489362%; - *width: 40.37234042553192%; -} - -.row-fluid .span4 { - width: 31.914893617021278%; - *width: 31.861702127659576%; -} - -.row-fluid .span3 { - width: 23.404255319148934%; - *width: 23.351063829787233%; -} - -.row-fluid .span2 { - width: 14.893617021276595%; - *width: 14.840425531914894%; -} - -.row-fluid .span1 { - width: 6.382978723404255%; - *width: 6.329787234042553%; -} - -.row-fluid .offset12 { - margin-left: 104.25531914893617%; - *margin-left: 104.14893617021275%; -} - -.row-fluid .offset12:first-child { - margin-left: 102.12765957446808%; - *margin-left: 102.02127659574467%; -} - -.row-fluid .offset11 { - margin-left: 95.74468085106382%; - *margin-left: 95.6382978723404%; -} - -.row-fluid .offset11:first-child { - margin-left: 93.61702127659574%; - *margin-left: 93.51063829787232%; -} - -.row-fluid .offset10 { - margin-left: 87.23404255319149%; - *margin-left: 87.12765957446807%; -} - -.row-fluid .offset10:first-child { - margin-left: 85.1063829787234%; - *margin-left: 84.99999999999999%; -} - -.row-fluid .offset9 { - margin-left: 78.72340425531914%; - *margin-left: 78.61702127659572%; -} - -.row-fluid .offset9:first-child { - margin-left: 76.59574468085106%; - *margin-left: 76.48936170212764%; -} - -.row-fluid .offset8 { - margin-left: 70.2127659574468%; - *margin-left: 70.10638297872339%; -} - -.row-fluid .offset8:first-child { - margin-left: 68.08510638297872%; - *margin-left: 67.9787234042553%; -} - -.row-fluid .offset7 { - margin-left: 61.70212765957446%; - *margin-left: 61.59574468085106%; -} - -.row-fluid .offset7:first-child { - margin-left: 59.574468085106375%; - *margin-left: 59.46808510638297%; -} - -.row-fluid .offset6 { - margin-left: 53.191489361702125%; - *margin-left: 53.085106382978715%; -} - -.row-fluid .offset6:first-child { - margin-left: 51.063829787234035%; - *margin-left: 50.95744680851063%; -} - -.row-fluid .offset5 { - margin-left: 44.68085106382979%; - *margin-left: 44.57446808510638%; -} - -.row-fluid .offset5:first-child { - margin-left: 42.5531914893617%; - *margin-left: 42.4468085106383%; -} - -.row-fluid .offset4 { - margin-left: 36.170212765957444%; - *margin-left: 36.06382978723405%; -} - -.row-fluid .offset4:first-child { - margin-left: 34.04255319148936%; - *margin-left: 33.93617021276596%; -} - -.row-fluid .offset3 { - margin-left: 27.659574468085104%; - *margin-left: 27.5531914893617%; -} - -.row-fluid .offset3:first-child { - margin-left: 25.53191489361702%; - *margin-left: 25.425531914893618%; -} - -.row-fluid .offset2 { - margin-left: 19.148936170212764%; - *margin-left: 19.04255319148936%; -} - -.row-fluid .offset2:first-child { - margin-left: 17.02127659574468%; - *margin-left: 16.914893617021278%; -} - -.row-fluid .offset1 { - margin-left: 10.638297872340425%; - *margin-left: 10.53191489361702%; -} - -.row-fluid .offset1:first-child { - margin-left: 8.51063829787234%; - *margin-left: 8.404255319148938%; -} - -[class*="span"].hide, -.row-fluid [class*="span"].hide { - display: none; -} - -[class*="span"].pull-right, -.row-fluid [class*="span"].pull-right { - float: right; -} - -.container { - margin-right: auto; - margin-left: auto; - *zoom: 1; -} - -.container:before, -.container:after { - display: table; - line-height: 0; - content: ""; -} - -.container:after { - clear: both; -} - -.container-fluid { - padding-right: 20px; - padding-left: 20px; - *zoom: 1; -} - -.container-fluid:before, -.container-fluid:after { - display: table; - line-height: 0; - content: ""; -} - -.container-fluid:after { - clear: both; -} - -p { - margin: 0 0 10px; -} - -.lead { - margin-bottom: 20px; - font-size: 21px; - font-weight: 200; - line-height: 30px; -} - -small { - font-size: 85%; -} - -strong { - font-weight: bold; -} - -em { - font-style: italic; -} - -cite { - font-style: normal; -} - -.muted { - color: #999999; -} - -a.muted:hover, -a.muted:focus { - color: #808080; -} - -.text-warning { - color: #c09853; -} - -a.text-warning:hover, -a.text-warning:focus { - color: #a47e3c; -} - -.text-error { - color: #b94a48; -} - -a.text-error:hover, -a.text-error:focus { - color: #953b39; -} - -.text-info { - color: #3a87ad; -} - -a.text-info:hover, -a.text-info:focus { - color: #2d6987; -} - -.text-success { - color: #468847; -} - -a.text-success:hover, -a.text-success:focus { - color: #356635; -} - -.text-left { - text-align: left; -} - -.text-right { - text-align: right; -} - -.text-center { - text-align: center; -} - -h1, -h2, -h3, -h4, -h5, -h6 { - margin: 10px 0; - font-family: inherit; - font-weight: bold; - line-height: 20px; - color: inherit; - text-rendering: optimizelegibility; -} - -h1 small, -h2 small, -h3 small, -h4 small, -h5 small, -h6 small { - font-weight: normal; - line-height: 1; - color: #999999; -} - -h1, -h2, -h3 { - line-height: 40px; -} - -h1 { - font-size: 38.5px; -} - -h2 { - font-size: 31.5px; -} - -h3 { - font-size: 24.5px; -} - -h4 { - font-size: 17.5px; -} - -h5 { - font-size: 14px; -} - -h6 { - font-size: 11.9px; -} - -h1 small { - font-size: 24.5px; -} - -h2 small { - font-size: 17.5px; -} - -h3 small { - font-size: 14px; -} - -h4 small { - font-size: 14px; -} - -.page-header { - padding-bottom: 9px; - margin: 20px 0 30px; - border-bottom: 1px solid #eeeeee; -} - -ul, -ol { - padding: 0; - margin: 0 0 10px 25px; -} - -ul ul, -ul ol, -ol ol, -ol ul { - margin-bottom: 0; -} - -li { - line-height: 20px; -} - -ul.unstyled, -ol.unstyled { - margin-left: 0; - list-style: none; -} - -ul.inline, -ol.inline { - margin-left: 0; - list-style: none; -} - -ul.inline > li, -ol.inline > li { - display: inline-block; - *display: inline; - padding-right: 5px; - padding-left: 5px; - *zoom: 1; -} - -dl { - margin-bottom: 20px; -} - -dt, -dd { - line-height: 20px; -} - -dt { - font-weight: bold; -} - -dd { - margin-left: 10px; -} - -.dl-horizontal { - *zoom: 1; -} - -.dl-horizontal:before, -.dl-horizontal:after { - display: table; - line-height: 0; - content: ""; -} - -.dl-horizontal:after { - clear: both; -} - -.dl-horizontal dt { - float: left; - width: 160px; - overflow: hidden; - clear: left; - text-align: right; - text-overflow: ellipsis; - white-space: nowrap; -} - -.dl-horizontal dd { - margin-left: 180px; -} - -hr { - margin: 20px 0; - border: 0; - border-top: 1px solid #eeeeee; - border-bottom: 1px solid #ffffff; -} - -abbr[title], -abbr[data-original-title] { - cursor: help; - border-bottom: 1px dotted #999999; -} - -abbr.initialism { - font-size: 90%; - text-transform: uppercase; -} - -blockquote { - padding: 0 0 0 15px; - margin: 0 0 20px; - border-left: 5px solid #eeeeee; -} - -blockquote p { - margin-bottom: 0; - font-size: 17.5px; - font-weight: 300; - line-height: 1.25; -} - -blockquote small { - display: block; - line-height: 20px; - color: #999999; -} - -blockquote small:before { - content: '\2014 \00A0'; -} - -blockquote.pull-right { - float: right; - padding-right: 15px; - padding-left: 0; - border-right: 5px solid #eeeeee; - border-left: 0; -} - -blockquote.pull-right p, -blockquote.pull-right small { - text-align: right; -} - -blockquote.pull-right small:before { - content: ''; -} - -blockquote.pull-right small:after { - content: '\00A0 \2014'; -} - -q:before, -q:after, -blockquote:before, -blockquote:after { - content: ""; -} - -address { - display: block; - margin-bottom: 20px; - font-style: normal; - line-height: 20px; -} - -code, -pre { - padding: 0 3px 2px; - font-family: Monaco, Menlo, Consolas, "Courier New", monospace; - font-size: 12px; - color: #333333; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -code { - padding: 2px 4px; - color: #d14; - white-space: nowrap; - background-color: #f7f7f9; - border: 1px solid #e1e1e8; -} - -pre { - display: block; - padding: 9.5px; - margin: 0 0 10px; - font-size: 13px; - line-height: 20px; - word-break: break-all; - word-wrap: break-word; - white-space: pre; - white-space: pre-wrap; - background-color: #f5f5f5; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.15); - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -pre.prettyprint { - margin-bottom: 20px; -} - -pre code { - padding: 0; - color: inherit; - white-space: pre; - white-space: pre-wrap; - background-color: transparent; - border: 0; -} - -.pre-scrollable { - max-height: 340px; - overflow-y: scroll; -} - -form { - margin: 0 0 20px; -} - -fieldset { - padding: 0; - margin: 0; - border: 0; -} - -legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: 20px; - font-size: 21px; - line-height: 40px; - color: #333333; - border: 0; - border-bottom: 1px solid #e5e5e5; -} - -legend small { - font-size: 15px; - color: #999999; -} - -label, -input, -button, -select, -textarea { - font-size: 14px; - font-weight: normal; - line-height: 20px; -} - -input, -button, -select, -textarea { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; -} - -label { - display: block; - margin-bottom: 5px; -} - -select, -textarea, -input[type="text"], -input[type="password"], -input[type="datetime"], -input[type="datetime-local"], -input[type="date"], -input[type="month"], -input[type="time"], -input[type="week"], -input[type="number"], -input[type="email"], -input[type="url"], -input[type="search"], -input[type="tel"], -input[type="color"], -.uneditable-input { - display: inline-block; - height: 20px; - padding: 4px 6px; - margin-bottom: 10px; - font-size: 14px; - line-height: 20px; - color: #555555; - vertical-align: middle; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -input, -textarea, -.uneditable-input { - width: 206px; -} - -textarea { - height: auto; -} - -textarea, -input[type="text"], -input[type="password"], -input[type="datetime"], -input[type="datetime-local"], -input[type="date"], -input[type="month"], -input[type="time"], -input[type="week"], -input[type="number"], -input[type="email"], -input[type="url"], -input[type="search"], -input[type="tel"], -input[type="color"], -.uneditable-input { - background-color: #ffffff; - border: 1px solid #cccccc; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; - -moz-transition: border linear 0.2s, box-shadow linear 0.2s; - -o-transition: border linear 0.2s, box-shadow linear 0.2s; - transition: border linear 0.2s, box-shadow linear 0.2s; -} - -textarea:focus, -input[type="text"]:focus, -input[type="password"]:focus, -input[type="datetime"]:focus, -input[type="datetime-local"]:focus, -input[type="date"]:focus, -input[type="month"]:focus, -input[type="time"]:focus, -input[type="week"]:focus, -input[type="number"]:focus, -input[type="email"]:focus, -input[type="url"]:focus, -input[type="search"]:focus, -input[type="tel"]:focus, -input[type="color"]:focus, -.uneditable-input:focus { - border-color: rgba(82, 168, 236, 0.8); - outline: 0; - outline: thin dotted \9; - /* IE6-9 */ - - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); -} - -input[type="radio"], -input[type="checkbox"] { - margin: 4px 0 0; - margin-top: 1px \9; - *margin-top: 0; - line-height: normal; -} - -input[type="file"], -input[type="image"], -input[type="submit"], -input[type="reset"], -input[type="button"], -input[type="radio"], -input[type="checkbox"] { - width: auto; -} - -select, -input[type="file"] { - height: 30px; - /* In IE7, the height of the select element cannot be changed by height, only font-size */ - - *margin-top: 4px; - /* For IE7, add top margin to align select with labels */ - - line-height: 30px; -} - -select { - width: 220px; - background-color: #ffffff; - border: 1px solid #cccccc; -} - -select[multiple], -select[size] { - height: auto; -} - -select:focus, -input[type="file"]:focus, -input[type="radio"]:focus, -input[type="checkbox"]:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -.uneditable-input, -.uneditable-textarea { - color: #999999; - cursor: not-allowed; - background-color: #fcfcfc; - border-color: #cccccc; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); -} - -.uneditable-input { - overflow: hidden; - white-space: nowrap; -} - -.uneditable-textarea { - width: auto; - height: auto; -} - -input:-moz-placeholder, -textarea:-moz-placeholder { - color: #999999; -} - -input:-ms-input-placeholder, -textarea:-ms-input-placeholder { - color: #999999; -} - -input::-webkit-input-placeholder, -textarea::-webkit-input-placeholder { - color: #999999; -} - -.radio, -.checkbox { - min-height: 20px; - padding-left: 20px; -} - -.radio input[type="radio"], -.checkbox input[type="checkbox"] { - float: left; - margin-left: -20px; -} - -.controls > .radio:first-child, -.controls > .checkbox:first-child { - padding-top: 5px; -} - -.radio.inline, -.checkbox.inline { - display: inline-block; - padding-top: 5px; - margin-bottom: 0; - vertical-align: middle; -} - -.radio.inline + .radio.inline, -.checkbox.inline + .checkbox.inline { - margin-left: 10px; -} - -.input-mini { - width: 60px; -} - -.input-small { - width: 90px; -} - -.input-medium { - width: 150px; -} - -.input-large { - width: 210px; -} - -.input-xlarge { - width: 270px; -} - -.input-xxlarge { - width: 530px; -} - -input[class*="span"], -select[class*="span"], -textarea[class*="span"], -.uneditable-input[class*="span"], -.row-fluid input[class*="span"], -.row-fluid select[class*="span"], -.row-fluid textarea[class*="span"], -.row-fluid .uneditable-input[class*="span"] { - float: none; - margin-left: 0; -} - -.input-append input[class*="span"], -.input-append .uneditable-input[class*="span"], -.input-prepend input[class*="span"], -.input-prepend .uneditable-input[class*="span"], -.row-fluid input[class*="span"], -.row-fluid select[class*="span"], -.row-fluid textarea[class*="span"], -.row-fluid .uneditable-input[class*="span"], -.row-fluid .input-prepend [class*="span"], -.row-fluid .input-append [class*="span"] { - display: inline-block; -} - -input, -textarea, -.uneditable-input { - margin-left: 0; -} - -.controls-row [class*="span"] + [class*="span"] { - margin-left: 20px; -} - -input.span12, -textarea.span12, -.uneditable-input.span12 { - width: 926px; -} - -input.span11, -textarea.span11, -.uneditable-input.span11 { - width: 846px; -} - -input.span10, -textarea.span10, -.uneditable-input.span10 { - width: 766px; -} - -input.span9, -textarea.span9, -.uneditable-input.span9 { - width: 686px; -} - -input.span8, -textarea.span8, -.uneditable-input.span8 { - width: 606px; -} - -input.span7, -textarea.span7, -.uneditable-input.span7 { - width: 526px; -} - -input.span6, -textarea.span6, -.uneditable-input.span6 { - width: 446px; -} - -input.span5, -textarea.span5, -.uneditable-input.span5 { - width: 366px; -} - -input.span4, -textarea.span4, -.uneditable-input.span4 { - width: 286px; -} - -input.span3, -textarea.span3, -.uneditable-input.span3 { - width: 206px; -} - -input.span2, -textarea.span2, -.uneditable-input.span2 { - width: 126px; -} - -input.span1, -textarea.span1, -.uneditable-input.span1 { - width: 46px; -} - -.controls-row { - *zoom: 1; -} - -.controls-row:before, -.controls-row:after { - display: table; - line-height: 0; - content: ""; -} - -.controls-row:after { - clear: both; -} - -.controls-row [class*="span"], -.row-fluid .controls-row [class*="span"] { - float: left; -} - -.controls-row .checkbox[class*="span"], -.controls-row .radio[class*="span"] { - padding-top: 5px; -} - -input[disabled], -select[disabled], -textarea[disabled], -input[readonly], -select[readonly], -textarea[readonly] { - cursor: not-allowed; - background-color: #eeeeee; -} - -input[type="radio"][disabled], -input[type="checkbox"][disabled], -input[type="radio"][readonly], -input[type="checkbox"][readonly] { - background-color: transparent; -} - -.control-group.warning .control-label, -.control-group.warning .help-block, -.control-group.warning .help-inline { - color: #c09853; -} - -.control-group.warning .checkbox, -.control-group.warning .radio, -.control-group.warning input, -.control-group.warning select, -.control-group.warning textarea { - color: #c09853; -} - -.control-group.warning input, -.control-group.warning select, -.control-group.warning textarea { - border-color: #c09853; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.control-group.warning input:focus, -.control-group.warning select:focus, -.control-group.warning textarea:focus { - border-color: #a47e3c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; -} - -.control-group.warning .input-prepend .add-on, -.control-group.warning .input-append .add-on { - color: #c09853; - background-color: #fcf8e3; - border-color: #c09853; -} - -.control-group.error .control-label, -.control-group.error .help-block, -.control-group.error .help-inline { - color: #b94a48; -} - -.control-group.error .checkbox, -.control-group.error .radio, -.control-group.error input, -.control-group.error select, -.control-group.error textarea { - color: #b94a48; -} - -.control-group.error input, -.control-group.error select, -.control-group.error textarea { - border-color: #b94a48; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.control-group.error input:focus, -.control-group.error select:focus, -.control-group.error textarea:focus { - border-color: #953b39; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; -} - -.control-group.error .input-prepend .add-on, -.control-group.error .input-append .add-on { - color: #b94a48; - background-color: #f2dede; - border-color: #b94a48; -} - -.control-group.success .control-label, -.control-group.success .help-block, -.control-group.success .help-inline { - color: #468847; -} - -.control-group.success .checkbox, -.control-group.success .radio, -.control-group.success input, -.control-group.success select, -.control-group.success textarea { - color: #468847; -} - -.control-group.success input, -.control-group.success select, -.control-group.success textarea { - border-color: #468847; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.control-group.success input:focus, -.control-group.success select:focus, -.control-group.success textarea:focus { - border-color: #356635; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; -} - -.control-group.success .input-prepend .add-on, -.control-group.success .input-append .add-on { - color: #468847; - background-color: #dff0d8; - border-color: #468847; -} - -.control-group.info .control-label, -.control-group.info .help-block, -.control-group.info .help-inline { - color: #3a87ad; -} - -.control-group.info .checkbox, -.control-group.info .radio, -.control-group.info input, -.control-group.info select, -.control-group.info textarea { - color: #3a87ad; -} - -.control-group.info input, -.control-group.info select, -.control-group.info textarea { - border-color: #3a87ad; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.control-group.info input:focus, -.control-group.info select:focus, -.control-group.info textarea:focus { - border-color: #2d6987; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; -} - -.control-group.info .input-prepend .add-on, -.control-group.info .input-append .add-on { - color: #3a87ad; - background-color: #d9edf7; - border-color: #3a87ad; -} - -input:focus:invalid, -textarea:focus:invalid, -select:focus:invalid { - color: #b94a48; - border-color: #ee5f5b; -} - -input:focus:invalid:focus, -textarea:focus:invalid:focus, -select:focus:invalid:focus { - border-color: #e9322d; - -webkit-box-shadow: 0 0 6px #f8b9b7; - -moz-box-shadow: 0 0 6px #f8b9b7; - box-shadow: 0 0 6px #f8b9b7; -} - -.form-actions { - padding: 19px 20px 20px; - margin-top: 20px; - margin-bottom: 20px; - background-color: #f5f5f5; - border-top: 1px solid #e5e5e5; - *zoom: 1; -} - -.form-actions:before, -.form-actions:after { - display: table; - line-height: 0; - content: ""; -} - -.form-actions:after { - clear: both; -} - -.help-block, -.help-inline { - color: #595959; -} - -.help-block { - display: block; - margin-bottom: 10px; -} - -.help-inline { - display: inline-block; - *display: inline; - padding-left: 5px; - vertical-align: middle; - *zoom: 1; -} - -.input-append, -.input-prepend { - display: inline-block; - margin-bottom: 10px; - font-size: 0; - white-space: nowrap; - vertical-align: middle; -} - -.input-append input, -.input-prepend input, -.input-append select, -.input-prepend select, -.input-append .uneditable-input, -.input-prepend .uneditable-input, -.input-append .dropdown-menu, -.input-prepend .dropdown-menu, -.input-append .popover, -.input-prepend .popover { - font-size: 14px; -} - -.input-append input, -.input-prepend input, -.input-append select, -.input-prepend select, -.input-append .uneditable-input, -.input-prepend .uneditable-input { - position: relative; - margin-bottom: 0; - *margin-left: 0; - vertical-align: top; - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.input-append input:focus, -.input-prepend input:focus, -.input-append select:focus, -.input-prepend select:focus, -.input-append .uneditable-input:focus, -.input-prepend .uneditable-input:focus { - z-index: 2; -} - -.input-append .add-on, -.input-prepend .add-on { - display: inline-block; - width: auto; - height: 20px; - min-width: 16px; - padding: 4px 5px; - font-size: 14px; - font-weight: normal; - line-height: 20px; - text-align: center; - text-shadow: 0 1px 0 #ffffff; - background-color: #eeeeee; - border: 1px solid #ccc; -} - -.input-append .add-on, -.input-prepend .add-on, -.input-append .btn, -.input-prepend .btn, -.input-append .btn-group > .dropdown-toggle, -.input-prepend .btn-group > .dropdown-toggle { - vertical-align: top; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.input-append .active, -.input-prepend .active { - background-color: #a9dba9; - border-color: #46a546; -} - -.input-prepend .add-on, -.input-prepend .btn { - margin-right: -1px; -} - -.input-prepend .add-on:first-child, -.input-prepend .btn:first-child { - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} - -.input-append input, -.input-append select, -.input-append .uneditable-input { - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} - -.input-append input + .btn-group .btn:last-child, -.input-append select + .btn-group .btn:last-child, -.input-append .uneditable-input + .btn-group .btn:last-child { - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.input-append .add-on, -.input-append .btn, -.input-append .btn-group { - margin-left: -1px; -} - -.input-append .add-on:last-child, -.input-append .btn:last-child, -.input-append .btn-group:last-child > .dropdown-toggle { - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.input-prepend.input-append input, -.input-prepend.input-append select, -.input-prepend.input-append .uneditable-input { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.input-prepend.input-append input + .btn-group .btn, -.input-prepend.input-append select + .btn-group .btn, -.input-prepend.input-append .uneditable-input + .btn-group .btn { - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.input-prepend.input-append .add-on:first-child, -.input-prepend.input-append .btn:first-child { - margin-right: -1px; - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} - -.input-prepend.input-append .add-on:last-child, -.input-prepend.input-append .btn:last-child { - margin-left: -1px; - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.input-prepend.input-append .btn-group:first-child { - margin-left: 0; -} - -input.search-query { - padding-right: 14px; - padding-right: 4px \9; - padding-left: 14px; - padding-left: 4px \9; - /* IE7-8 doesn't have border-radius, so don't indent the padding */ - - margin-bottom: 0; - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; -} - -/* Allow for input prepend/append in search forms */ - -.form-search .input-append .search-query, -.form-search .input-prepend .search-query { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.form-search .input-append .search-query { - -webkit-border-radius: 14px 0 0 14px; - -moz-border-radius: 14px 0 0 14px; - border-radius: 14px 0 0 14px; -} - -.form-search .input-append .btn { - -webkit-border-radius: 0 14px 14px 0; - -moz-border-radius: 0 14px 14px 0; - border-radius: 0 14px 14px 0; -} - -.form-search .input-prepend .search-query { - -webkit-border-radius: 0 14px 14px 0; - -moz-border-radius: 0 14px 14px 0; - border-radius: 0 14px 14px 0; -} - -.form-search .input-prepend .btn { - -webkit-border-radius: 14px 0 0 14px; - -moz-border-radius: 14px 0 0 14px; - border-radius: 14px 0 0 14px; -} - -.form-search input, -.form-inline input, -.form-horizontal input, -.form-search textarea, -.form-inline textarea, -.form-horizontal textarea, -.form-search select, -.form-inline select, -.form-horizontal select, -.form-search .help-inline, -.form-inline .help-inline, -.form-horizontal .help-inline, -.form-search .uneditable-input, -.form-inline .uneditable-input, -.form-horizontal .uneditable-input, -.form-search .input-prepend, -.form-inline .input-prepend, -.form-horizontal .input-prepend, -.form-search .input-append, -.form-inline .input-append, -.form-horizontal .input-append { - display: inline-block; - *display: inline; - margin-bottom: 0; - vertical-align: middle; - *zoom: 1; -} - -.form-search .hide, -.form-inline .hide, -.form-horizontal .hide { - display: none; -} - -.form-search label, -.form-inline label, -.form-search .btn-group, -.form-inline .btn-group { - display: inline-block; -} - -.form-search .input-append, -.form-inline .input-append, -.form-search .input-prepend, -.form-inline .input-prepend { - margin-bottom: 0; -} - -.form-search .radio, -.form-search .checkbox, -.form-inline .radio, -.form-inline .checkbox { - padding-left: 0; - margin-bottom: 0; - vertical-align: middle; -} - -.form-search .radio input[type="radio"], -.form-search .checkbox input[type="checkbox"], -.form-inline .radio input[type="radio"], -.form-inline .checkbox input[type="checkbox"] { - float: left; - margin-right: 3px; - margin-left: 0; -} - -.control-group { - margin-bottom: 10px; -} - -legend + .control-group { - margin-top: 20px; - -webkit-margin-top-collapse: separate; -} - -.form-horizontal .control-group { - margin-bottom: 20px; - *zoom: 1; -} - -.form-horizontal .control-group:before, -.form-horizontal .control-group:after { - display: table; - line-height: 0; - content: ""; -} - -.form-horizontal .control-group:after { - clear: both; -} - -.form-horizontal .control-label { - float: left; - width: 160px; - padding-top: 5px; - text-align: right; -} - -.form-horizontal .controls { - *display: inline-block; - *padding-left: 20px; - margin-left: 180px; - *margin-left: 0; -} - -.form-horizontal .controls:first-child { - *padding-left: 180px; -} - -.form-horizontal .help-block { - margin-bottom: 0; -} - -.form-horizontal input + .help-block, -.form-horizontal select + .help-block, -.form-horizontal textarea + .help-block, -.form-horizontal .uneditable-input + .help-block, -.form-horizontal .input-prepend + .help-block, -.form-horizontal .input-append + .help-block { - margin-top: 10px; -} - -.form-horizontal .form-actions { - padding-left: 180px; -} - -table { - max-width: 100%; - background-color: transparent; - border-collapse: collapse; - border-spacing: 0; -} - -.table { - width: 100%; - margin-bottom: 20px; -} - -.table th, -.table td { - padding: 8px; - line-height: 20px; - text-align: left; - vertical-align: top; - border-top: 1px solid #dddddd; -} - -.table th { - font-weight: bold; -} - -.table thead th { - vertical-align: bottom; -} - -.table caption + thead tr:first-child th, -.table caption + thead tr:first-child td, -.table colgroup + thead tr:first-child th, -.table colgroup + thead tr:first-child td, -.table thead:first-child tr:first-child th, -.table thead:first-child tr:first-child td { - border-top: 0; -} - -.table tbody + tbody { - border-top: 2px solid #dddddd; -} - -.table .table { - background-color: #ffffff; -} - -.table-condensed th, -.table-condensed td { - padding: 4px 5px; -} - -.table-bordered { - border: 1px solid #dddddd; - border-collapse: separate; - *border-collapse: collapse; - border-left: 0; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.table-bordered th, -.table-bordered td { - border-left: 1px solid #dddddd; -} - -.table-bordered caption + thead tr:first-child th, -.table-bordered caption + tbody tr:first-child th, -.table-bordered caption + tbody tr:first-child td, -.table-bordered colgroup + thead tr:first-child th, -.table-bordered colgroup + tbody tr:first-child th, -.table-bordered colgroup + tbody tr:first-child td, -.table-bordered thead:first-child tr:first-child th, -.table-bordered tbody:first-child tr:first-child th, -.table-bordered tbody:first-child tr:first-child td { - border-top: 0; -} - -.table-bordered thead:first-child tr:first-child > th:first-child, -.table-bordered tbody:first-child tr:first-child > td:first-child, -.table-bordered tbody:first-child tr:first-child > th:first-child { - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-topleft: 4px; -} - -.table-bordered thead:first-child tr:first-child > th:last-child, -.table-bordered tbody:first-child tr:first-child > td:last-child, -.table-bordered tbody:first-child tr:first-child > th:last-child { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -moz-border-radius-topright: 4px; -} - -.table-bordered thead:last-child tr:last-child > th:first-child, -.table-bordered tbody:last-child tr:last-child > td:first-child, -.table-bordered tbody:last-child tr:last-child > th:first-child, -.table-bordered tfoot:last-child tr:last-child > td:first-child, -.table-bordered tfoot:last-child tr:last-child > th:first-child { - -webkit-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; -} - -.table-bordered thead:last-child tr:last-child > th:last-child, -.table-bordered tbody:last-child tr:last-child > td:last-child, -.table-bordered tbody:last-child tr:last-child > th:last-child, -.table-bordered tfoot:last-child tr:last-child > td:last-child, -.table-bordered tfoot:last-child tr:last-child > th:last-child { - -webkit-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px; - -moz-border-radius-bottomright: 4px; -} - -.table-bordered tfoot + tbody:last-child tr:last-child td:first-child { - -webkit-border-bottom-left-radius: 0; - border-bottom-left-radius: 0; - -moz-border-radius-bottomleft: 0; -} - -.table-bordered tfoot + tbody:last-child tr:last-child td:last-child { - -webkit-border-bottom-right-radius: 0; - border-bottom-right-radius: 0; - -moz-border-radius-bottomright: 0; -} - -.table-bordered caption + thead tr:first-child th:first-child, -.table-bordered caption + tbody tr:first-child td:first-child, -.table-bordered colgroup + thead tr:first-child th:first-child, -.table-bordered colgroup + tbody tr:first-child td:first-child { - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-topleft: 4px; -} - -.table-bordered caption + thead tr:first-child th:last-child, -.table-bordered caption + tbody tr:first-child td:last-child, -.table-bordered colgroup + thead tr:first-child th:last-child, -.table-bordered colgroup + tbody tr:first-child td:last-child { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -moz-border-radius-topright: 4px; -} - -.table-striped tbody > tr:nth-child(odd) > td, -.table-striped tbody > tr:nth-child(odd) > th { - background-color: #f9f9f9; -} - -.table-hover tbody tr:hover > td, -.table-hover tbody tr:hover > th { - background-color: #f5f5f5; -} - -table td[class*="span"], -table th[class*="span"], -.row-fluid table td[class*="span"], -.row-fluid table th[class*="span"] { - display: table-cell; - float: none; - margin-left: 0; -} - -.table td.span1, -.table th.span1 { - float: none; - width: 44px; - margin-left: 0; -} - -.table td.span2, -.table th.span2 { - float: none; - width: 124px; - margin-left: 0; -} - -.table td.span3, -.table th.span3 { - float: none; - width: 204px; - margin-left: 0; -} - -.table td.span4, -.table th.span4 { - float: none; - width: 284px; - margin-left: 0; -} - -.table td.span5, -.table th.span5 { - float: none; - width: 364px; - margin-left: 0; -} - -.table td.span6, -.table th.span6 { - float: none; - width: 444px; - margin-left: 0; -} - -.table td.span7, -.table th.span7 { - float: none; - width: 524px; - margin-left: 0; -} - -.table td.span8, -.table th.span8 { - float: none; - width: 604px; - margin-left: 0; -} - -.table td.span9, -.table th.span9 { - float: none; - width: 684px; - margin-left: 0; -} - -.table td.span10, -.table th.span10 { - float: none; - width: 764px; - margin-left: 0; -} - -.table td.span11, -.table th.span11 { - float: none; - width: 844px; - margin-left: 0; -} - -.table td.span12, -.table th.span12 { - float: none; - width: 924px; - margin-left: 0; -} - -.table tbody tr.success > td { - background-color: #dff0d8; -} - -.table tbody tr.error > td { - background-color: #f2dede; -} - -.table tbody tr.warning > td { - background-color: #fcf8e3; -} - -.table tbody tr.info > td { - background-color: #d9edf7; -} - -.table-hover tbody tr.success:hover > td { - background-color: #d0e9c6; -} - -.table-hover tbody tr.error:hover > td { - background-color: #ebcccc; -} - -.table-hover tbody tr.warning:hover > td { - background-color: #faf2cc; -} - -.table-hover tbody tr.info:hover > td { - background-color: #c4e3f3; -} - -[class^="icon-"], -[class*=" icon-"] { - display: inline-block; - width: 14px; - height: 14px; - margin-top: 1px; - *margin-right: .3em; - line-height: 14px; - vertical-align: text-top; - //background-image: url("../img/glyphicons-halflings.png"); - background-image: url(data:image/png;base64,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); - background-position: 14px 14px; - background-repeat: no-repeat; -} - -/* White icons with optional class, or on hover/focus/active states of certain elements */ - -.icon-white, -.nav-pills > .active > a > [class^="icon-"], -.nav-pills > .active > a > [class*=" icon-"], -.nav-list > .active > a > [class^="icon-"], -.nav-list > .active > a > [class*=" icon-"], -.navbar-inverse .nav > .active > a > [class^="icon-"], -.navbar-inverse .nav > .active > a > [class*=" icon-"], -.dropdown-menu > li > a:hover > [class^="icon-"], -.dropdown-menu > li > a:focus > [class^="icon-"], -.dropdown-menu > li > a:hover > [class*=" icon-"], -.dropdown-menu > li > a:focus > [class*=" icon-"], -.dropdown-menu > .active > a > [class^="icon-"], -.dropdown-menu > .active > a > [class*=" icon-"], -.dropdown-submenu:hover > a > [class^="icon-"], -.dropdown-submenu:focus > a > [class^="icon-"], -.dropdown-submenu:hover > a > [class*=" icon-"], -.dropdown-submenu:focus > a > [class*=" icon-"] { - //background-image: url("../img/glyphicons-halflings-white.png"); -background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAdUAAACFCAMAAAA6npKGAAAAhFBMVEX///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////9hWbqAAAAAK3RSTlMAzw/vn78vX98frz9/TY9PgG8J9tirS6iiSBseyfN1w5P51e0nkMAqese9zI5zvgAAEABJREFUeF7tnYlypDiXha/WBWiy819m3fflvP/7TRhwK8y5SmBwuatqdCoq03GQbwp9SCnhG0J+HnVZB8AthsFvMkrBx2yw88Yhu2GUT9FwxbcBCFa+Y3H7sM9KAkiSlgCy4qhShYhg5Wawyewb7I0osA+asMhX5+XVUQa4WSaHoQgp4kFe2w8AEOicq8gvZMvmFtWvcVjW79rHGytijZdG+5z0rYEAAmNPU7UhcGFUVaxK1NV3H4OOcElkdDseravDZgBYXhzXZKaTfOWrTQ7BL4sgTFUY0uaK7repWrNrIQ8Yaw3gW+1zyhcDI8Dydo6qW69uJy8V3QIvavTDM8rHoAPSAndfCV+vDi9VT1Q9iVNeUbNvyG9SxTtVfCpVhrrjZwCY5YXaB6D2abZbglnBGaRzVAMWhWZnrVgVqIJxfduBeD+pXeENq7EeUjWhapIqSQ7vcon8SP7NvnpdDNVYssiVvH4otU/LD4gruIhBRbqnagFTSgDsvuiv27/NiEAUFkSh6lpUF6wLVEhVQtVHSMVstok7Pz8XuptftfB21/rq/e/VONgKlbCS64jege9kk8tnqI4BKAvbEF9TFUDOUh3WHhyRiapYY6x4gMYLfciYF3sW9pM8yN9IkVfHTYiuWyNwdDClQtWoUvsA1D7NdsuO+L6kGivV8f9ONY4fjz3gxqWjTbvCXry31nvxoHPXZ2Nx8R/C/iM8yGeqx3213J8tDVR9GoEP2od8HoFX3oGR6iNwsJZG4EtUPTWkB4zh6ZUXD3gPePF09ipUmYEMeN135I/rdHr82u9Vrj7Pltrtc+ynd5gB6YAqzZauU33kxVS+yZIB8uQIKzb5xkyDlDHJE+6cb2dsmu2Xfq9y9Xll026fY98g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); -} - -.icon-glass { - background-position: 0 0; -} - -.icon-music { - background-position: -24px 0; -} - -.icon-search { - background-position: -48px 0; -} - -.icon-envelope { - background-position: -72px 0; -} - -.icon-heart { - background-position: -96px 0; -} - -.icon-star { - background-position: -120px 0; -} - -.icon-star-empty { - background-position: -144px 0; -} - -.icon-user { - background-position: -168px 0; -} - -.icon-film { - background-position: -192px 0; -} - -.icon-th-large { - background-position: -216px 0; -} - -.icon-th { - background-position: -240px 0; -} - -.icon-th-list { - background-position: -264px 0; -} - -.icon-ok { - background-position: -288px 0; -} - -.icon-remove { - background-position: -312px 0; -} - -.icon-zoom-in { - background-position: -336px 0; -} - -.icon-zoom-out { - background-position: -360px 0; -} - -.icon-off { - background-position: -384px 0; -} - -.icon-signal { - background-position: -408px 0; -} - -.icon-cog { - background-position: -432px 0; -} - -.icon-trash { - background-position: -456px 0; -} - -.icon-home { - background-position: 0 -24px; -} - -.icon-file { - background-position: -24px -24px; -} - -.icon-time { - background-position: -48px -24px; -} - -.icon-road { - background-position: -72px -24px; -} - -.icon-download-alt { - background-position: -96px -24px; -} - -.icon-download { - background-position: -120px -24px; -} - -.icon-upload { - background-position: -144px -24px; -} - -.icon-inbox { - background-position: -168px -24px; -} - -.icon-play-circle { - background-position: -192px -24px; -} - -.icon-repeat { - background-position: -216px -24px; -} - -.icon-refresh { - background-position: -240px -24px; -} - -.icon-list-alt { - background-position: -264px -24px; -} - -.icon-lock { - background-position: -287px -24px; -} - -.icon-flag { - background-position: -312px -24px; -} - -.icon-headphones { - background-position: -336px -24px; -} - -.icon-volume-off { - background-position: -360px -24px; -} - -.icon-volume-down { - background-position: -384px -24px; -} - -.icon-volume-up { - background-position: -408px -24px; -} - -.icon-qrcode { - background-position: -432px -24px; -} - -.icon-barcode { - background-position: -456px -24px; -} - -.icon-tag { - background-position: 0 -48px; -} - -.icon-tags { - background-position: -25px -48px; -} - -.icon-book { - background-position: -48px -48px; -} - -.icon-bookmark { - background-position: -72px -48px; -} - -.icon-print { - background-position: -96px -48px; -} - -.icon-camera { - background-position: -120px -48px; -} - -.icon-font { - background-position: -144px -48px; -} - -.icon-bold { - background-position: -167px -48px; -} - -.icon-italic { - background-position: -192px -48px; -} - -.icon-text-height { - background-position: -216px -48px; -} - -.icon-text-width { - background-position: -240px -48px; -} - -.icon-align-left { - background-position: -264px -48px; -} - -.icon-align-center { - background-position: -288px -48px; -} - -.icon-align-right { - background-position: -312px -48px; -} - -.icon-align-justify { - background-position: -336px -48px; -} - -.icon-list { - background-position: -360px -48px; -} - -.icon-indent-left { - background-position: -384px -48px; -} - -.icon-indent-right { - background-position: -408px -48px; -} - -.icon-facetime-video { - background-position: -432px -48px; -} - -.icon-picture { - background-position: -456px -48px; -} - -.icon-pencil { - background-position: 0 -72px; -} - -.icon-map-marker { - background-position: -24px -72px; -} - -.icon-adjust { - background-position: -48px -72px; -} - -.icon-tint { - background-position: -72px -72px; -} - -.icon-edit { - background-position: -96px -72px; -} - -.icon-share { - background-position: -120px -72px; -} - -.icon-check { - background-position: -144px -72px; -} - -.icon-move { - background-position: -168px -72px; -} - -.icon-step-backward { - background-position: -192px -72px; -} - -.icon-fast-backward { - background-position: -216px -72px; -} - -.icon-backward { - background-position: -240px -72px; -} - -.icon-play { - background-position: -264px -72px; -} - -.icon-pause { - background-position: -288px -72px; -} - -.icon-stop { - background-position: -312px -72px; -} - -.icon-forward { - background-position: -336px -72px; -} - -.icon-fast-forward { - background-position: -360px -72px; -} - -.icon-step-forward { - background-position: -384px -72px; -} - -.icon-eject { - background-position: -408px -72px; -} - -.icon-chevron-left { - background-position: -432px -72px; -} - -.icon-chevron-right { - background-position: -456px -72px; -} - -.icon-plus-sign { - background-position: 0 -96px; -} - -.icon-minus-sign { - background-position: -24px -96px; -} - -.icon-remove-sign { - background-position: -48px -96px; -} - -.icon-ok-sign { - background-position: -72px -96px; -} - -.icon-question-sign { - background-position: -96px -96px; -} - -.icon-info-sign { - background-position: -120px -96px; -} - -.icon-screenshot { - background-position: -144px -96px; -} - -.icon-remove-circle { - background-position: -168px -96px; -} - -.icon-ok-circle { - background-position: -192px -96px; -} - -.icon-ban-circle { - background-position: -216px -96px; -} - -.icon-arrow-left { - background-position: -240px -96px; -} - -.icon-arrow-right { - background-position: -264px -96px; -} - -.icon-arrow-up { - background-position: -289px -96px; -} - -.icon-arrow-down { - background-position: -312px -96px; -} - -.icon-share-alt { - background-position: -336px -96px; -} - -.icon-resize-full { - background-position: -360px -96px; -} - -.icon-resize-small { - background-position: -384px -96px; -} - -.icon-plus { - background-position: -408px -96px; -} - -.icon-minus { - background-position: -433px -96px; -} - -.icon-asterisk { - background-position: -456px -96px; -} - -.icon-exclamation-sign { - background-position: 0 -120px; -} - -.icon-gift { - background-position: -24px -120px; -} - -.icon-leaf { - background-position: -48px -120px; -} - -.icon-fire { - background-position: -72px -120px; -} - -.icon-eye-open { - background-position: -96px -120px; -} - -.icon-eye-close { - background-position: -120px -120px; -} - -.icon-warning-sign { - background-position: -144px -120px; -} - -.icon-plane { - background-position: -168px -120px; -} - -.icon-calendar { - background-position: -192px -120px; -} - -.icon-random { - width: 16px; - background-position: -216px -120px; -} - -.icon-comment { - background-position: -240px -120px; -} - -.icon-magnet { - background-position: -264px -120px; -} - -.icon-chevron-up { - background-position: -288px -120px; -} - -.icon-chevron-down { - background-position: -313px -119px; -} - -.icon-retweet { - background-position: -336px -120px; -} - -.icon-shopping-cart { - background-position: -360px -120px; -} - -.icon-folder-close { - width: 16px; - background-position: -384px -120px; -} - -.icon-folder-open { - width: 16px; - background-position: -408px -120px; -} - -.icon-resize-vertical { - background-position: -432px -119px; -} - -.icon-resize-horizontal { - background-position: -456px -118px; -} - -.icon-hdd { - background-position: 0 -144px; -} - -.icon-bullhorn { - background-position: -24px -144px; -} - -.icon-bell { - background-position: -48px -144px; -} - -.icon-certificate { - background-position: -72px -144px; -} - -.icon-thumbs-up { - background-position: -96px -144px; -} - -.icon-thumbs-down { - background-position: -120px -144px; -} - -.icon-hand-right { - background-position: -144px -144px; -} - -.icon-hand-left { - background-position: -168px -144px; -} - -.icon-hand-up { - background-position: -192px -144px; -} - -.icon-hand-down { - background-position: -216px -144px; -} - -.icon-circle-arrow-right { - background-position: -240px -144px; -} - -.icon-circle-arrow-left { - background-position: -264px -144px; -} - -.icon-circle-arrow-up { - background-position: -288px -144px; -} - -.icon-circle-arrow-down { - background-position: -312px -144px; -} - -.icon-globe { - background-position: -336px -144px; -} - -.icon-wrench { - background-position: -360px -144px; -} - -.icon-tasks { - background-position: -384px -144px; -} - -.icon-filter { - background-position: -408px -144px; -} - -.icon-briefcase { - background-position: -432px -144px; -} - -.icon-fullscreen { - background-position: -456px -144px; -} - -.dropup, -.dropdown { - position: relative; -} - -.dropdown-toggle { - *margin-bottom: -3px; -} - -.dropdown-toggle:active, -.open .dropdown-toggle { - outline: 0; -} - -.caret { - display: inline-block; - width: 0; - height: 0; - vertical-align: top; - border-top: 4px solid #000000; - border-right: 4px solid transparent; - border-left: 4px solid transparent; - content: ""; -} - -.dropdown .caret { - margin-top: 8px; - margin-left: 2px; -} - -.dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - list-style: none; - background-color: #ffffff; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - *border-right-width: 2px; - *border-bottom-width: 2px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -webkit-background-clip: padding-box; - -moz-background-clip: padding; - background-clip: padding-box; -} - -.dropdown-menu.pull-right { - right: 0; - left: auto; -} - -.dropdown-menu .divider { - *width: 100%; - height: 1px; - margin: 9px 1px; - *margin: -5px 0 5px; - overflow: hidden; - background-color: #e5e5e5; - border-bottom: 1px solid #ffffff; -} - -.dropdown-menu > li > a { - display: block; - padding: 3px 20px; - clear: both; - font-weight: normal; - line-height: 20px; - color: #333333; - white-space: nowrap; -} - -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus, -.dropdown-submenu:hover > a, -.dropdown-submenu:focus > a { - color: #ffffff; - text-decoration: none; - background-color: #0081c2; - background-image: -moz-linear-gradient(top, #0088cc, #0077b3); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); - background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); - background-image: -o-linear-gradient(top, #0088cc, #0077b3); - background-image: linear-gradient(to bottom, #0088cc, #0077b3); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); -} - -.dropdown-menu > .active > a, -.dropdown-menu > .active > a:hover, -.dropdown-menu > .active > a:focus { - color: #ffffff; - text-decoration: none; - background-color: #0081c2; - background-image: -moz-linear-gradient(top, #0088cc, #0077b3); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); - background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); - background-image: -o-linear-gradient(top, #0088cc, #0077b3); - background-image: linear-gradient(to bottom, #0088cc, #0077b3); - background-repeat: repeat-x; - outline: 0; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); -} - -.dropdown-menu > .disabled > a, -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - color: #999999; -} - -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - text-decoration: none; - cursor: default; - background-color: transparent; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.open { - *z-index: 1000; -} - -.open > .dropdown-menu { - display: block; -} - -.pull-right > .dropdown-menu { - right: 0; - left: auto; -} - -.dropup .caret, -.navbar-fixed-bottom .dropdown .caret { - border-top: 0; - border-bottom: 4px solid #000000; - content: ""; -} - -.dropup .dropdown-menu, -.navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 1px; -} - -.dropdown-submenu { - position: relative; -} - -.dropdown-submenu > .dropdown-menu { - top: 0; - left: 100%; - margin-top: -6px; - margin-left: -1px; - -webkit-border-radius: 0 6px 6px 6px; - -moz-border-radius: 0 6px 6px 6px; - border-radius: 0 6px 6px 6px; -} - -.dropdown-submenu:hover > .dropdown-menu { - display: block; -} - -.dropup .dropdown-submenu > .dropdown-menu { - top: auto; - bottom: 0; - margin-top: 0; - margin-bottom: -2px; - -webkit-border-radius: 5px 5px 5px 0; - -moz-border-radius: 5px 5px 5px 0; - border-radius: 5px 5px 5px 0; -} - -.dropdown-submenu > a:after { - display: block; - float: right; - width: 0; - height: 0; - margin-top: 5px; - margin-right: -10px; - border-color: transparent; - border-left-color: #cccccc; - border-style: solid; - border-width: 5px 0 5px 5px; - content: " "; -} - -.dropdown-submenu:hover > a:after { - border-left-color: #ffffff; -} - -.dropdown-submenu.pull-left { - float: none; -} - -.dropdown-submenu.pull-left > .dropdown-menu { - left: -100%; - margin-left: 10px; - -webkit-border-radius: 6px 0 6px 6px; - -moz-border-radius: 6px 0 6px 6px; - border-radius: 6px 0 6px 6px; -} - -.dropdown .dropdown-menu .nav-header { - padding-right: 20px; - padding-left: 20px; -} - -.typeahead { - z-index: 1051; - margin-top: 2px; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: #f5f5f5; - border: 1px solid #e3e3e3; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); -} - -.well blockquote { - border-color: #ddd; - border-color: rgba(0, 0, 0, 0.15); -} - -.well-large { - padding: 24px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.well-small { - padding: 9px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -.fade { - opacity: 0; - -webkit-transition: opacity 0.15s linear; - -moz-transition: opacity 0.15s linear; - -o-transition: opacity 0.15s linear; - transition: opacity 0.15s linear; -} - -.fade.in { - opacity: 1; -} - -.collapse { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition: height 0.35s ease; - -moz-transition: height 0.35s ease; - -o-transition: height 0.35s ease; - transition: height 0.35s ease; -} - -.collapse.in { - height: auto; -} - -.close { - float: right; - font-size: 20px; - font-weight: bold; - line-height: 20px; - color: #000000; - text-shadow: 0 1px 0 #ffffff; - opacity: 0.2; - filter: alpha(opacity=20); -} - -.close:hover, -.close:focus { - color: #000000; - text-decoration: none; - cursor: pointer; - opacity: 0.4; - filter: alpha(opacity=40); -} - -button.close { - padding: 0; - cursor: pointer; - background: transparent; - border: 0; - -webkit-appearance: none; -} - -.btn { - display: inline-block; - *display: inline; - padding: 4px 12px; - margin-bottom: 0; - *margin-left: .3em; - font-size: 14px; - line-height: 20px; - color: #333333; - text-align: center; - text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); - vertical-align: middle; - cursor: pointer; - background-color: #f5f5f5; - *background-color: #e6e6e6; - background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); - background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); - background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); - background-repeat: repeat-x; - border: 1px solid #cccccc; - *border: 0; - border-color: #e6e6e6 #e6e6e6 #bfbfbf; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - border-bottom-color: #b3b3b3; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); - *zoom: 1; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn:hover, -.btn:focus, -.btn:active, -.btn.active, -.btn.disabled, -.btn[disabled] { - color: #333333; - background-color: #e6e6e6; - *background-color: #d9d9d9; -} - -.btn:active, -.btn.active { - background-color: #cccccc \9; -} - -.btn:first-child { - *margin-left: 0; -} - -.btn:hover, -.btn:focus { - color: #333333; - text-decoration: none; - background-position: 0 -15px; - -webkit-transition: background-position 0.1s linear; - -moz-transition: background-position 0.1s linear; - -o-transition: background-position 0.1s linear; - transition: background-position 0.1s linear; -} - -.btn:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -.btn.active, -.btn:active { - background-image: none; - outline: 0; - -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn.disabled, -.btn[disabled] { - cursor: default; - background-image: none; - opacity: 0.65; - filter: alpha(opacity=65); - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} - -.btn-large { - padding: 11px 19px; - font-size: 17.5px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.btn-large [class^="icon-"], -.btn-large [class*=" icon-"] { - margin-top: 4px; -} - -.btn-small { - padding: 2px 10px; - font-size: 11.9px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -.btn-small [class^="icon-"], -.btn-small [class*=" icon-"] { - margin-top: 0; -} - -.btn-mini [class^="icon-"], -.btn-mini [class*=" icon-"] { - margin-top: -1px; -} - -.btn-mini { - padding: 0 6px; - font-size: 10.5px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -.btn-block { - display: block; - width: 100%; - padding-right: 0; - padding-left: 0; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.btn-block + .btn-block { - margin-top: 5px; -} - -input[type="submit"].btn-block, -input[type="reset"].btn-block, -input[type="button"].btn-block { - width: 100%; -} - -.btn-primary.active, -.btn-warning.active, -.btn-danger.active, -.btn-success.active, -.btn-info.active, -.btn-inverse.active { - color: rgba(255, 255, 255, 0.75); -} - -.btn-primary { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #006dcc; - *background-color: #0044cc; - background-image: -moz-linear-gradient(top, #0088cc, #0044cc); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); - background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); - background-image: -o-linear-gradient(top, #0088cc, #0044cc); - background-image: linear-gradient(to bottom, #0088cc, #0044cc); - background-repeat: repeat-x; - border-color: #0044cc #0044cc #002a80; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-primary:hover, -.btn-primary:focus, -.btn-primary:active, -.btn-primary.active, -.btn-primary.disabled, -.btn-primary[disabled] { - color: #ffffff; - background-color: #0044cc; - *background-color: #003bb3; -} - -.btn-primary:active, -.btn-primary.active { - background-color: #003399 \9; -} - -.btn-warning { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #faa732; - *background-color: #f89406; - background-image: -moz-linear-gradient(top, #fbb450, #f89406); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); - background-image: -webkit-linear-gradient(top, #fbb450, #f89406); - background-image: -o-linear-gradient(top, #fbb450, #f89406); - background-image: linear-gradient(to bottom, #fbb450, #f89406); - background-repeat: repeat-x; - border-color: #f89406 #f89406 #ad6704; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-warning:hover, -.btn-warning:focus, -.btn-warning:active, -.btn-warning.active, -.btn-warning.disabled, -.btn-warning[disabled] { - color: #ffffff; - background-color: #f89406; - *background-color: #df8505; -} - -.btn-warning:active, -.btn-warning.active { - background-color: #c67605 \9; -} - -.btn-danger { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #da4f49; - *background-color: #bd362f; - background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); - background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); - background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); - background-image: linear-gradient(to bottom, #ee5f5b, #bd362f); - background-repeat: repeat-x; - border-color: #bd362f #bd362f #802420; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-danger:hover, -.btn-danger:focus, -.btn-danger:active, -.btn-danger.active, -.btn-danger.disabled, -.btn-danger[disabled] { - color: #ffffff; - background-color: #bd362f; - *background-color: #a9302a; -} - -.btn-danger:active, -.btn-danger.active { - background-color: #942a25 \9; -} - -.btn-success { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #5bb75b; - *background-color: #51a351; - background-image: -moz-linear-gradient(top, #62c462, #51a351); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); - background-image: -webkit-linear-gradient(top, #62c462, #51a351); - background-image: -o-linear-gradient(top, #62c462, #51a351); - background-image: linear-gradient(to bottom, #62c462, #51a351); - background-repeat: repeat-x; - border-color: #51a351 #51a351 #387038; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-success:hover, -.btn-success:focus, -.btn-success:active, -.btn-success.active, -.btn-success.disabled, -.btn-success[disabled] { - color: #ffffff; - background-color: #51a351; - *background-color: #499249; -} - -.btn-success:active, -.btn-success.active { - background-color: #408140 \9; -} - -.btn-info { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #49afcd; - *background-color: #2f96b4; - background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); - background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); - background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); - background-image: linear-gradient(to bottom, #5bc0de, #2f96b4); - background-repeat: repeat-x; - border-color: #2f96b4 #2f96b4 #1f6377; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-info:hover, -.btn-info:focus, -.btn-info:active, -.btn-info.active, -.btn-info.disabled, -.btn-info[disabled] { - color: #ffffff; - background-color: #2f96b4; - *background-color: #2a85a0; -} - -.btn-info:active, -.btn-info.active { - background-color: #24748c \9; -} - -.btn-inverse { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #363636; - *background-color: #222222; - background-image: -moz-linear-gradient(top, #444444, #222222); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222)); - background-image: -webkit-linear-gradient(top, #444444, #222222); - background-image: -o-linear-gradient(top, #444444, #222222); - background-image: linear-gradient(to bottom, #444444, #222222); - background-repeat: repeat-x; - border-color: #222222 #222222 #000000; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-inverse:hover, -.btn-inverse:focus, -.btn-inverse:active, -.btn-inverse.active, -.btn-inverse.disabled, -.btn-inverse[disabled] { - color: #ffffff; - background-color: #222222; - *background-color: #151515; -} - -.btn-inverse:active, -.btn-inverse.active { - background-color: #080808 \9; -} - -button.btn, -input[type="submit"].btn { - *padding-top: 3px; - *padding-bottom: 3px; -} - -button.btn::-moz-focus-inner, -input[type="submit"].btn::-moz-focus-inner { - padding: 0; - border: 0; -} - -button.btn.btn-large, -input[type="submit"].btn.btn-large { - *padding-top: 7px; - *padding-bottom: 7px; -} - -button.btn.btn-small, -input[type="submit"].btn.btn-small { - *padding-top: 3px; - *padding-bottom: 3px; -} - -button.btn.btn-mini, -input[type="submit"].btn.btn-mini { - *padding-top: 1px; - *padding-bottom: 1px; -} - -.btn-link, -.btn-link:active, -.btn-link[disabled] { - background-color: transparent; - background-image: none; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} - -.btn-link { - color: #0088cc; - cursor: pointer; - border-color: transparent; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.btn-link:hover, -.btn-link:focus { - color: #005580; - text-decoration: underline; - background-color: transparent; -} - -.btn-link[disabled]:hover, -.btn-link[disabled]:focus { - color: #333333; - text-decoration: none; -} - -.btn-group { - position: relative; - display: inline-block; - *display: inline; - *margin-left: .3em; - font-size: 0; - white-space: nowrap; - vertical-align: middle; - *zoom: 1; -} - -.btn-group:first-child { - *margin-left: 0; -} - -.btn-group + .btn-group { - margin-left: 5px; -} - -.btn-toolbar { - margin-top: 10px; - margin-bottom: 10px; - font-size: 0; -} - -.btn-toolbar > .btn + .btn, -.btn-toolbar > .btn-group + .btn, -.btn-toolbar > .btn + .btn-group { - margin-left: 5px; -} - -.btn-group > .btn { - position: relative; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.btn-group > .btn + .btn { - margin-left: -1px; -} - -.btn-group > .btn, -.btn-group > .dropdown-menu, -.btn-group > .popover { - font-size: 14px; -} - -.btn-group > .btn-mini { - font-size: 10.5px; -} - -.btn-group > .btn-small { - font-size: 11.9px; -} - -.btn-group > .btn-large { - font-size: 17.5px; -} - -.btn-group > .btn:first-child { - margin-left: 0; - -webkit-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px; - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; - -moz-border-radius-topleft: 4px; -} - -.btn-group > .btn:last-child, -.btn-group > .dropdown-toggle { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px; - -moz-border-radius-topright: 4px; - -moz-border-radius-bottomright: 4px; -} - -.btn-group > .btn.large:first-child { - margin-left: 0; - -webkit-border-bottom-left-radius: 6px; - border-bottom-left-radius: 6px; - -webkit-border-top-left-radius: 6px; - border-top-left-radius: 6px; - -moz-border-radius-bottomleft: 6px; - -moz-border-radius-topleft: 6px; -} - -.btn-group > .btn.large:last-child, -.btn-group > .large.dropdown-toggle { - -webkit-border-top-right-radius: 6px; - border-top-right-radius: 6px; - -webkit-border-bottom-right-radius: 6px; - border-bottom-right-radius: 6px; - -moz-border-radius-topright: 6px; - -moz-border-radius-bottomright: 6px; -} - -.btn-group > .btn:hover, -.btn-group > .btn:focus, -.btn-group > .btn:active, -.btn-group > .btn.active { - z-index: 2; -} - -.btn-group .dropdown-toggle:active, -.btn-group.open .dropdown-toggle { - outline: 0; -} - -.btn-group > .btn + .dropdown-toggle { - *padding-top: 5px; - padding-right: 8px; - *padding-bottom: 5px; - padding-left: 8px; - -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn-group > .btn-mini + .dropdown-toggle { - *padding-top: 2px; - padding-right: 5px; - *padding-bottom: 2px; - padding-left: 5px; -} - -.btn-group > .btn-small + .dropdown-toggle { - *padding-top: 5px; - *padding-bottom: 4px; -} - -.btn-group > .btn-large + .dropdown-toggle { - *padding-top: 7px; - padding-right: 12px; - *padding-bottom: 7px; - padding-left: 12px; -} - -.btn-group.open .dropdown-toggle { - background-image: none; - -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn-group.open .btn.dropdown-toggle { - background-color: #e6e6e6; -} - -.btn-group.open .btn-primary.dropdown-toggle { - background-color: #0044cc; -} - -.btn-group.open .btn-warning.dropdown-toggle { - background-color: #f89406; -} - -.btn-group.open .btn-danger.dropdown-toggle { - background-color: #bd362f; -} - -.btn-group.open .btn-success.dropdown-toggle { - background-color: #51a351; -} - -.btn-group.open .btn-info.dropdown-toggle { - background-color: #2f96b4; -} - -.btn-group.open .btn-inverse.dropdown-toggle { - background-color: #222222; -} - -.btn .caret { - margin-top: 8px; - margin-left: 0; -} - -.btn-large .caret { - margin-top: 6px; -} - -.btn-large .caret { - border-top-width: 5px; - border-right-width: 5px; - border-left-width: 5px; -} - -.btn-mini .caret, -.btn-small .caret { - margin-top: 8px; -} - -.dropup .btn-large .caret { - border-bottom-width: 5px; -} - -.btn-primary .caret, -.btn-warning .caret, -.btn-danger .caret, -.btn-info .caret, -.btn-success .caret, -.btn-inverse .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} - -.btn-group-vertical { - display: inline-block; - *display: inline; - /* IE7 inline-block hack */ - - *zoom: 1; -} - -.btn-group-vertical > .btn { - display: block; - float: none; - max-width: 100%; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.btn-group-vertical > .btn + .btn { - margin-top: -1px; - margin-left: 0; -} - -.btn-group-vertical > .btn:first-child { - -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; -} - -.btn-group-vertical > .btn:last-child { - -webkit-border-radius: 0 0 4px 4px; - -moz-border-radius: 0 0 4px 4px; - border-radius: 0 0 4px 4px; -} - -.btn-group-vertical > .btn-large:first-child { - -webkit-border-radius: 6px 6px 0 0; - -moz-border-radius: 6px 6px 0 0; - border-radius: 6px 6px 0 0; -} - -.btn-group-vertical > .btn-large:last-child { - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; -} - -.alert { - padding: 8px 35px 8px 14px; - margin-bottom: 20px; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - background-color: #fcf8e3; - border: 1px solid #fbeed5; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.alert, -.alert h4 { - color: #c09853; -} - -.alert h4 { - margin: 0; -} - -.alert .close { - position: relative; - top: -2px; - right: -21px; - line-height: 20px; -} - -.alert-success { - color: #468847; - background-color: #dff0d8; - border-color: #d6e9c6; -} - -.alert-success h4 { - color: #468847; -} - -.alert-danger, -.alert-error { - color: #b94a48; - background-color: #f2dede; - border-color: #eed3d7; -} - -.alert-danger h4, -.alert-error h4 { - color: #b94a48; -} - -.alert-info { - color: #3a87ad; - background-color: #d9edf7; - border-color: #bce8f1; -} - -.alert-info h4 { - color: #3a87ad; -} - -.alert-block { - padding-top: 14px; - padding-bottom: 14px; -} - -.alert-block > p, -.alert-block > ul { - margin-bottom: 0; -} - -.alert-block p + p { - margin-top: 5px; -} - -.nav { - margin-bottom: 20px; - margin-left: 0; - list-style: none; -} - -.nav > li > a { - display: block; -} - -.nav > li > a:hover, -.nav > li > a:focus { - text-decoration: none; - background-color: #eeeeee; -} - -.nav > li > a > img { - max-width: none; -} - -.nav > .pull-right { - float: right; -} - -.nav-header { - display: block; - padding: 3px 15px; - font-size: 11px; - font-weight: bold; - line-height: 20px; - color: #999999; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - text-transform: uppercase; -} - -.nav li + .nav-header { - margin-top: 9px; -} - -.nav-list { - padding-right: 15px; - padding-left: 15px; - margin-bottom: 0; -} - -.nav-list > li > a, -.nav-list .nav-header { - margin-right: -15px; - margin-left: -15px; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); -} - -.nav-list > li > a { - padding: 3px 15px; -} - -.nav-list > .active > a, -.nav-list > .active > a:hover, -.nav-list > .active > a:focus { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); - background-color: #0088cc; -} - -.nav-list [class^="icon-"], -.nav-list [class*=" icon-"] { - margin-right: 2px; -} - -.nav-list .divider { - *width: 100%; - height: 1px; - margin: 9px 1px; - *margin: -5px 0 5px; - overflow: hidden; - background-color: #e5e5e5; - border-bottom: 1px solid #ffffff; -} - -.nav-tabs, -.nav-pills { - *zoom: 1; -} - -.nav-tabs:before, -.nav-pills:before, -.nav-tabs:after, -.nav-pills:after { - display: table; - line-height: 0; - content: ""; -} - -.nav-tabs:after, -.nav-pills:after { - clear: both; -} - -.nav-tabs > li, -.nav-pills > li { - float: left; -} - -.nav-tabs > li > a, -.nav-pills > li > a { - padding-right: 12px; - padding-left: 12px; - margin-right: 2px; - line-height: 14px; -} - -.nav-tabs { - border-bottom: 1px solid #ddd; -} - -.nav-tabs > li { - margin-bottom: -1px; -} - -.nav-tabs > li > a { - padding-top: 8px; - padding-bottom: 8px; - line-height: 20px; - border: 1px solid transparent; - -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; -} - -.nav-tabs > li > a:hover, -.nav-tabs > li > a:focus { - border-color: #eeeeee #eeeeee #dddddd; -} - -.nav-tabs > .active > a, -.nav-tabs > .active > a:hover, -.nav-tabs > .active > a:focus { - color: #555555; - cursor: default; - background-color: #ffffff; - border: 1px solid #ddd; - border-bottom-color: transparent; -} - -.nav-pills > li > a { - padding-top: 8px; - padding-bottom: 8px; - margin-top: 2px; - margin-bottom: 2px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; -} - -.nav-pills > .active > a, -.nav-pills > .active > a:hover, -.nav-pills > .active > a:focus { - color: #ffffff; - background-color: #0088cc; -} - -.nav-stacked > li { - float: none; -} - -.nav-stacked > li > a { - margin-right: 0; -} - -.nav-tabs.nav-stacked { - border-bottom: 0; -} - -.nav-tabs.nav-stacked > li > a { - border: 1px solid #ddd; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.nav-tabs.nav-stacked > li:first-child > a { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-topright: 4px; - -moz-border-radius-topleft: 4px; -} - -.nav-tabs.nav-stacked > li:last-child > a { - -webkit-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px; - -webkit-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px; - -moz-border-radius-bottomright: 4px; - -moz-border-radius-bottomleft: 4px; -} - -.nav-tabs.nav-stacked > li > a:hover, -.nav-tabs.nav-stacked > li > a:focus { - z-index: 2; - border-color: #ddd; -} - -.nav-pills.nav-stacked > li > a { - margin-bottom: 3px; -} - -.nav-pills.nav-stacked > li:last-child > a { - margin-bottom: 1px; -} - -.nav-tabs .dropdown-menu { - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; -} - -.nav-pills .dropdown-menu { - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.nav .dropdown-toggle .caret { - margin-top: 6px; - border-top-color: #0088cc; - border-bottom-color: #0088cc; -} - -.nav .dropdown-toggle:hover .caret, -.nav .dropdown-toggle:focus .caret { - border-top-color: #005580; - border-bottom-color: #005580; -} - -/* move down carets for tabs */ - -.nav-tabs .dropdown-toggle .caret { - margin-top: 8px; -} - -.nav .active .dropdown-toggle .caret { - border-top-color: #fff; - border-bottom-color: #fff; -} - -.nav-tabs .active .dropdown-toggle .caret { - border-top-color: #555555; - border-bottom-color: #555555; -} - -.nav > .dropdown.active > a:hover, -.nav > .dropdown.active > a:focus { - cursor: pointer; -} - -.nav-tabs .open .dropdown-toggle, -.nav-pills .open .dropdown-toggle, -.nav > li.dropdown.open.active > a:hover, -.nav > li.dropdown.open.active > a:focus { - color: #ffffff; - background-color: #999999; - border-color: #999999; -} - -.nav li.dropdown.open .caret, -.nav li.dropdown.open.active .caret, -.nav li.dropdown.open a:hover .caret, -.nav li.dropdown.open a:focus .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; - opacity: 1; - filter: alpha(opacity=100); -} - -.tabs-stacked .open > a:hover, -.tabs-stacked .open > a:focus { - border-color: #999999; -} - -.tabbable { - *zoom: 1; -} - -.tabbable:before, -.tabbable:after { - display: table; - line-height: 0; - content: ""; -} - -.tabbable:after { - clear: both; -} - -.tab-content { - overflow: auto; -} - -.tabs-below > .nav-tabs, -.tabs-right > .nav-tabs, -.tabs-left > .nav-tabs { - border-bottom: 0; -} - -.tab-content > .tab-pane, -.pill-content > .pill-pane { - display: none; -} - -.tab-content > .active, -.pill-content > .active { - display: block; -} - -.tabs-below > .nav-tabs { - border-top: 1px solid #ddd; -} - -.tabs-below > .nav-tabs > li { - margin-top: -1px; - margin-bottom: 0; -} - -.tabs-below > .nav-tabs > li > a { - -webkit-border-radius: 0 0 4px 4px; - -moz-border-radius: 0 0 4px 4px; - border-radius: 0 0 4px 4px; -} - -.tabs-below > .nav-tabs > li > a:hover, -.tabs-below > .nav-tabs > li > a:focus { - border-top-color: #ddd; - border-bottom-color: transparent; -} - -.tabs-below > .nav-tabs > .active > a, -.tabs-below > .nav-tabs > .active > a:hover, -.tabs-below > .nav-tabs > .active > a:focus { - border-color: transparent #ddd #ddd #ddd; -} - -.tabs-left > .nav-tabs > li, -.tabs-right > .nav-tabs > li { - float: none; -} - -.tabs-left > .nav-tabs > li > a, -.tabs-right > .nav-tabs > li > a { - min-width: 74px; - margin-right: 0; - margin-bottom: 3px; -} - -.tabs-left > .nav-tabs { - float: left; - margin-right: 19px; - border-right: 1px solid #ddd; -} - -.tabs-left > .nav-tabs > li > a { - margin-right: -1px; - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} - -.tabs-left > .nav-tabs > li > a:hover, -.tabs-left > .nav-tabs > li > a:focus { - border-color: #eeeeee #dddddd #eeeeee #eeeeee; -} - -.tabs-left > .nav-tabs .active > a, -.tabs-left > .nav-tabs .active > a:hover, -.tabs-left > .nav-tabs .active > a:focus { - border-color: #ddd transparent #ddd #ddd; - *border-right-color: #ffffff; -} - -.tabs-right > .nav-tabs { - float: right; - margin-left: 19px; - border-left: 1px solid #ddd; -} - -.tabs-right > .nav-tabs > li > a { - margin-left: -1px; - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.tabs-right > .nav-tabs > li > a:hover, -.tabs-right > .nav-tabs > li > a:focus { - border-color: #eeeeee #eeeeee #eeeeee #dddddd; -} - -.tabs-right > .nav-tabs .active > a, -.tabs-right > .nav-tabs .active > a:hover, -.tabs-right > .nav-tabs .active > a:focus { - border-color: #ddd #ddd #ddd transparent; - *border-left-color: #ffffff; -} - -.nav > .disabled > a { - color: #999999; -} - -.nav > .disabled > a:hover, -.nav > .disabled > a:focus { - text-decoration: none; - cursor: default; - background-color: transparent; -} - -.navbar { - *position: relative; - *z-index: 2; - margin-bottom: 20px; - overflow: visible; -} - -.navbar-inner { - min-height: 40px; - padding-right: 20px; - padding-left: 20px; - background-color: #fafafa; - background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2)); - background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2); - background-image: -o-linear-gradient(top, #ffffff, #f2f2f2); - background-image: linear-gradient(to bottom, #ffffff, #f2f2f2); - background-repeat: repeat-x; - border: 1px solid #d4d4d4; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0); - *zoom: 1; - -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); - -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); - box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); -} - -.navbar-inner:before, -.navbar-inner:after { - display: table; - line-height: 0; - content: ""; -} - -.navbar-inner:after { - clear: both; -} - -.navbar .container { - width: auto; -} - -.nav-collapse.collapse { - height: auto; - overflow: visible; -} - -.navbar .brand { - display: block; - float: left; - padding: 10px 20px 10px; - margin-left: -20px; - font-size: 20px; - font-weight: 200; - color: #777777; - text-shadow: 0 1px 0 #ffffff; -} - -.navbar .brand:hover, -.navbar .brand:focus { - text-decoration: none; -} - -.navbar-text { - margin-bottom: 0; - line-height: 40px; - color: #777777; -} - -.navbar-link { - color: #777777; -} - -.navbar-link:hover, -.navbar-link:focus { - color: #333333; -} - -.navbar .divider-vertical { - height: 40px; - margin: 0 9px; - border-right: 1px solid #ffffff; - border-left: 1px solid #f2f2f2; -} - -.navbar .btn, -.navbar .btn-group { - margin-top: 5px; -} - -.navbar .btn-group .btn, -.navbar .input-prepend .btn, -.navbar .input-append .btn, -.navbar .input-prepend .btn-group, -.navbar .input-append .btn-group { - margin-top: 0; -} - -.navbar-form { - margin-bottom: 0; - *zoom: 1; -} - -.navbar-form:before, -.navbar-form:after { - display: table; - line-height: 0; - content: ""; -} - -.navbar-form:after { - clear: both; -} - -.navbar-form input, -.navbar-form select, -.navbar-form .radio, -.navbar-form .checkbox { - margin-top: 5px; -} - -.navbar-form input, -.navbar-form select, -.navbar-form .btn { - display: inline-block; - margin-bottom: 0; -} - -.navbar-form input[type="image"], -.navbar-form input[type="checkbox"], -.navbar-form input[type="radio"] { - margin-top: 3px; -} - -.navbar-form .input-append, -.navbar-form .input-prepend { - margin-top: 5px; - white-space: nowrap; -} - -.navbar-form .input-append input, -.navbar-form .input-prepend input { - margin-top: 0; -} - -.navbar-search { - position: relative; - float: left; - margin-top: 5px; - margin-bottom: 0; -} - -.navbar-search .search-query { - padding: 4px 14px; - margin-bottom: 0; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 13px; - font-weight: normal; - line-height: 1; - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; -} - -.navbar-static-top { - position: static; - margin-bottom: 0; -} - -.navbar-static-top .navbar-inner { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.navbar-fixed-top, -.navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - z-index: 1030; - margin-bottom: 0; -} - -.navbar-fixed-top .navbar-inner, -.navbar-static-top .navbar-inner { - border-width: 0 0 1px; -} - -.navbar-fixed-bottom .navbar-inner { - border-width: 1px 0 0; -} - -.navbar-fixed-top .navbar-inner, -.navbar-fixed-bottom .navbar-inner { - padding-right: 0; - padding-left: 0; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.navbar-static-top .container, -.navbar-fixed-top .container, -.navbar-fixed-bottom .container { - width: 940px; -} - -.navbar-fixed-top { - top: 0; -} - -.navbar-fixed-top .navbar-inner, -.navbar-static-top .navbar-inner { - -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); -} - -.navbar-fixed-bottom { - bottom: 0; -} - -.navbar-fixed-bottom .navbar-inner { - -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); - box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); -} - -.navbar .nav { - position: relative; - left: 0; - display: block; - float: left; - margin: 0 10px 0 0; -} - -.navbar .nav.pull-right { - float: right; - margin-right: 0; -} - -.navbar .nav > li { - float: left; -} - -.navbar .nav > li > a { - float: none; - padding: 10px 15px 10px; - color: #777777; - text-decoration: none; - text-shadow: 0 1px 0 #ffffff; -} - -.navbar .nav .dropdown-toggle .caret { - margin-top: 8px; -} - -.navbar .nav > li > a:focus, -.navbar .nav > li > a:hover { - color: #333333; - text-decoration: none; - background-color: transparent; -} - -.navbar .nav > .active > a, -.navbar .nav > .active > a:hover, -.navbar .nav > .active > a:focus { - color: #555555; - text-decoration: none; - background-color: #e5e5e5; - -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); - -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); - box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); -} - -.navbar .btn-navbar { - display: none; - float: right; - padding: 7px 10px; - margin-right: 5px; - margin-left: 5px; - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #ededed; - *background-color: #e5e5e5; - background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5)); - background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5); - background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5); - background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5); - background-repeat: repeat-x; - border-color: #e5e5e5 #e5e5e5 #bfbfbf; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); -} - -.navbar .btn-navbar:hover, -.navbar .btn-navbar:focus, -.navbar .btn-navbar:active, -.navbar .btn-navbar.active, -.navbar .btn-navbar.disabled, -.navbar .btn-navbar[disabled] { - color: #ffffff; - background-color: #e5e5e5; - *background-color: #d9d9d9; -} - -.navbar .btn-navbar:active, -.navbar .btn-navbar.active { - background-color: #cccccc \9; -} - -.navbar .btn-navbar .icon-bar { - display: block; - width: 18px; - height: 2px; - background-color: #f5f5f5; - -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; - -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); - -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); -} - -.btn-navbar .icon-bar + .icon-bar { - margin-top: 3px; -} - -.navbar .nav > li > .dropdown-menu:before { - position: absolute; - top: -7px; - left: 9px; - display: inline-block; - border-right: 7px solid transparent; - border-bottom: 7px solid #ccc; - border-left: 7px solid transparent; - border-bottom-color: rgba(0, 0, 0, 0.2); - content: ''; -} - -.navbar .nav > li > .dropdown-menu:after { - position: absolute; - top: -6px; - left: 10px; - display: inline-block; - border-right: 6px solid transparent; - border-bottom: 6px solid #ffffff; - border-left: 6px solid transparent; - content: ''; -} - -.navbar-fixed-bottom .nav > li > .dropdown-menu:before { - top: auto; - bottom: -7px; - border-top: 7px solid #ccc; - border-bottom: 0; - border-top-color: rgba(0, 0, 0, 0.2); -} - -.navbar-fixed-bottom .nav > li > .dropdown-menu:after { - top: auto; - bottom: -6px; - border-top: 6px solid #ffffff; - border-bottom: 0; -} - -.navbar .nav li.dropdown > a:hover .caret, -.navbar .nav li.dropdown > a:focus .caret { - border-top-color: #333333; - border-bottom-color: #333333; -} - -.navbar .nav li.dropdown.open > .dropdown-toggle, -.navbar .nav li.dropdown.active > .dropdown-toggle, -.navbar .nav li.dropdown.open.active > .dropdown-toggle { - color: #555555; - background-color: #e5e5e5; -} - -.navbar .nav li.dropdown > .dropdown-toggle .caret { - border-top-color: #777777; - border-bottom-color: #777777; -} - -.navbar .nav li.dropdown.open > .dropdown-toggle .caret, -.navbar .nav li.dropdown.active > .dropdown-toggle .caret, -.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret { - border-top-color: #555555; - border-bottom-color: #555555; -} - -.navbar .pull-right > li > .dropdown-menu, -.navbar .nav > li > .dropdown-menu.pull-right { - right: 0; - left: auto; -} - -.navbar .pull-right > li > .dropdown-menu:before, -.navbar .nav > li > .dropdown-menu.pull-right:before { - right: 12px; - left: auto; -} - -.navbar .pull-right > li > .dropdown-menu:after, -.navbar .nav > li > .dropdown-menu.pull-right:after { - right: 13px; - left: auto; -} - -.navbar .pull-right > li > .dropdown-menu .dropdown-menu, -.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu { - right: 100%; - left: auto; - margin-right: -1px; - margin-left: 0; - -webkit-border-radius: 6px 0 6px 6px; - -moz-border-radius: 6px 0 6px 6px; - border-radius: 6px 0 6px 6px; -} - -.navbar-inverse .navbar-inner { - background-color: #1b1b1b; - background-image: -moz-linear-gradient(top, #222222, #111111); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111)); - background-image: -webkit-linear-gradient(top, #222222, #111111); - background-image: -o-linear-gradient(top, #222222, #111111); - background-image: linear-gradient(to bottom, #222222, #111111); - background-repeat: repeat-x; - border-color: #252525; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0); -} - -.navbar-inverse .brand, -.navbar-inverse .nav > li > a { - color: #999999; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); -} - -.navbar-inverse .brand:hover, -.navbar-inverse .nav > li > a:hover, -.navbar-inverse .brand:focus, -.navbar-inverse .nav > li > a:focus { - color: #ffffff; -} - -.navbar-inverse .brand { - color: #999999; -} - -.navbar-inverse .navbar-text { - color: #999999; -} - -.navbar-inverse .nav > li > a:focus, -.navbar-inverse .nav > li > a:hover { - color: #ffffff; - background-color: transparent; -} - -.navbar-inverse .nav .active > a, -.navbar-inverse .nav .active > a:hover, -.navbar-inverse .nav .active > a:focus { - color: #ffffff; - background-color: #111111; -} - -.navbar-inverse .navbar-link { - color: #999999; -} - -.navbar-inverse .navbar-link:hover, -.navbar-inverse .navbar-link:focus { - color: #ffffff; -} - -.navbar-inverse .divider-vertical { - border-right-color: #222222; - border-left-color: #111111; -} - -.navbar-inverse .nav li.dropdown.open > .dropdown-toggle, -.navbar-inverse .nav li.dropdown.active > .dropdown-toggle, -.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle { - color: #ffffff; - background-color: #111111; -} - -.navbar-inverse .nav li.dropdown > a:hover .caret, -.navbar-inverse .nav li.dropdown > a:focus .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} - -.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret { - border-top-color: #999999; - border-bottom-color: #999999; -} - -.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret, -.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret, -.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} - -.navbar-inverse .navbar-search .search-query { - color: #ffffff; - background-color: #515151; - border-color: #111111; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - -webkit-transition: none; - -moz-transition: none; - -o-transition: none; - transition: none; -} - -.navbar-inverse .navbar-search .search-query:-moz-placeholder { - color: #cccccc; -} - -.navbar-inverse .navbar-search .search-query:-ms-input-placeholder { - color: #cccccc; -} - -.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder { - color: #cccccc; -} - -.navbar-inverse .navbar-search .search-query:focus, -.navbar-inverse .navbar-search .search-query.focused { - padding: 5px 15px; - color: #333333; - text-shadow: 0 1px 0 #ffffff; - background-color: #ffffff; - border: 0; - outline: 0; - -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); - -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); - box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); -} - -.navbar-inverse .btn-navbar { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #0e0e0e; - *background-color: #040404; - background-image: -moz-linear-gradient(top, #151515, #040404); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404)); - background-image: -webkit-linear-gradient(top, #151515, #040404); - background-image: -o-linear-gradient(top, #151515, #040404); - background-image: linear-gradient(to bottom, #151515, #040404); - background-repeat: repeat-x; - border-color: #040404 #040404 #000000; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.navbar-inverse .btn-navbar:hover, -.navbar-inverse .btn-navbar:focus, -.navbar-inverse .btn-navbar:active, -.navbar-inverse .btn-navbar.active, -.navbar-inverse .btn-navbar.disabled, -.navbar-inverse .btn-navbar[disabled] { - color: #ffffff; - background-color: #040404; - *background-color: #000000; -} - -.navbar-inverse .btn-navbar:active, -.navbar-inverse .btn-navbar.active { - background-color: #000000 \9; -} - -.breadcrumb { - padding: 8px 15px; - margin: 0 0 20px; - list-style: none; - background-color: #f5f5f5; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.breadcrumb > li { - display: inline-block; - *display: inline; - text-shadow: 0 1px 0 #ffffff; - *zoom: 1; -} - -.breadcrumb > li > .divider { - padding: 0 5px; - color: #ccc; -} - -.breadcrumb > .active { - color: #999999; -} - -.pagination { - margin: 20px 0; -} - -.pagination ul { - display: inline-block; - *display: inline; - margin-bottom: 0; - margin-left: 0; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - *zoom: 1; - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.pagination ul > li { - display: inline; -} - -.pagination ul > li > a, -.pagination ul > li > span { - float: left; - padding: 4px 12px; - line-height: 20px; - text-decoration: none; - background-color: #ffffff; - border: 1px solid #dddddd; - border-left-width: 0; -} - -.pagination ul > li > a:hover, -.pagination ul > li > a:focus, -.pagination ul > .active > a, -.pagination ul > .active > span { - background-color: #f5f5f5; -} - -.pagination ul > .active > a, -.pagination ul > .active > span { - color: #999999; - cursor: default; -} - -.pagination ul > .disabled > span, -.pagination ul > .disabled > a, -.pagination ul > .disabled > a:hover, -.pagination ul > .disabled > a:focus { - color: #999999; - cursor: default; - background-color: transparent; -} - -.pagination ul > li:first-child > a, -.pagination ul > li:first-child > span { - border-left-width: 1px; - -webkit-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px; - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; - -moz-border-radius-topleft: 4px; -} - -.pagination ul > li:last-child > a, -.pagination ul > li:last-child > span { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px; - -moz-border-radius-topright: 4px; - -moz-border-radius-bottomright: 4px; -} - -.pagination-centered { - text-align: center; -} - -.pagination-right { - text-align: right; -} - -.pagination-large ul > li > a, -.pagination-large ul > li > span { - padding: 11px 19px; - font-size: 17.5px; -} - -.pagination-large ul > li:first-child > a, -.pagination-large ul > li:first-child > span { - -webkit-border-bottom-left-radius: 6px; - border-bottom-left-radius: 6px; - -webkit-border-top-left-radius: 6px; - border-top-left-radius: 6px; - -moz-border-radius-bottomleft: 6px; - -moz-border-radius-topleft: 6px; -} - -.pagination-large ul > li:last-child > a, -.pagination-large ul > li:last-child > span { - -webkit-border-top-right-radius: 6px; - border-top-right-radius: 6px; - -webkit-border-bottom-right-radius: 6px; - border-bottom-right-radius: 6px; - -moz-border-radius-topright: 6px; - -moz-border-radius-bottomright: 6px; -} - -.pagination-mini ul > li:first-child > a, -.pagination-small ul > li:first-child > a, -.pagination-mini ul > li:first-child > span, -.pagination-small ul > li:first-child > span { - -webkit-border-bottom-left-radius: 3px; - border-bottom-left-radius: 3px; - -webkit-border-top-left-radius: 3px; - border-top-left-radius: 3px; - -moz-border-radius-bottomleft: 3px; - -moz-border-radius-topleft: 3px; -} - -.pagination-mini ul > li:last-child > a, -.pagination-small ul > li:last-child > a, -.pagination-mini ul > li:last-child > span, -.pagination-small ul > li:last-child > span { - -webkit-border-top-right-radius: 3px; - border-top-right-radius: 3px; - -webkit-border-bottom-right-radius: 3px; - border-bottom-right-radius: 3px; - -moz-border-radius-topright: 3px; - -moz-border-radius-bottomright: 3px; -} - -.pagination-small ul > li > a, -.pagination-small ul > li > span { - padding: 2px 10px; - font-size: 11.9px; -} - -.pagination-mini ul > li > a, -.pagination-mini ul > li > span { - padding: 0 6px; - font-size: 10.5px; -} - -.pager { - margin: 20px 0; - text-align: center; - list-style: none; - *zoom: 1; -} - -.pager:before, -.pager:after { - display: table; - line-height: 0; - content: ""; -} - -.pager:after { - clear: both; -} - -.pager li { - display: inline; -} - -.pager li > a, -.pager li > span { - display: inline-block; - padding: 5px 14px; - background-color: #fff; - border: 1px solid #ddd; - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; -} - -.pager li > a:hover, -.pager li > a:focus { - text-decoration: none; - background-color: #f5f5f5; -} - -.pager .next > a, -.pager .next > span { - float: right; -} - -.pager .previous > a, -.pager .previous > span { - float: left; -} - -.pager .disabled > a, -.pager .disabled > a:hover, -.pager .disabled > a:focus, -.pager .disabled > span { - color: #999999; - cursor: default; - background-color: #fff; -} - -.modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - background-color: #000000; -} - -.modal-backdrop.fade { - opacity: 0; -} - -.modal-backdrop, -.modal-backdrop.fade.in { - opacity: 0.8; - filter: alpha(opacity=80); -} - -.modal { - position: fixed; - top: 10%; - left: 50%; - z-index: 1050; - width: 560px; - margin-left: -280px; - background-color: #ffffff; - border: 1px solid #999; - border: 1px solid rgba(0, 0, 0, 0.3); - *border: 1px solid #999; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - outline: none; - -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -webkit-background-clip: padding-box; - -moz-background-clip: padding-box; - background-clip: padding-box; -} - -.modal.fade { - top: -25%; - -webkit-transition: opacity 0.3s linear, top 0.3s ease-out; - -moz-transition: opacity 0.3s linear, top 0.3s ease-out; - -o-transition: opacity 0.3s linear, top 0.3s ease-out; - transition: opacity 0.3s linear, top 0.3s ease-out; -} - -.modal.fade.in { - top: 10%; -} - -.modal-header { - padding: 9px 15px; - border-bottom: 1px solid #eee; -} - -.modal-header .close { - margin-top: 2px; -} - -.modal-header h3 { - margin: 0; - line-height: 30px; -} - -.modal-body { - position: relative; - max-height: 400px; - padding: 15px; - overflow-y: auto; -} - -.modal-form { - margin-bottom: 0; -} - -.modal-footer { - padding: 14px 15px 15px; - margin-bottom: 0; - text-align: right; - background-color: #f5f5f5; - border-top: 1px solid #ddd; - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; - *zoom: 1; - -webkit-box-shadow: inset 0 1px 0 #ffffff; - -moz-box-shadow: inset 0 1px 0 #ffffff; - box-shadow: inset 0 1px 0 #ffffff; -} - -.modal-footer:before, -.modal-footer:after { - display: table; - line-height: 0; - content: ""; -} - -.modal-footer:after { - clear: both; -} - -.modal-footer .btn + .btn { - margin-bottom: 0; - margin-left: 5px; -} - -.modal-footer .btn-group .btn + .btn { - margin-left: -1px; -} - -.modal-footer .btn-block + .btn-block { - margin-left: 0; -} - -.tooltip { - position: absolute; - z-index: 1030; - display: block; - font-size: 11px; - line-height: 1.4; - opacity: 0; - filter: alpha(opacity=0); - visibility: visible; -} - -.tooltip.in { - opacity: 0.8; - filter: alpha(opacity=80); -} - -.tooltip.top { - padding: 5px 0; - margin-top: -3px; -} - -.tooltip.right { - padding: 0 5px; - margin-left: 3px; -} - -.tooltip.bottom { - padding: 5px 0; - margin-top: 3px; -} - -.tooltip.left { - padding: 0 5px; - margin-left: -3px; -} - -.tooltip-inner { - max-width: 200px; - padding: 8px; - color: #ffffff; - text-align: center; - text-decoration: none; - background-color: #000000; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} - -.tooltip.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-top-color: #000000; - border-width: 5px 5px 0; -} - -.tooltip.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-right-color: #000000; - border-width: 5px 5px 5px 0; -} - -.tooltip.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-left-color: #000000; - border-width: 5px 0 5px 5px; -} - -.tooltip.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-bottom-color: #000000; - border-width: 0 5px 5px; -} - -.popover { - position: absolute; - top: 0; - left: 0; - z-index: 1010; - display: none; - max-width: 276px; - padding: 1px; - text-align: left; - white-space: normal; - background-color: #ffffff; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -webkit-background-clip: padding-box; - -moz-background-clip: padding; - background-clip: padding-box; -} - -.popover.top { - margin-top: -10px; -} - -.popover.right { - margin-left: 10px; -} - -.popover.bottom { - margin-top: 10px; -} - -.popover.left { - margin-left: -10px; -} - -.popover-title { - padding: 8px 14px; - margin: 0; - font-size: 14px; - font-weight: normal; - line-height: 18px; - background-color: #f7f7f7; - border-bottom: 1px solid #ebebeb; - -webkit-border-radius: 5px 5px 0 0; - -moz-border-radius: 5px 5px 0 0; - border-radius: 5px 5px 0 0; -} - -.popover-title:empty { - display: none; -} - -.popover-content { - padding: 9px 14px; -} - -.popover .arrow, -.popover .arrow:after { - position: absolute; - display: block; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} - -.popover .arrow { - border-width: 11px; -} - -.popover .arrow:after { - border-width: 10px; - content: ""; -} - -.popover.top .arrow { - bottom: -11px; - left: 50%; - margin-left: -11px; - border-top-color: #999; - border-top-color: rgba(0, 0, 0, 0.25); - border-bottom-width: 0; -} - -.popover.top .arrow:after { - bottom: 1px; - margin-left: -10px; - border-top-color: #ffffff; - border-bottom-width: 0; -} - -.popover.right .arrow { - top: 50%; - left: -11px; - margin-top: -11px; - border-right-color: #999; - border-right-color: rgba(0, 0, 0, 0.25); - border-left-width: 0; -} - -.popover.right .arrow:after { - bottom: -10px; - left: 1px; - border-right-color: #ffffff; - border-left-width: 0; -} - -.popover.bottom .arrow { - top: -11px; - left: 50%; - margin-left: -11px; - border-bottom-color: #999; - border-bottom-color: rgba(0, 0, 0, 0.25); - border-top-width: 0; -} - -.popover.bottom .arrow:after { - top: 1px; - margin-left: -10px; - border-bottom-color: #ffffff; - border-top-width: 0; -} - -.popover.left .arrow { - top: 50%; - right: -11px; - margin-top: -11px; - border-left-color: #999; - border-left-color: rgba(0, 0, 0, 0.25); - border-right-width: 0; -} - -.popover.left .arrow:after { - right: 1px; - bottom: -10px; - border-left-color: #ffffff; - border-right-width: 0; -} - -.thumbnails { - margin-left: -20px; - list-style: none; - *zoom: 1; -} - -.thumbnails:before, -.thumbnails:after { - display: table; - line-height: 0; - content: ""; -} - -.thumbnails:after { - clear: both; -} - -.row-fluid .thumbnails { - margin-left: 0; -} - -.thumbnails > li { - float: left; - margin-bottom: 20px; - margin-left: 20px; -} - -.thumbnail { - display: block; - padding: 4px; - line-height: 20px; - border: 1px solid #ddd; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); - -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); - -webkit-transition: all 0.2s ease-in-out; - -moz-transition: all 0.2s ease-in-out; - -o-transition: all 0.2s ease-in-out; - transition: all 0.2s ease-in-out; -} - -a.thumbnail:hover, -a.thumbnail:focus { - border-color: #0088cc; - -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); - -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); - box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); -} - -.thumbnail > img { - display: block; - max-width: 100%; - margin-right: auto; - margin-left: auto; -} - -.thumbnail .caption { - padding: 9px; - color: #555555; -} - -.media, -.media-body { - overflow: hidden; - *overflow: visible; - zoom: 1; -} - -.media, -.media .media { - margin-top: 15px; -} - -.media:first-child { - margin-top: 0; -} - -.media-object { - display: block; -} - -.media-heading { - margin: 0 0 5px; -} - -.media > .pull-left { - margin-right: 10px; -} - -.media > .pull-right { - margin-left: 10px; -} - -.media-list { - margin-left: 0; - list-style: none; -} - -.label, -.badge { - display: inline-block; - padding: 2px 4px; - font-size: 11.844px; - font-weight: bold; - line-height: 14px; - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - white-space: nowrap; - vertical-align: baseline; - background-color: #999999; -} - -.label { - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -.badge { - padding-right: 9px; - padding-left: 9px; - -webkit-border-radius: 9px; - -moz-border-radius: 9px; - border-radius: 9px; -} - -.label:empty, -.badge:empty { - display: none; -} - -a.label:hover, -a.label:focus, -a.badge:hover, -a.badge:focus { - color: #ffffff; - text-decoration: none; - cursor: pointer; -} - -.label-important, -.badge-important { - background-color: #b94a48; -} - -.label-important[href], -.badge-important[href] { - background-color: #953b39; -} - -.label-warning, -.badge-warning { - background-color: #f89406; -} - -.label-warning[href], -.badge-warning[href] { - background-color: #c67605; -} - -.label-success, -.badge-success { - background-color: #468847; -} - -.label-success[href], -.badge-success[href] { - background-color: #356635; -} - -.label-info, -.badge-info { - background-color: #3a87ad; -} - -.label-info[href], -.badge-info[href] { - background-color: #2d6987; -} - -.label-inverse, -.badge-inverse { - background-color: #333333; -} - -.label-inverse[href], -.badge-inverse[href] { - background-color: #1a1a1a; -} - -.btn .label, -.btn .badge { - position: relative; - top: -1px; -} - -.btn-mini .label, -.btn-mini .badge { - top: 0; -} - -@-webkit-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -@-moz-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -@-ms-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -@-o-keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} - -@keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -.progress { - height: 20px; - margin-bottom: 20px; - overflow: hidden; - background-color: #f7f7f7; - background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); - background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9); - background-repeat: repeat-x; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0); - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -} - -.progress .bar { - float: left; - width: 0; - height: 100%; - font-size: 12px; - color: #ffffff; - text-align: center; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #0e90d2; - background-image: -moz-linear-gradient(top, #149bdf, #0480be); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); - background-image: -webkit-linear-gradient(top, #149bdf, #0480be); - background-image: -o-linear-gradient(top, #149bdf, #0480be); - background-image: linear-gradient(to bottom, #149bdf, #0480be); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0); - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - -webkit-transition: width 0.6s ease; - -moz-transition: width 0.6s ease; - -o-transition: width 0.6s ease; - transition: width 0.6s ease; -} - -.progress .bar + .bar { - -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); - box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); -} - -.progress-striped .bar { - background-color: #149bdf; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - -webkit-background-size: 40px 40px; - -moz-background-size: 40px 40px; - -o-background-size: 40px 40px; - background-size: 40px 40px; -} - -.progress.active .bar { - -webkit-animation: progress-bar-stripes 2s linear infinite; - -moz-animation: progress-bar-stripes 2s linear infinite; - -ms-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; -} - -.progress-danger .bar, -.progress .bar-danger { - background-color: #dd514c; - background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); - background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); - background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); - background-image: linear-gradient(to bottom, #ee5f5b, #c43c35); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0); -} - -.progress-danger.progress-striped .bar, -.progress-striped .bar-danger { - background-color: #ee5f5b; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.progress-success .bar, -.progress .bar-success { - background-color: #5eb95e; - background-image: -moz-linear-gradient(top, #62c462, #57a957); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); - background-image: -webkit-linear-gradient(top, #62c462, #57a957); - background-image: -o-linear-gradient(top, #62c462, #57a957); - background-image: linear-gradient(to bottom, #62c462, #57a957); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0); -} - -.progress-success.progress-striped .bar, -.progress-striped .bar-success { - background-color: #62c462; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.progress-info .bar, -.progress .bar-info { - background-color: #4bb1cf; - background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); - background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); - background-image: -o-linear-gradient(top, #5bc0de, #339bb9); - background-image: linear-gradient(to bottom, #5bc0de, #339bb9); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0); -} - -.progress-info.progress-striped .bar, -.progress-striped .bar-info { - background-color: #5bc0de; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.progress-warning .bar, -.progress .bar-warning { - background-color: #faa732; - background-image: -moz-linear-gradient(top, #fbb450, #f89406); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); - background-image: -webkit-linear-gradient(top, #fbb450, #f89406); - background-image: -o-linear-gradient(top, #fbb450, #f89406); - background-image: linear-gradient(to bottom, #fbb450, #f89406); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); -} - -.progress-warning.progress-striped .bar, -.progress-striped .bar-warning { - background-color: #fbb450; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.accordion { - margin-bottom: 20px; -} - -.accordion-group { - margin-bottom: 2px; - border: 1px solid #e5e5e5; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.accordion-heading { - border-bottom: 0; -} - -.accordion-heading .accordion-toggle { - display: block; - padding: 8px 15px; -} - -.accordion-toggle { - cursor: pointer; -} - -.accordion-inner { - padding: 9px 15px; - border-top: 1px solid #e5e5e5; -} - -.carousel { - position: relative; - margin-bottom: 20px; - line-height: 1; -} - -.carousel-inner { - position: relative; - width: 100%; - overflow: hidden; -} - -.carousel-inner > .item { - position: relative; - display: none; - -webkit-transition: 0.6s ease-in-out left; - -moz-transition: 0.6s ease-in-out left; - -o-transition: 0.6s ease-in-out left; - transition: 0.6s ease-in-out left; -} - -.carousel-inner > .item > img, -.carousel-inner > .item > a > img { - display: block; - line-height: 1; -} - -.carousel-inner > .active, -.carousel-inner > .next, -.carousel-inner > .prev { - display: block; -} - -.carousel-inner > .active { - left: 0; -} - -.carousel-inner > .next, -.carousel-inner > .prev { - position: absolute; - top: 0; - width: 100%; -} - -.carousel-inner > .next { - left: 100%; -} - -.carousel-inner > .prev { - left: -100%; -} - -.carousel-inner > .next.left, -.carousel-inner > .prev.right { - left: 0; -} - -.carousel-inner > .active.left { - left: -100%; -} - -.carousel-inner > .active.right { - left: 100%; -} - -.carousel-control { - position: absolute; - top: 40%; - left: 15px; - width: 40px; - height: 40px; - margin-top: -20px; - font-size: 60px; - font-weight: 100; - line-height: 30px; - color: #ffffff; - text-align: center; - background: #222222; - border: 3px solid #ffffff; - -webkit-border-radius: 23px; - -moz-border-radius: 23px; - border-radius: 23px; - opacity: 0.5; - filter: alpha(opacity=50); -} - -.carousel-control.right { - right: 15px; - left: auto; -} - -.carousel-control:hover, -.carousel-control:focus { - color: #ffffff; - text-decoration: none; - opacity: 0.9; - filter: alpha(opacity=90); -} - -.carousel-indicators { - position: absolute; - top: 15px; - right: 15px; - z-index: 5; - margin: 0; - list-style: none; -} - -.carousel-indicators li { - display: block; - float: left; - width: 10px; - height: 10px; - margin-left: 5px; - text-indent: -999px; - background-color: #ccc; - background-color: rgba(255, 255, 255, 0.25); - border-radius: 5px; -} - -.carousel-indicators .active { - background-color: #fff; -} - -.carousel-caption { - position: absolute; - right: 0; - bottom: 0; - left: 0; - padding: 15px; - background: #333333; - background: rgba(0, 0, 0, 0.75); -} - -.carousel-caption h4, -.carousel-caption p { - line-height: 20px; - color: #ffffff; -} - -.carousel-caption h4 { - margin: 0 0 5px; -} - -.carousel-caption p { - margin-bottom: 0; -} - -.hero-unit { - padding: 60px; - margin-bottom: 30px; - font-size: 18px; - font-weight: 200; - line-height: 30px; - color: inherit; - background-color: #eeeeee; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.hero-unit h1 { - margin-bottom: 0; - font-size: 60px; - line-height: 1; - letter-spacing: -1px; - color: inherit; -} - -.hero-unit li { - line-height: 30px; -} - -.pull-right { - float: right; -} - -.pull-left { - float: left; -} - -.hide { - display: none; -} - -.show { - display: block; -} - -.invisible { - visibility: hidden; -} - -.affix { - position: fixed; -} diff --git a/css/normalize.css b/css/normalize.css deleted file mode 100755 index a9c6f52..0000000 --- a/css/normalize.css +++ /dev/null @@ -1,396 +0,0 @@ -/*! normalize.css v2.1.0 | MIT License | git.io/normalize */ - -/* ========================================================================== - HTML5 display definitions - ========================================================================== */ - -/** - * Correct `block` display not defined in IE 8/9. - */ - -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -main, -nav, -section, -summary { - display: block; -} - -/** - * Correct `inline-block` display not defined in IE 8/9. - */ - -audio, -canvas, -video { - display: inline-block; -} - -/** - * Prevent modern browsers from displaying `audio` without controls. - * Remove excess height in iOS 5 devices. - */ - -audio:not([controls]) { - display: none; - height: 0; -} - -/** - * Address styling not present in IE 8/9. - */ - -[hidden] { - display: none; -} - -/* ========================================================================== - Base - ========================================================================== */ - -/** - * 1. Set default font family to sans-serif. - * 2. Prevent iOS text size adjust after orientation change, without disabling - * user zoom. - */ - -html { - font-family: sans-serif; /* 1 */ - -webkit-text-size-adjust: 100%; /* 2 */ - -ms-text-size-adjust: 100%; /* 2 */ -} - -/** - * Remove default margin. - */ - -body { - margin: 0; -} - -/* ========================================================================== - Links - ========================================================================== */ - -/** - * Address `outline` inconsistency between Chrome and other browsers. - */ - -a:focus { - outline: thin dotted; -} - -/** - * Improve readability when focused and also mouse hovered in all browsers. - */ - -a:active, -a:hover { - outline: 0; -} - -/* ========================================================================== - Typography - ========================================================================== */ - -/** - * Address variable `h1` font-size and margin within `section` and `article` - * contexts in Firefox 4+, Safari 5, and Chrome. - */ - -h1 { - font-size: 2em; - margin: 0.67em 0; -} - -/** - * Address styling not present in IE 8/9, Safari 5, and Chrome. - */ - -abbr[title] { - border-bottom: 1px dotted; -} - -/** - * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. - */ - -b, -strong { - font-weight: bold; -} - -/** - * Address styling not present in Safari 5 and Chrome. - */ - -dfn { - font-style: italic; -} - -/** - * Address differences between Firefox and other browsers. - */ - -hr { - -moz-box-sizing: content-box; - box-sizing: content-box; - height: 0; -} - -/** - * Address styling not present in IE 8/9. - */ - -mark { - background: #ff0; - color: #000; -} - -/** - * Correct font family set oddly in Safari 5 and Chrome. - */ - -code, -kbd, -pre, -samp { - font-family: monospace, serif; - font-size: 1em; -} - -/** - * Improve readability of pre-formatted text in all browsers. - */ - -pre { - white-space: pre-wrap; -} - -/** - * Set consistent quote types. - */ - -q { - quotes: "\201C" "\201D" "\2018" "\2019"; -} - -/** - * Address inconsistent and variable font size in all browsers. - */ - -small { - font-size: 80%; -} - -/** - * Prevent `sub` and `sup` affecting `line-height` in all browsers. - */ - -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sup { - top: -0.5em; -} - -sub { - bottom: -0.25em; -} - -/* ========================================================================== - Embedded content - ========================================================================== */ - -/** - * Remove border when inside `a` element in IE 8/9. - */ - -img { - border: 0; -} - -/** - * Correct overflow displayed oddly in IE 9. - */ - -svg:not(:root) { - overflow: hidden; -} - -/* ========================================================================== - Figures - ========================================================================== */ - -/** - * Address margin not present in IE 8/9 and Safari 5. - */ - -figure { - margin: 0; -} - -/* ========================================================================== - Forms - ========================================================================== */ - -/** - * Define consistent border, margin, and padding. - */ - -fieldset { - border: 1px solid #c0c0c0; - margin: 0 2px; - padding: 0.35em 0.625em 0.75em; -} - -/** - * 1. Correct `color` not being inherited in IE 8/9. - * 2. Remove padding so people aren't caught out if they zero out fieldsets. - */ - -legend { - border: 0; /* 1 */ - padding: 0; /* 2 */ -} - -/** - * 1. Correct font family not being inherited in all browsers. - * 2. Correct font size not being inherited in all browsers. - * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. - */ - -button, -input, -select, -textarea { - font-family: inherit; /* 1 */ - font-size: 100%; /* 2 */ - margin: 0; /* 3 */ -} - -/** - * Address Firefox 4+ setting `line-height` on `input` using `!important` in - * the UA stylesheet. - */ - -button, -input { - line-height: normal; -} - -/** - * Address inconsistent `text-transform` inheritance for `button` and `select`. - * All other form control elements do not inherit `text-transform` values. - * Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. - * Correct `select` style inheritance in Firefox 4+ and Opera. - */ - -button, -select { - text-transform: none; -} - -/** - * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` - * and `video` controls. - * 2. Correct inability to style clickable `input` types in iOS. - * 3. Improve usability and consistency of cursor style between image-type - * `input` and others. - */ - -button, -html input[type="button"], /* 1 */ -input[type="reset"], -input[type="submit"] { - -webkit-appearance: button; /* 2 */ - cursor: pointer; /* 3 */ -} - -/** - * Re-set default cursor for disabled elements. - */ - -button[disabled], -html input[disabled] { - cursor: default; -} - -/** - * 1. Address box sizing set to `content-box` in IE 8/9. - * 2. Remove excess padding in IE 8/9. - */ - -input[type="checkbox"], -input[type="radio"] { - box-sizing: border-box; /* 1 */ - padding: 0; /* 2 */ -} - -/** - * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. - * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome - * (include `-moz` to future-proof). - */ - -input[type="search"] { - -webkit-appearance: textfield; /* 1 */ - -moz-box-sizing: content-box; - -webkit-box-sizing: content-box; /* 2 */ - box-sizing: content-box; -} - -/** - * Remove inner padding and search cancel button in Safari 5 and Chrome - * on OS X. - */ - -input[type="search"]::-webkit-search-cancel-button, -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} - -/** - * Remove inner padding and border in Firefox 4+. - */ - -button::-moz-focus-inner, -input::-moz-focus-inner { - border: 0; - padding: 0; -} - -/** - * 1. Remove default vertical scrollbar in IE 8/9. - * 2. Improve readability and alignment in all browsers. - */ - -textarea { - overflow: auto; /* 1 */ - vertical-align: top; /* 2 */ -} - -/* ========================================================================== - Tables - ========================================================================== */ - -/** - * Remove most spacing between table cells. - */ - -table { - border-collapse: collapse; - border-spacing: 0; -} diff --git a/css/style.css b/css/style.css deleted file mode 100755 index 86c81b0..0000000 --- a/css/style.css +++ /dev/null @@ -1,133 +0,0 @@ -/* - * - * This file is part of the digital testament management program - * DigiProof. - * - * By accessing this software, DigiProof, you are duly informed - * of and agree to be bound by the conditions described below in this - * notice: - * - * This software product, DigiProof, is developed by T. Linden and - * copyrighted (C) 2013 by T. Linden, with all rights reserved. - * - * There is no charge for DigiProof software. You can redistribute - * it and/or modify it under the terms of the GNU General Public - * License, which is incorporated by reference herein. - * - * DigiProof is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, - * OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that - * the use of it will not infringe on any third party's intellectual - * property rights. - * - * You should have received a copy of the GNU General Public License - * along with DigiProof. Copies can also be obtained from: - * - * http://www.gnu.org/licenses/gpl-2.0.html - * - * or by writing to: - * - * Free Software Foundation, Inc. - * Inc., 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 - * USA - * - * Or contact: - * - * "T. Linden" - * - * The sourcecode can be found on: - * - * https://codeberg.org/scip/digiproof - * - */ - -html, body { - margin: 20px; -} - -a { - cursor: pointer; -} - -.navbar .nav > li > a.active { - color: black; - font-weight: bold; -} - -.about { - padding-bottom: 15px; - width: 700px; -} - -.about + .about { - padding-top: 25px; - border-top: 1px solid #000; -} - - -@media print { - .visible-print { display: inherit !important; } - .page-break { display: block; page-break-after: always; } - .hidden-print { display: none !important; } - - .pr-toptitle { - font-size: 14px; - } - .pr-title { - font-size: 12px; - } - .pr-label { - font-size: 10px; - font-weight: bold; - } - .pr-data { - font-size: 10px; - font-family: Monaco, Menlo, Consolas, "Courier New", monospace - } - .pr-text { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 11px; - } -} - -@media all { - .page-break { display: none; } -} - -.addicon { - padding-left: 16px; - padding-right: 16px; - padding-bottom: 16px; - height: 32px; - width: 32px; - border: 0px; - background-repeat: no-repeat; - background-image:url(data:image/png;base64,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) - - } - - -.addlogo { - padding-left: 175px; - padding-right: 175px; - padding-bottom: 95px; - height: 0px; - width: 0px; - border: 0px; - background-repeat: no-repeat; -background-image: url(data:image/jpeg;base64,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); -} - -.dpedge-prod { - padding: 3px; - background-color: #ffffff; - margin-top: 9px; - color: #6a6a6a; -} - -.dpedge-devel { - padding: 3px; - background-color: #ff8a00; - margin-top: 7px; - color: #6a6a6a; -} \ No newline at end of file diff --git a/digiproof-dev.html b/digiproof-dev.html deleted file mode 100644 index a3888cb..0000000 --- a/digiproof-dev.html +++ /dev/null @@ -1,56520 +0,0 @@ - - - - - -Digital Testament App - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/digiproof-prod.html b/digiproof-prod.html deleted file mode 100644 index 64a7ab8..0000000 --- a/digiproof-prod.html +++ /dev/null @@ -1,3542 +0,0 @@ - - - - - -Digital Testament App - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/index.html b/index.html deleted file mode 100644 index 5ed9b4a..0000000 --- a/index.html +++ /dev/null @@ -1,909 +0,0 @@ - - - - - -Digital Testament App - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/js/apphelpers.js b/js/apphelpers.js deleted file mode 100644 index 2e7b1d7..0000000 --- a/js/apphelpers.js +++ /dev/null @@ -1,122 +0,0 @@ -/* - * - * This file is part of the digital testament management program - * DigiProof. - * - * By accessing this software, DigiProof, you are duly informed - * of and agree to be bound by the conditions described below in this - * notice: - * - * This software product, DigiProof, is developed by T. Linden and - * copyrighted (C) 2013 by T. Linden, with all rights reserved. - * - * There is no charge for DigiProof software. You can redistribute - * it and/or modify it under the terms of the GNU General Public - * License, which is incorporated by reference herein. - * - * DigiProof is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, - * OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that - * the use of it will not infringe on any third party's intellectual - * property rights. - * - * You should have received a copy of the GNU General Public License - * along with DigiProof. Copies can also be obtained from: - * - * http://www.gnu.org/licenses/gpl-2.0.html - * - * or by writing to: - * - * Free Software Foundation, Inc. - * Inc., 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 - * USA - * - * Or contact: - * - * "T. Linden" - * - * The sourcecode can be found on: - * - * https://codeberg.org/scip/digiproof - * - */ - - -// tell if there have been anything done yet -function CheckForEmptyDB() { - var assets = App.Asset.find(); - var notempty = true; - notempty = assets.forEach(function(asset) { - return false; - }); - return notempty; -} - - -// Convert hex string to ASCII. -// See http://stackoverflow.com/questions/11889329/word-array-to-string -function hex2a(hex) { - var str = ''; - for (var i = 0; i < hex.length; i += 2) - str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); - return str; -} - -// decrypt data -function decryptimport(hash, data) { - var clear = CryptoJS.AES.decrypt(data, hash); - return unescape(hex2a(clear.toString())); -} - - - -// from: -// http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html -function decode64(input) { - var output = ""; - var chr1, chr2, chr3 = ""; - var enc1, enc2, enc3, enc4 = ""; - var i = 0; - - var keyStr = "ABCDEFGHIJKLMNOP" + - "QRSTUVWXYZabcdef" + - "ghijklmnopqrstuv" + - "wxyz0123456789+/" + - "="; - - // remove all characters that are not A-Z, a-z, 0-9, +, /, or = - var base64test = /[^A-Za-z0-9\+\/\=]/g; // - if (base64test.exec(input)) { - alert("There were invalid base64 characters in the input text.\n" + - "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" + - "Expect errors in decoding."); - } - input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); - - do { - enc1 = keyStr.indexOf(input.charAt(i++)); - enc2 = keyStr.indexOf(input.charAt(i++)); - enc3 = keyStr.indexOf(input.charAt(i++)); - enc4 = keyStr.indexOf(input.charAt(i++)); - - chr1 = (enc1 << 2) | (enc2 >> 4); - chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); - chr3 = ((enc3 & 3) << 6) | enc4; - - output = output + String.fromCharCode(chr1); - - if (enc3 != 64) { - output = output + String.fromCharCode(chr2); - } - if (enc4 != 64) { - output = output + String.fromCharCode(chr3); - } - - chr1 = chr2 = chr3 = ""; - enc1 = enc2 = enc3 = enc4 = ""; - - } while (i < input.length); - - return unescape(output); -} - diff --git a/js/confirm.js b/js/confirm.js deleted file mode 100644 index ec6b5e8..0000000 --- a/js/confirm.js +++ /dev/null @@ -1,73 +0,0 @@ -/* - * - * This file is part of the digital testament management program - * DigiProof. - * - * By accessing this software, DigiProof, you are duly informed - * of and agree to be bound by the conditions described below in this - * notice: - * - * This software product, DigiProof, is developed by T. Linden and - * copyrighted (C) 2013 by T. Linden, with all rights reserved. - * - * There is no charge for DigiProof software. You can redistribute - * it and/or modify it under the terms of the GNU General Public - * License, which is incorporated by reference herein. - * - * DigiProof is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, - * OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that - * the use of it will not infringe on any third party's intellectual - * property rights. - * - * You should have received a copy of the GNU General Public License - * along with DigiProof. Copies can also be obtained from: - * - * http://www.gnu.org/licenses/gpl-2.0.html - * - * or by writing to: - * - * Free Software Foundation, Inc. - * Inc., 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 - * USA - * - * Or contact: - * - * "T. Linden" - * - * The sourcecode can be found on: - * - * https://codeberg.org/scip/digiproof - * - */ - -/* - * Unused currently! - * - * The idea here was, if the user enters data and closes the page, - * check if there have been made an export and if not ask the user - * to do one. - * - * Howver, it doesn't work so far. - */ - -function confirminit() { - window.onbeforeunload = function(e) { - if(window.confirmExit) return confirmExit(); - }; -} - -var hadConfirmExit = false; -function checkUnsavedChanges() { - if(App.store && App.store.isDirty && window.hadConfirmExit === false) { - if(confirm("unsafed changes")) - saveChanges(); - } -} - -function confirmExit() { - hadConfirmExit = true; - if(App.store && App.store.isDirty) { - return "ok"; - } -} diff --git a/js/controllers_about.js b/js/controllers_about.js deleted file mode 100644 index 7b05bd8..0000000 --- a/js/controllers_about.js +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * This file is part of the digital testament management program - * DigiProof. - * - * By accessing this software, DigiProof, you are duly informed - * of and agree to be bound by the conditions described below in this - * notice: - * - * This software product, DigiProof, is developed by T. Linden and - * copyrighted (C) 2013 by T. Linden, with all rights reserved. - * - * There is no charge for DigiProof software. You can redistribute - * it and/or modify it under the terms of the GNU General Public - * License, which is incorporated by reference herein. - * - * DigiProof is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, - * OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that - * the use of it will not infringe on any third party's intellectual - * property rights. - * - * You should have received a copy of the GNU General Public License - * along with DigiProof. Copies can also be obtained from: - * - * http://www.gnu.org/licenses/gpl-2.0.html - * - * or by writing to: - * - * Free Software Foundation, Inc. - * Inc., 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 - * USA - * - * Or contact: - * - * "T. Linden" - * - * The sourcecode can be found on: - * - * https://codeberg.org/scip/digiproof - * - */ - - -// only template stuff here, no action. -App.AboutController = Ember.Controller.extend({ - -}); - - - - diff --git a/js/controllers_application.js b/js/controllers_application.js deleted file mode 100644 index 160c6b9..0000000 --- a/js/controllers_application.js +++ /dev/null @@ -1,53 +0,0 @@ -/* - * - * This file is part of the digital testament management program - * DigiProof. - * - * By accessing this software, DigiProof, you are duly informed - * of and agree to be bound by the conditions described below in this - * notice: - * - * This software product, DigiProof, is developed by T. Linden and - * copyrighted (C) 2013 by T. Linden, with all rights reserved. - * - * There is no charge for DigiProof software. You can redistribute - * it and/or modify it under the terms of the GNU General Public - * License, which is incorporated by reference herein. - * - * DigiProof is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, - * OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that - * the use of it will not infringe on any third party's intellectual - * property rights. - * - * You should have received a copy of the GNU General Public License - * along with DigiProof. Copies can also be obtained from: - * - * http://www.gnu.org/licenses/gpl-2.0.html - * - * or by writing to: - * - * Free Software Foundation, Inc. - * Inc., 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 - * USA - * - * Or contact: - * - * "T. Linden" - * - * The sourcecode can be found on: - * - * https://codeberg.org/scip/digiproof - * - */ - - -/* - * distribute those template vars app-wide - */ -App.ApplicationController = Ember.Controller.extend({ - isDevel: isDevel, - VERSION: VERSION -}); - - diff --git a/js/controllers_asset.js b/js/controllers_asset.js deleted file mode 100644 index 18a51d6..0000000 --- a/js/controllers_asset.js +++ /dev/null @@ -1,144 +0,0 @@ -/* - * - * This file is part of the digital testament management program - * DigiProof. - * - * By accessing this software, DigiProof, you are duly informed - * of and agree to be bound by the conditions described below in this - * notice: - * - * This software product, DigiProof, is developed by T. Linden and - * copyrighted (C) 2013 by T. Linden, with all rights reserved. - * - * There is no charge for DigiProof software. You can redistribute - * it and/or modify it under the terms of the GNU General Public - * License, which is incorporated by reference herein. - * - * DigiProof is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, - * OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that - * the use of it will not infringe on any third party's intellectual - * property rights. - * - * You should have received a copy of the GNU General Public License - * along with DigiProof. Copies can also be obtained from: - * - * http://www.gnu.org/licenses/gpl-2.0.html - * - * or by writing to: - * - * Free Software Foundation, Inc. - * Inc., 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 - * USA - * - * Or contact: - * - * "T. Linden" - * - * The sourcecode can be found on: - * - * https://codeberg.org/scip/digiproof - * - */ - - - - -App.AssetsAssetController = Ember.ObjectController.extend({ - isEditing: false, - orders: App.Order.find(), - errors: {}, - - edit: function() { - // prepare order to the actual object, not id - this.set('isEditing', true); - this.set('successors', App.Successor.find()); - }, - - doneEditing: function() { - var validated = this.get('model').validate(); - if(validated.valid){ - this.set('isEditing', false); - this.get('model').get("store").commit(); - } - else { - this.set('errors', validated); - this.set('isEditing', true); - } - }, - - cancelEditing: function() { - this.set('isEditing', false); - }, - - remove: function() { - var asset = this.get('model'); - asset.deleteRecord(); - asset.get("store").commit(); - this.get("target").transitionTo("assets"); - } -}); - -App.AssetsNewController = Ember.ArrayController.extend({ - successors: App.Successor.find(), - orders: App.Order.find(), - next: 0, - selected_successor: 0, - selected_order: 0, - errors: {}, - - - createNextAsset: function () { - this.set('next', 1); - this.createAsset(); - }, - - createAsset: function () { - var name = this.get('name'); - if (!name.trim()) { return; } - //console.log("successor: %o", this.get('order')); - - var asset = App.Asset.createRecord({ - name: name, - uri: this.get('uri'), - login: this.get('login'), - password: this.get('password'), - mail: this.get('mail'), - successor: this.get('successor'), - order: this.get('order'), - notes: this.get('notes') - }); - - var validated = asset.validate(); - //console.log("validated: %o", validated); - if(! validated.valid) { - asset.deleteRecord(); - this.set('errors', validated); - this.set('isEditing', true); - } - else { - // Save the new model - asset.get("store").commit(); - - // empty form fields so new entries starts from scratch - this.set('name', ''); - this.set('uri', ''); - this.set('login', ''); - this.set('password', ''); - this.set('mail', ''); - this.set('order', ''); - this.set('successor',''); - this.set('notes', ''); - - if(this.get('next') == 1) { - this.get("target").transitionTo("assets.new"); - } - else { - // redirect to newly created entry - this.get("target").transitionTo("assets.asset", asset); - } - } - } -}); - - diff --git a/js/controllers_data.js b/js/controllers_data.js deleted file mode 100644 index ed68f95..0000000 --- a/js/controllers_data.js +++ /dev/null @@ -1,360 +0,0 @@ -/* - * - * This file is part of the digital testament management program - * DigiProof. - * - * By accessing this software, DigiProof, you are duly informed - * of and agree to be bound by the conditions described below in this - * notice: - * - * This software product, DigiProof, is developed by T. Linden and - * copyrighted (C) 2013 by T. Linden, with all rights reserved. - * - * There is no charge for DigiProof software. You can redistribute - * it and/or modify it under the terms of the GNU General Public - * License, which is incorporated by reference herein. - * - * DigiProof is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, - * OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that - * the use of it will not infringe on any third party's intellectual - * property rights. - * - * You should have received a copy of the GNU General Public License - * along with DigiProof. Copies can also be obtained from: - * - * http://www.gnu.org/licenses/gpl-2.0.html - * - * or by writing to: - * - * Free Software Foundation, Inc. - * Inc., 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 - * USA - * - * Or contact: - * - * "T. Linden" - * - * The sourcecode can be found on: - * - * https://codeberg.org/scip/digiproof - * - */ - - - -/* - * This controller is being used to data export and import. - * It handles the whole encryption/decryption of data. - */ - - -App.DataExportController = Ember.ArrayController.extend({ - successors: App.Successor.find(), - self: App.Self.find(0), - assets: App.Asset.find(), - download: function() { - /* - Encrypt the data: - - 1) the data/export template receives all objects and puts - json objects of it into the invisible div 'rawjson'. - this happened on first template execution. - - 2) when the 'download' action gets triggered, fetch that - generated json out of the div. - - 3) fetch self.pass and create an SHA512 hash from it. - - 4) hash this hash 32times recursive (that is, create a - hash of the previous hash and so on 32 times). - - 5) encrypt the json string using AES256 using the generated - base64 encoded hash. - - 6) put the base64 encoded encrypted data into the div 'rawdata' - - 7) retrieve the data from 'rawdata'. note: it doesn't work - to just continue to work with the already base64 encoded - data (variable cr), it is empty. however, if we put it into - the div and retrieve it right away then it's filled. - that's reliable javascript programming, yay. - - 8) now calculate a SHA256 MAC authentication message of the - base64 encoded encrypted data using the base64 encoded - password hash (=> mac). - - 9) concatenate the mac and the encrypted data (mac first minus - the last 2 chars '==') (=> signedcrypted). - - 10) insert a msdos newline every 64 chars so that we get a nice - base64 encoded block. - - 11) add a header and footer to that block. - - 12) create a Blob object of that block. - - 13) put up a "save as..." dialog box to the user using this - blob as content. - - */ - var raw = $('#rawjson').text(); - var pass = $('#rawp').text(); - var hash = CryptoJS.SHA512(pass); - - for(var i=0; i<31; i++) { - hash = CryptoJS.SHA512(hash); - } - - // fix handlebars generated json output comma syntax - raw = raw.replace(/,\],/g, '],'); - // console.log("raw: %s", raw); - var cr = CryptoJS.AES.encrypt(escape(raw), hash.toString(CryptoJS.enc.Base64)); - - $('#rawdata').text(cr); - - var crypted = $('#rawdata').text(); - - var mac = CryptoJS.HmacSHA512(crypted, hash.toString(CryptoJS.enc.Base64)); - var signedcrypted = mac.toString(CryptoJS.enc.Base64).substring(0,86) + crypted; - - // console.log("cr: %s", crypted); - // console.log("pass: <%s>, hash: <%s>", pass, hash.toString(CryptoJS.enc.Base64)); - // console.log("mac: %s", mac.toString(CryptoJS.enc.Base64).substring(0,86)); - - var block = ''; - var c = 1; - for(var i=0; i, hash: <%s>, hash: %o", pass, hash.toString(CryptoJS.enc.Base64), hash); - // console.log("json: %s", json); - - // make it an obj - var importobj = JSON.parse(json); - // console.log("imported json: %o", importobj); - - if(json) { - // suck it in - ImportJSON(importobj, pass); - this.set('clear', translate('_importdone')); - var isuccessors = []; - $.each(importobj.successors, function(index, obj) { - if(obj.id != '0') { - isuccessors.pushObject(obj); - } - }); - this.set('successors', isuccessors); - this.set('assets', importobj.assets); - this.set('self', importobj.self); - } - else { - throw 'decrypted variable $json doesnt contain anything, weird'; - } - } - catch (e) { - // console.log("decryption exception: %o", e); - this.set('clear', translate('_error_decrypt') + " (" + e + ")"); - this.set('failed', true); - } - } - else { - // no password given - this.set('isEditing', true); - this.set('errors', validated); - this.set('failed', true); - this.set('clear', translate('_error_decrypt')); - } - }, - - repeatEditing: function() { - this.set('isEditing', true); - this.set('importdata', ''); - this.set('password', ''); - } -}); - -function ImportJSON(json, pass) { - // start with self - var self = App.Self.find(0).then(function(self) { - self.set('name', json.self.name); - self.set('birth', json.self.birth); - self.set('address', json.self.address); - self.set('password', pass); - }); - - - // now the successors - $.each(json.successors, function(index, obj){ - if(obj.id !== "0") { - var exists = App.Successor.all().some(function(successor) { - return successor.get('id') === obj.id; - }); - if(exists) { - // Update - App.Successor.find(obj.id).then(function(successor) { - //console.log("updating successor %o", obj); - successor.set("name", obj.name); - successor.set("address", obj.address); - successor.set("birth", obj.birth); - successor.set("name2", obj.name2); - successor.set("address2", obj.address2); - successor.set("birth2", obj.birth2); - }); - } - else { - var successor = App.Successor.createRecord(obj); - } - } - }); - - // and the assets - $.each(json.assets, function(index, obj){ - var exists = App.Asset.all().some(function(asset) { - return asset.get('id') === obj.id; - }); - if(exists) { - /// Update - App.Asset.find(obj.id).then(function(asset) { - //console.log("updating asset %o", obj); - asset.set("name", obj.name); - asset.set("uri", obj.uri); - asset.set("login", obj.login); - asset.set("password", obj.password); - asset.set("mail", obj.mail); - asset.set("successor", App.Successor.find(obj.successor)); - asset.set("order", App.Order.find(obj.order)); - asset.set("notes", obj.notes); - App.store.commit(); // we do update it here to avoid rootState.loaded.updated.uncommitted - }); - } - else { - // create - var asset = App.Asset.createRecord({ - id: obj.id, - name: obj.name, - uri: obj.uri, - login: obj.login, - password: obj.password, - mail: obj.mail, - successor: App.Successor.find(obj.successor), - order: App.Order.find(obj.order), - notes: obj.notes - }); - } - }); - - App.store.commit(); -} - diff --git a/js/controllers_index.js b/js/controllers_index.js deleted file mode 100644 index eaad9a3..0000000 --- a/js/controllers_index.js +++ /dev/null @@ -1,77 +0,0 @@ -/* - * - * This file is part of the digital testament management program - * DigiProof. - * - * By accessing this software, DigiProof, you are duly informed - * of and agree to be bound by the conditions described below in this - * notice: - * - * This software product, DigiProof, is developed by T. Linden and - * copyrighted (C) 2013 by T. Linden, with all rights reserved. - * - * There is no charge for DigiProof software. You can redistribute - * it and/or modify it under the terms of the GNU General Public - * License, which is incorporated by reference herein. - * - * DigiProof is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, - * OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that - * the use of it will not infringe on any third party's intellectual - * property rights. - * - * You should have received a copy of the GNU General Public License - * along with DigiProof. Copies can also be obtained from: - * - * http://www.gnu.org/licenses/gpl-2.0.html - * - * or by writing to: - * - * Free Software Foundation, Inc. - * Inc., 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 - * USA - * - * Or contact: - * - * "T. Linden" - * - * The sourcecode can be found on: - * - * https://codeberg.org/scip/digiproof - * - */ - - -/* - * Used for general navbar display and intro texts - */ -App.IndexController = Ember.Controller.extend({ - has_self: App.Self.find(), - has_asset: App.Asset.find(), - has_successor: App.Successor.find(), - isDevel: isDevel, - VERSION: VERSION -}); - - -/* - * Make sure, a clicked menu item gets highlighted, - * so the user knows where he is. - */ -App.NavView = Ember.View.extend({ - tagName: 'li', - classNameBindings: 'active'.w(), - - didInsertElement: function () { - this._super(); - var _this = this; - this.get('parentView').on('click', function () { - _this.notifyPropertyChange('active'); - }); - }, - - active: function () { - return this.get('childViews.firstObject.active'); - }.property() -}); - diff --git a/js/controllers_self.js b/js/controllers_self.js deleted file mode 100644 index 28fc76c..0000000 --- a/js/controllers_self.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * - * This file is part of the digital testament management program - * DigiProof. - * - * By accessing this software, DigiProof, you are duly informed - * of and agree to be bound by the conditions described below in this - * notice: - * - * This software product, DigiProof, is developed by T. Linden and - * copyrighted (C) 2013 by T. Linden, with all rights reserved. - * - * There is no charge for DigiProof software. You can redistribute - * it and/or modify it under the terms of the GNU General Public - * License, which is incorporated by reference herein. - * - * DigiProof is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, - * OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that - * the use of it will not infringe on any third party's intellectual - * property rights. - * - * You should have received a copy of the GNU General Public License - * along with DigiProof. Copies can also be obtained from: - * - * http://www.gnu.org/licenses/gpl-2.0.html - * - * or by writing to: - * - * Free Software Foundation, Inc. - * Inc., 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 - * USA - * - * Or contact: - * - * "T. Linden" - * - * The sourcecode can be found on: - * - * https://codeberg.org/scip/digiproof - * - */ - - - -App.SelfController = Ember.ObjectController.extend({ - isEditing: false, - errors: {}, - - edit: function() { - // prepare order to the actual object, not id - this.set('isEditing', true); - }, - - doneEditing: function() { - var validated = this.get('model').validate(); - if(! validated.valid) { - this.set('errors', validated); - this.set('isEditing', true); - } - else { - this.set('isEditing', false); - this.get('model').get("store").commit(); - } - }, - - cancelEditing: function() { - this.set('isEditing', false); - } -}); - diff --git a/js/controllers_successor.js b/js/controllers_successor.js deleted file mode 100644 index f8a4fdc..0000000 --- a/js/controllers_successor.js +++ /dev/null @@ -1,130 +0,0 @@ -/* - * - * This file is part of the digital testament management program - * DigiProof. - * - * By accessing this software, DigiProof, you are duly informed - * of and agree to be bound by the conditions described below in this - * notice: - * - * This software product, DigiProof, is developed by T. Linden and - * copyrighted (C) 2013 by T. Linden, with all rights reserved. - * - * There is no charge for DigiProof software. You can redistribute - * it and/or modify it under the terms of the GNU General Public - * License, which is incorporated by reference herein. - * - * DigiProof is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, - * OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that - * the use of it will not infringe on any third party's intellectual - * property rights. - * - * You should have received a copy of the GNU General Public License - * along with DigiProof. Copies can also be obtained from: - * - * http://www.gnu.org/licenses/gpl-2.0.html - * - * or by writing to: - * - * Free Software Foundation, Inc. - * Inc., 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 - * USA - * - * Or contact: - * - * "T. Linden" - * - * The sourcecode can be found on: - * - * https://codeberg.org/scip/digiproof - * - */ - - - - - -// manage successors: create, edit and delete them. -App.SuccessorsSuccessorController = Ember.ObjectController.extend({ - isEditing: false, - errors: {}, - - edit: function() { - this.set('isEditing', true); - }, - - doneEditing: function() { - var validated = this.get('model').validate(); - if(! validated.valid) { - this.set('errors', validated); - this.set('isEditing', true); - } - else { - this.set('isEditing', false); - this.get('model').get("store").commit(); - } - }, - - cancelEditing: function() { - this.set('isEditing', false); - }, - - remove: function() { - var successor = this.get('model'); - successor.deleteRecord(); - successor.get("store").commit(); - this.get("target").transitionTo("successors"); - } -}); - -App.SuccessorsNewController = Ember.ArrayController.extend({ - newName: '', - next: 0, - erros: {}, - - createNextSuccessor: function () { - this.set('next', 1); - this.createSuccessor(); - }, - - createSuccessor: function () { - var successor = App.Successor.createRecord({ - name: this.get('name'), - address: this.get('address'), - birth: this.get('birth'), - name2: this.get('name2'), - address2: this.get('address2'), - birth2: this.get('birth2') - }); - - var validated = successor.validate(); - //console.log("validated: %o", validated); - if(! validated.valid) { - successor.deleteRecord(); - this.set('errors', validated); - this.set('isEditing', true); - } - else { - // Save the new model - successor.get("store").commit(); - - // empty form fields so new entries starts from scratch - this.set('name', ''); - this.set('address', ''); - this.set('birth', ''); - this.set('name2', ''); - this.set('address2', ''); - this.set('birth2', ''); - - if(this.get('next') == 1) { - this.get("target").transitionTo("successors.new"); - } - else { - // redirect to newly created entry - this.get("target").transitionTo("successors.successor", successor); - } - } - } -}); - diff --git a/js/controllers_testament.js b/js/controllers_testament.js deleted file mode 100644 index 9fa1d1d..0000000 --- a/js/controllers_testament.js +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * This file is part of the digital testament management program - * DigiProof. - * - * By accessing this software, DigiProof, you are duly informed - * of and agree to be bound by the conditions described below in this - * notice: - * - * This software product, DigiProof, is developed by T. Linden and - * copyrighted (C) 2013 by T. Linden, with all rights reserved. - * - * There is no charge for DigiProof software. You can redistribute - * it and/or modify it under the terms of the GNU General Public - * License, which is incorporated by reference herein. - * - * DigiProof is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, - * OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that - * the use of it will not infringe on any third party's intellectual - * property rights. - * - * You should have received a copy of the GNU General Public License - * along with DigiProof. Copies can also be obtained from: - * - * http://www.gnu.org/licenses/gpl-2.0.html - * - * or by writing to: - * - * Free Software Foundation, Inc. - * Inc., 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 - * USA - * - * Or contact: - * - * "T. Linden" - * - * The sourcecode can be found on: - * - * https://codeberg.org/scip/digiproof - * - */ - - -/* - * plain simple controller, just spits out all our - * data, the acual testament generation happens in the - * template - */ -App.TestamentController = Ember.ArrayController.extend({ - needs: "self", - //self: Ember.computed.alias("controllers.self"), - successors: App.Successor.find(), - self: App.Self.find(0), - now: new Date(), - notempty: CheckForEmptyDB() -}); - diff --git a/js/digiproof_dev.js b/js/digiproof_dev.js deleted file mode 100644 index 5320485..0000000 --- a/js/digiproof_dev.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * - * This file is part of the digital testament management program - * DigiProof. - * - * By accessing this software, DigiProof, you are duly informed - * of and agree to be bound by the conditions described below in this - * notice: - * - * This software product, DigiProof, is developed by T. Linden and - * copyrighted (C) 2013 by T. Linden, with all rights reserved. - * - * There is no charge for DigiProof software. You can redistribute - * it and/or modify it under the terms of the GNU General Public - * License, which is incorporated by reference herein. - * - * DigiProof is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, - * OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that - * the use of it will not infringe on any third party's intellectual - * property rights. - * - * You should have received a copy of the GNU General Public License - * along with DigiProof. Copies can also be obtained from: - * - * http://www.gnu.org/licenses/gpl-2.0.html - * - * or by writing to: - * - * Free Software Foundation, Inc. - * Inc., 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 - * USA - * - * Or contact: - * - * "T. Linden" - * - * The sourcecode can be found on: - * - * https://codeberg.org/scip/digiproof - * - */ - -// signal the app, we are running in development mode! -var isDevel = true; diff --git a/js/digiproof_prod.js b/js/digiproof_prod.js deleted file mode 100644 index f739daa..0000000 --- a/js/digiproof_prod.js +++ /dev/null @@ -1,61 +0,0 @@ -/* - * - * This file is part of the digital testament management program - * DigiProof. - * - * By accessing this software, DigiProof, you are duly informed - * of and agree to be bound by the conditions described below in this - * notice: - * - * This software product, DigiProof, is developed by T. Linden and - * copyrighted (C) 2013 by T. Linden, with all rights reserved. - * - * There is no charge for DigiProof software. You can redistribute - * it and/or modify it under the terms of the GNU General Public - * License, which is incorporated by reference herein. - * - * DigiProof is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, - * OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that - * the use of it will not infringe on any third party's intellectual - * property rights. - * - * You should have received a copy of the GNU General Public License - * along with DigiProof. Copies can also be obtained from: - * - * http://www.gnu.org/licenses/gpl-2.0.html - * - * or by writing to: - * - * Free Software Foundation, Inc. - * Inc., 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 - * USA - * - * Or contact: - * - * "T. Linden" - * - * The sourcecode can be found on: - * - * https://codeberg.org/scip/digiproof - * - */ - -// signal the app, we are running in productive mode! -var isDevel = false; - -/* - * in the production actual saving to browser - * storage on disk is disabled here by overwriting - * the setItem and getItem function of localStorage - * with dummies, which hold the data in memory only. - */ -localStorage.setItem = function(namespace, json) { - this.set('_fakestore') = { namespace: json }; - return this; -} - -localStorage.getItem = function(namespace) { - return this.get('_fakestore').namespace; -} - diff --git a/js/fs.js b/js/fs.js deleted file mode 100755 index 037fb25..0000000 --- a/js/fs.js +++ /dev/null @@ -1,323 +0,0 @@ -/* - * - * This file is part of the digital testament management program - * DigiProof. - * - * By accessing this software, DigiProof, you are duly informed - * of and agree to be bound by the conditions described below in this - * notice: - * - * This software product, DigiProof, is developed by T. Linden and - * copyrighted (C) 2013 by T. Linden, with all rights reserved. - * - * There is no charge for DigiProof software. You can redistribute - * it and/or modify it under the terms of the GNU General Public - * License, which is incorporated by reference herein. - * - * DigiProof is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, - * OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that - * the use of it will not infringe on any third party's intellectual - * property rights. - * - * You should have received a copy of the GNU General Public License - * along with DigiProof. Copies can also be obtained from: - * - * http://www.gnu.org/licenses/gpl-2.0.html - * - * or by writing to: - * - * Free Software Foundation, Inc. - * Inc., 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 - * USA - * - * Or contact: - * - * "T. Linden" - * - * The sourcecode can be found on: - * - * https://codeberg.org/scip/digiproof - * - */ - - -/* - * CURRENTLY UNUSED !!!!! - */ - - -//-- -//-- Filesystem code from TiddlyWiki -//-- - -function convertUTF8ToUnicode(u) -{ - return window.netscape == undefined ? manualConvertUTF8ToUnicode(u) : mozConvertUTF8ToUnicode(u); -} - -function manualConvertUTF8ToUnicode(utf) -{ - var uni = utf; - var src = 0; - var dst = 0; - var b1, b2, b3; - var c; - while(src < utf.length) { - b1 = utf.charCodeAt(src++); - if(b1 < 0x80) { - dst++; - } else if(b1 < 0xE0) { - b2 = utf.charCodeAt(src++); - c = String.fromCharCode(((b1 & 0x1F) << 6) | (b2 & 0x3F)); - uni = uni.substring(0,dst++).concat(c,utf.substr(src)); - } else { - b2 = utf.charCodeAt(src++); - b3 = utf.charCodeAt(src++); - c = String.fromCharCode(((b1 & 0xF) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F)); - uni = uni.substring(0,dst++).concat(c,utf.substr(src)); - } - } - return uni; -} - -function mozConvertUTF8ToUnicode(u) -{ - try { - netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); - var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Components.interfaces.nsIScriptableUnicodeConverter); - converter.charset = "UTF-8"; - } catch(ex) { - return manualConvertUTF8ToUnicode(u); - } // fallback - var s = converter.ConvertToUnicode(u); - var fin = converter.Finish(); - return (fin.length > 0) ? s+fin : s; -} - -function convertUnicodeToUTF8(s) -{ - if(window.netscape == undefined) - return manualConvertUnicodeToUTF8(s); - else - return mozConvertUnicodeToUTF8(s); -} - - -function manualConvertUnicodeToUTF8(s) -{ - var re = /[^\u0000-\u007F]/g ; - return s.replace(re,function($0) {return "&#" + $0.charCodeAt(0).toString() + ";";}); -} - -function mozConvertUnicodeToUTF8(s) -{ - try { - netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); - var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Components.interfaces.nsIScriptableUnicodeConverter); - converter.charset = "UTF-8"; - } catch(ex) { - return manualConvertUnicodeToUTF8(s); - } // fallback - var u = converter.ConvertFromUnicode(s); - var fin = converter.Finish(); - return fin.length > 0 ? u + fin : u; -} - -function convertUriToUTF8(uri,charSet) -{ - if(window.netscape == undefined || charSet == undefined || charSet == "") - return uri; - try { - netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); - var converter = Components.classes["@mozilla.org/intl/utf8converterservice;1"].getService(Components.interfaces.nsIUTF8ConverterService); - } catch(ex) { - return uri; - } - return converter.convertURISpecToUTF8(uri,charSet); -} - -function saveFile(fileUrl,content) -{ - var r = mozillaSaveFile(fileUrl,content); - if(!r) - r = ieSaveFile(fileUrl,content); - if(!r) - r = javaSaveFile(fileUrl,content); - return r; -} - -function loadFile(fileUrl) -{ - var r = mozillaLoadFile(fileUrl); - if((r == null) || (r == false)) - r = ieLoadFile(fileUrl); - if((r == null) || (r == false)) - r = javaLoadFile(fileUrl); - return r; -} - - -function ieCreatePath(path) -{ - try { - var fso = new ActiveXObject("Scripting.FileSystemObject"); - } catch(ex) { - return null; - } - - var pos = path.lastIndexOf("\\"); - if(pos!=-1) - path = path.substring(0, pos+1); - - var scan = []; - scan.push(path); - var i = 0; - do { - var parent = fso.GetParentFolderName(scan[i++]); - if (fso.FolderExists(parent)) - break; - scan.push(parent); - } while(true); - - for(i=scan.length-1;i>=0;i--) { - if (!fso.FolderExists(scan[i])) - fso.CreateFolder(scan[i]); - } - return true; -} - -// Returns null if it can't do it, false if there's an error, true if it saved OK -function ieSaveFile(filePath,content) -{ - ieCreatePath(filePath); - try { - var fso = new ActiveXObject("Scripting.FileSystemObject"); - } catch(ex) { - return null; - } - var file = fso.OpenTextFile(filePath,2,-1,0); - file.Write(content); - file.Close(); - return true; -} - - -// Returns null if it can't do it, false if there's an error, or a string of the content if successful -function ieLoadFile(filePath) -{ - try { - var fso = new ActiveXObject("Scripting.FileSystemObject"); - var file = fso.OpenTextFile(filePath,1); - var content = file.ReadAll(); - file.Close(); - } catch(ex) { - return null; - } - return content; -} - -function ieCopyFile(dest,source) -{ - ieCreatePath(dest); - try { - var fso = new ActiveXObject("Scripting.FileSystemObject"); - fso.GetFile(source).Copy(dest); - } catch(ex) { - return false; - } - return true; -} - -// Returns null if it can't do it, false if there's an error, true if it saved OK -function mozillaSaveFile(filePath,content) -{ - if(window.Components) { - try { - netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); - var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile); - file.initWithPath(filePath); - if(!file.exists()) - file.create(0,0664); - var out = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream); - out.init(file,0x20|0x02,00004,null); - out.write(content,content.length); - out.flush(); - out.close(); - return true; - } catch(ex) { - return false; - } - } - return null; -} - -// Returns null if it can't do it, false if there's an error, or a string of the content if successful -function mozillaLoadFile(filePath) -{ - if(window.Components) { - try { - netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); - var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile); - file.initWithPath(filePath); - if(!file.exists()) - return null; - var inputStream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream); - inputStream.init(file,0x01,00004,null); - var sInputStream = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream); - sInputStream.init(inputStream); - return sInputStream.read(sInputStream.available()); - } catch(ex) { - return false; - } - } - return null; -} - -function javaUrlToFilename(url) -{ - var f = "//localhost"; - if(url.indexOf(f) == 0) - return url.substring(f.length); - var i = url.indexOf(":"); - if(i > 0) - return url.substring(i-1); - return url; -} - -function javaSaveFile(filePath,content) -{ - try { - if(document.applets["TiddlySaver"]) - return document.applets["TiddlySaver"].saveFile(javaUrlToFilename(filePath),"UTF-8",content); - } catch(ex) { - } - try { - var s = new java.io.PrintStream(new java.io.FileOutputStream(javaUrlToFilename(filePath))); - s.print(content); - s.close(); - } catch(ex) { - return null; - } - return true; -} - -function javaLoadFile(filePath) -{ - try { - if(document.applets["TiddlySaver"]) - return String(document.applets["TiddlySaver"].loadFile(javaUrlToFilename(filePath),"UTF-8")); - } catch(ex) { - } - var content = []; - try { - var r = new java.io.BufferedReader(new java.io.FileReader(javaUrlToFilename(filePath))); - var line; - while((line = r.readLine()) != null) - content.push(new String(line)); - r.close(); - } catch(ex) { - return null; - } - return content.join("\n"); -} diff --git a/js/handlebars_helpers.js b/js/handlebars_helpers.js deleted file mode 100644 index dbd2bea..0000000 --- a/js/handlebars_helpers.js +++ /dev/null @@ -1,88 +0,0 @@ -/* - * - * This file is part of the digital testament management program - * DigiProof. - * - * By accessing this software, DigiProof, you are duly informed - * of and agree to be bound by the conditions described below in this - * notice: - * - * This software product, DigiProof, is developed by T. Linden and - * copyrighted (C) 2013 by T. Linden, with all rights reserved. - * - * There is no charge for DigiProof software. You can redistribute - * it and/or modify it under the terms of the GNU General Public - * License, which is incorporated by reference herein. - * - * DigiProof is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, - * OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that - * the use of it will not infringe on any third party's intellectual - * property rights. - * - * You should have received a copy of the GNU General Public License - * along with DigiProof. Copies can also be obtained from: - * - * http://www.gnu.org/licenses/gpl-2.0.html - * - * or by writing to: - * - * Free Software Foundation, Inc. - * Inc., 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 - * USA - * - * Or contact: - * - * "T. Linden" - * - * The sourcecode can be found on: - * - * https://codeberg.org/scip/digiproof - * - */ - - -/* - * handlebars helper to translate strings. - * Those are defined in js/locale.js, see there. Called with - * {{loc _tag}} from any handlebars template. - * - * See https://gist.github.com/tracend/3261055 - */ -Ember.Handlebars.registerBoundHelper('loc', function(keyword, options) { - // pick the right dictionary - var locale = window.locale[lang] || window.locale['en-US']; - - // loop through all the key hierarchy (if any) - var target = locale; - - //console.log("key: %o", [keyword, options.data.properties[0]]); - var key; - if(keyword) { - key = keyword; - } - else { - key = options.data.properties[0]; - } - keyword = ''; - options.data.properties[0] = ''; - - if(key) { - if(key in locale) { - return locale[key]; - } - else { - return '__UNTRANSLATED_STRING__(' + key + ')'; - } - } - else { - return ''; - } -}); - -// print a nice formatted date to the testament printout -Ember.Handlebars.registerBoundHelper('date', function(date) { - moment().lang(lang); - return moment(date).format('LL'); -}); - diff --git a/js/init.js b/js/init.js deleted file mode 100644 index b99a357..0000000 --- a/js/init.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * - * This file is part of the digital testament management program - * DigiProof. - * - * By accessing this software, DigiProof, you are duly informed - * of and agree to be bound by the conditions described below in this - * notice: - * - * This software product, DigiProof, is developed by T. Linden and - * copyrighted (C) 2013 by T. Linden, with all rights reserved. - * - * There is no charge for DigiProof software. You can redistribute - * it and/or modify it under the terms of the GNU General Public - * License, which is incorporated by reference herein. - * - * DigiProof is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, - * OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that - * the use of it will not infringe on any third party's intellectual - * property rights. - * - * You should have received a copy of the GNU General Public License - * along with DigiProof. Copies can also be obtained from: - * - * http://www.gnu.org/licenses/gpl-2.0.html - * - * or by writing to: - * - * Free Software Foundation, Inc. - * Inc., 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 - * USA - * - * Or contact: - * - * "T. Linden" - * - * The sourcecode can be found on: - * - * https://codeberg.org/scip/digiproof - * - */ - -// just the app object. put ember.js tuning, logging etc here. -App = Ember.Application.create({ - //LOG_TRANSITIONS: true -}); - - -/* - * Some trickery for help popovers: - * make sure, only one popover appears at a time. - * if the user hovers over another help button, - * hide other popovers and display the new. Hide - * all if not above a help button at all. - */ -$(document).ready(function () { - $('.popup-marker').popover({ - html: true, - trigger: 'hover' - }).click(function(e) { - $('.popup-marker').not(this).popover('hide'); - $(this).popover('toggle'); - }); - $(document).click(function(e) { - if (!$(e.target).is('.popup-marker, .popover-title, .popover-content')) { - $('.popup-marker').popover('hide'); - } - }); -}); - diff --git a/js/libs/aes.js b/js/libs/aes.js deleted file mode 100644 index 827503c..0000000 --- a/js/libs/aes.js +++ /dev/null @@ -1,35 +0,0 @@ -/* -CryptoJS v3.1.2 -code.google.com/p/crypto-js -(c) 2009-2013 by Jeff Mott. All rights reserved. -code.google.com/p/crypto-js/wiki/License -*/ -var CryptoJS=CryptoJS||function(u,p){var d={},l=d.lib={},s=function(){},t=l.Base={extend:function(a){s.prototype=this;var c=new s;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}, -r=l.WordArray=t.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=p?c:4*a.length},toString:function(a){return(a||v).stringify(this)},concat:function(a){var c=this.words,e=a.words,j=this.sigBytes;a=a.sigBytes;this.clamp();if(j%4)for(var k=0;k>>2]|=(e[k>>>2]>>>24-8*(k%4)&255)<<24-8*((j+k)%4);else if(65535>>2]=e[k>>>2];else c.push.apply(c,e);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<< -32-8*(c%4);a.length=u.ceil(c/4)},clone:function(){var a=t.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],e=0;e>>2]>>>24-8*(j%4)&255;e.push((k>>>4).toString(16));e.push((k&15).toString(16))}return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j>>3]|=parseInt(a.substr(j, -2),16)<<24-4*(j%8);return new r.init(e,c/2)}},b=w.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var e=[],j=0;j>>2]>>>24-8*(j%4)&255));return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j>>2]|=(a.charCodeAt(j)&255)<<24-8*(j%4);return new r.init(e,c)}},x=w.Utf8={stringify:function(a){try{return decodeURIComponent(escape(b.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return b.parse(unescape(encodeURIComponent(a)))}}, -q=l.BufferedBlockAlgorithm=t.extend({reset:function(){this._data=new r.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=x.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,e=c.words,j=c.sigBytes,k=this.blockSize,b=j/(4*k),b=a?u.ceil(b):u.max((b|0)-this._minBufferSize,0);a=b*k;j=u.min(4*a,j);if(a){for(var q=0;q>>2]>>>24-8*(r%4)&255)<<16|(l[r+1>>>2]>>>24-8*((r+1)%4)&255)<<8|l[r+2>>>2]>>>24-8*((r+2)%4)&255,v=0;4>v&&r+0.75*v>>6*(3-v)&63));if(l=t.charAt(64))for(;d.length%4;)d.push(l);return d.join("")},parse:function(d){var l=d.length,s=this._map,t=s.charAt(64);t&&(t=d.indexOf(t),-1!=t&&(l=t));for(var t=[],r=0,w=0;w< -l;w++)if(w%4){var v=s.indexOf(d.charAt(w-1))<<2*(w%4),b=s.indexOf(d.charAt(w))>>>6-2*(w%4);t[r>>>2]|=(v|b)<<24-8*(r%4);r++}return p.create(t,r)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})(); -(function(u){function p(b,n,a,c,e,j,k){b=b+(n&a|~n&c)+e+k;return(b<>>32-j)+n}function d(b,n,a,c,e,j,k){b=b+(n&c|a&~c)+e+k;return(b<>>32-j)+n}function l(b,n,a,c,e,j,k){b=b+(n^a^c)+e+k;return(b<>>32-j)+n}function s(b,n,a,c,e,j,k){b=b+(a^(n|~c))+e+k;return(b<>>32-j)+n}for(var t=CryptoJS,r=t.lib,w=r.WordArray,v=r.Hasher,r=t.algo,b=[],x=0;64>x;x++)b[x]=4294967296*u.abs(u.sin(x+1))|0;r=r.MD5=v.extend({_doReset:function(){this._hash=new w.init([1732584193,4023233417,2562383102,271733878])}, -_doProcessBlock:function(q,n){for(var a=0;16>a;a++){var c=n+a,e=q[c];q[c]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360}var a=this._hash.words,c=q[n+0],e=q[n+1],j=q[n+2],k=q[n+3],z=q[n+4],r=q[n+5],t=q[n+6],w=q[n+7],v=q[n+8],A=q[n+9],B=q[n+10],C=q[n+11],u=q[n+12],D=q[n+13],E=q[n+14],x=q[n+15],f=a[0],m=a[1],g=a[2],h=a[3],f=p(f,m,g,h,c,7,b[0]),h=p(h,f,m,g,e,12,b[1]),g=p(g,h,f,m,j,17,b[2]),m=p(m,g,h,f,k,22,b[3]),f=p(f,m,g,h,z,7,b[4]),h=p(h,f,m,g,r,12,b[5]),g=p(g,h,f,m,t,17,b[6]),m=p(m,g,h,f,w,22,b[7]), -f=p(f,m,g,h,v,7,b[8]),h=p(h,f,m,g,A,12,b[9]),g=p(g,h,f,m,B,17,b[10]),m=p(m,g,h,f,C,22,b[11]),f=p(f,m,g,h,u,7,b[12]),h=p(h,f,m,g,D,12,b[13]),g=p(g,h,f,m,E,17,b[14]),m=p(m,g,h,f,x,22,b[15]),f=d(f,m,g,h,e,5,b[16]),h=d(h,f,m,g,t,9,b[17]),g=d(g,h,f,m,C,14,b[18]),m=d(m,g,h,f,c,20,b[19]),f=d(f,m,g,h,r,5,b[20]),h=d(h,f,m,g,B,9,b[21]),g=d(g,h,f,m,x,14,b[22]),m=d(m,g,h,f,z,20,b[23]),f=d(f,m,g,h,A,5,b[24]),h=d(h,f,m,g,E,9,b[25]),g=d(g,h,f,m,k,14,b[26]),m=d(m,g,h,f,v,20,b[27]),f=d(f,m,g,h,D,5,b[28]),h=d(h,f, -m,g,j,9,b[29]),g=d(g,h,f,m,w,14,b[30]),m=d(m,g,h,f,u,20,b[31]),f=l(f,m,g,h,r,4,b[32]),h=l(h,f,m,g,v,11,b[33]),g=l(g,h,f,m,C,16,b[34]),m=l(m,g,h,f,E,23,b[35]),f=l(f,m,g,h,e,4,b[36]),h=l(h,f,m,g,z,11,b[37]),g=l(g,h,f,m,w,16,b[38]),m=l(m,g,h,f,B,23,b[39]),f=l(f,m,g,h,D,4,b[40]),h=l(h,f,m,g,c,11,b[41]),g=l(g,h,f,m,k,16,b[42]),m=l(m,g,h,f,t,23,b[43]),f=l(f,m,g,h,A,4,b[44]),h=l(h,f,m,g,u,11,b[45]),g=l(g,h,f,m,x,16,b[46]),m=l(m,g,h,f,j,23,b[47]),f=s(f,m,g,h,c,6,b[48]),h=s(h,f,m,g,w,10,b[49]),g=s(g,h,f,m, -E,15,b[50]),m=s(m,g,h,f,r,21,b[51]),f=s(f,m,g,h,u,6,b[52]),h=s(h,f,m,g,k,10,b[53]),g=s(g,h,f,m,B,15,b[54]),m=s(m,g,h,f,e,21,b[55]),f=s(f,m,g,h,v,6,b[56]),h=s(h,f,m,g,x,10,b[57]),g=s(g,h,f,m,t,15,b[58]),m=s(m,g,h,f,D,21,b[59]),f=s(f,m,g,h,z,6,b[60]),h=s(h,f,m,g,C,10,b[61]),g=s(g,h,f,m,j,15,b[62]),m=s(m,g,h,f,A,21,b[63]);a[0]=a[0]+f|0;a[1]=a[1]+m|0;a[2]=a[2]+g|0;a[3]=a[3]+h|0},_doFinalize:function(){var b=this._data,n=b.words,a=8*this._nDataBytes,c=8*b.sigBytes;n[c>>>5]|=128<<24-c%32;var e=u.floor(a/ -4294967296);n[(c+64>>>9<<4)+15]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360;n[(c+64>>>9<<4)+14]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;b.sigBytes=4*(n.length+1);this._process();b=this._hash;n=b.words;for(a=0;4>a;a++)c=n[a],n[a]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360;return b},clone:function(){var b=v.clone.call(this);b._hash=this._hash.clone();return b}});t.MD5=v._createHelper(r);t.HmacMD5=v._createHmacHelper(r)})(Math); -(function(){var u=CryptoJS,p=u.lib,d=p.Base,l=p.WordArray,p=u.algo,s=p.EvpKDF=d.extend({cfg:d.extend({keySize:4,hasher:p.MD5,iterations:1}),init:function(d){this.cfg=this.cfg.extend(d)},compute:function(d,r){for(var p=this.cfg,s=p.hasher.create(),b=l.create(),u=b.words,q=p.keySize,p=p.iterations;u.length>>2]&255}};d.BlockCipher=v.extend({cfg:v.cfg.extend({mode:b,padding:q}),reset:function(){v.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this._xformMode==this._ENC_XFORM_MODE)var c=a.createEncryptor;else c=a.createDecryptor,this._minBufferSize=1;this._mode=c.call(a, -this,b&&b.words)},_doProcessBlock:function(a,b){this._mode.processBlock(a,b)},_doFinalize:function(){var a=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){a.pad(this._data,this.blockSize);var b=this._process(!0)}else b=this._process(!0),a.unpad(b);return b},blockSize:4});var n=d.CipherParams=l.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),b=(p.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a=a.salt;return(a?s.create([1398893684, -1701076831]).concat(a).concat(b):b).toString(r)},parse:function(a){a=r.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var c=s.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return n.create({ciphertext:a,salt:c})}},a=d.SerializableCipher=l.extend({cfg:l.extend({format:b}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);var l=a.createEncryptor(c,d);b=l.finalize(b);l=l.cfg;return n.create({ciphertext:b,key:c,iv:l.iv,algorithm:a,mode:l.mode,padding:l.padding,blockSize:a.blockSize,formatter:d.format})}, -decrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this._parse(b,d.format);return a.createDecryptor(c,d).finalize(b.ciphertext)},_parse:function(a,b){return"string"==typeof a?b.parse(a,this):a}}),p=(p.kdf={}).OpenSSL={execute:function(a,b,c,d){d||(d=s.random(8));a=w.create({keySize:b+c}).compute(a,d);c=s.create(a.words.slice(b),4*c);a.sigBytes=4*b;return n.create({key:a,iv:c,salt:d})}},c=d.PasswordBasedCipher=a.extend({cfg:a.cfg.extend({kdf:p}),encrypt:function(b,c,d,l){l=this.cfg.extend(l);d=l.kdf.execute(d, -b.keySize,b.ivSize);l.iv=d.iv;b=a.encrypt.call(this,b,c,d.key,l);b.mixIn(d);return b},decrypt:function(b,c,d,l){l=this.cfg.extend(l);c=this._parse(c,l.format);d=l.kdf.execute(d,b.keySize,b.ivSize,c.salt);l.iv=d.iv;return a.decrypt.call(this,b,c,d.key,l)}})}(); -(function(){for(var u=CryptoJS,p=u.lib.BlockCipher,d=u.algo,l=[],s=[],t=[],r=[],w=[],v=[],b=[],x=[],q=[],n=[],a=[],c=0;256>c;c++)a[c]=128>c?c<<1:c<<1^283;for(var e=0,j=0,c=0;256>c;c++){var k=j^j<<1^j<<2^j<<3^j<<4,k=k>>>8^k&255^99;l[e]=k;s[k]=e;var z=a[e],F=a[z],G=a[F],y=257*a[k]^16843008*k;t[e]=y<<24|y>>>8;r[e]=y<<16|y>>>16;w[e]=y<<8|y>>>24;v[e]=y;y=16843009*G^65537*F^257*z^16843008*e;b[k]=y<<24|y>>>8;x[k]=y<<16|y>>>16;q[k]=y<<8|y>>>24;n[k]=y;e?(e=z^a[a[a[G^z]]],j^=a[a[j]]):e=j=1}var H=[0,1,2,4,8, -16,32,64,128,27,54],d=d.AES=p.extend({_doReset:function(){for(var a=this._key,c=a.words,d=a.sigBytes/4,a=4*((this._nRounds=d+6)+1),e=this._keySchedule=[],j=0;j>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255]):(k=k<<8|k>>>24,k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255],k^=H[j/d|0]<<24);e[j]=e[j-d]^k}c=this._invKeySchedule=[];for(d=0;dd||4>=j?k:b[l[k>>>24]]^x[l[k>>>16&255]]^q[l[k>>> -8&255]]^n[l[k&255]]},encryptBlock:function(a,b){this._doCryptBlock(a,b,this._keySchedule,t,r,w,v,l)},decryptBlock:function(a,c){var d=a[c+1];a[c+1]=a[c+3];a[c+3]=d;this._doCryptBlock(a,c,this._invKeySchedule,b,x,q,n,s);d=a[c+1];a[c+1]=a[c+3];a[c+3]=d},_doCryptBlock:function(a,b,c,d,e,j,l,f){for(var m=this._nRounds,g=a[b]^c[0],h=a[b+1]^c[1],k=a[b+2]^c[2],n=a[b+3]^c[3],p=4,r=1;r>>24]^e[h>>>16&255]^j[k>>>8&255]^l[n&255]^c[p++],s=d[h>>>24]^e[k>>>16&255]^j[n>>>8&255]^l[g&255]^c[p++],t= -d[k>>>24]^e[n>>>16&255]^j[g>>>8&255]^l[h&255]^c[p++],n=d[n>>>24]^e[g>>>16&255]^j[h>>>8&255]^l[k&255]^c[p++],g=q,h=s,k=t;q=(f[g>>>24]<<24|f[h>>>16&255]<<16|f[k>>>8&255]<<8|f[n&255])^c[p++];s=(f[h>>>24]<<24|f[k>>>16&255]<<16|f[n>>>8&255]<<8|f[g&255])^c[p++];t=(f[k>>>24]<<24|f[n>>>16&255]<<16|f[g>>>8&255]<<8|f[h&255])^c[p++];n=(f[n>>>24]<<24|f[g>>>16&255]<<16|f[h>>>8&255]<<8|f[k&255])^c[p++];a[b]=q;a[b+1]=s;a[b+2]=t;a[b+3]=n},keySize:8});u.AES=p._createHelper(d)})(); diff --git a/js/libs/blob.js b/js/libs/blob.js deleted file mode 100644 index 5893afc..0000000 --- a/js/libs/blob.js +++ /dev/null @@ -1,166 +0,0 @@ -/* Blob.js - * A Blob implementation. - * 2013-06-20 - * - * By Eli Grey, http://eligrey.com - * By Devin Samarin, https://github.com/eboyjr - * License: X11/MIT - * See LICENSE.md - */ - -/*global self, unescape */ -/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, - plusplus: true */ - -/*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */ - -if (!(typeof Blob === "function" || typeof Blob === "object") || typeof URL === "undefined") -if ((typeof Blob === "function" || typeof Blob === "object") && typeof webkitURL !== "undefined") self.URL = webkitURL; -else var Blob = (function (view) { - "use strict"; - - var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || view.MSBlobBuilder || (function(view) { - var - get_class = function(object) { - return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1]; - } - , FakeBlobBuilder = function BlobBuilder() { - this.data = []; - } - , FakeBlob = function Blob(data, type, encoding) { - this.data = data; - this.size = data.length; - this.type = type; - this.encoding = encoding; - } - , FBB_proto = FakeBlobBuilder.prototype - , FB_proto = FakeBlob.prototype - , FileReaderSync = view.FileReaderSync - , FileException = function(type) { - this.code = this[this.name = type]; - } - , file_ex_codes = ( - "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR " - + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR" - ).split(" ") - , file_ex_code = file_ex_codes.length - , real_URL = view.URL || view.webkitURL || view - , real_create_object_URL = real_URL.createObjectURL - , real_revoke_object_URL = real_URL.revokeObjectURL - , URL = real_URL - , btoa = view.btoa - , atob = view.atob - - , ArrayBuffer = view.ArrayBuffer - , Uint8Array = view.Uint8Array - ; - FakeBlob.fake = FB_proto.fake = true; - while (file_ex_code--) { - FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1; - } - if (!real_URL.createObjectURL) { - URL = view.URL = {}; - } - URL.createObjectURL = function(blob) { - var - type = blob.type - , data_URI_header - ; - if (type === null) { - type = "application/octet-stream"; - } - if (blob instanceof FakeBlob) { - data_URI_header = "data:" + type; - if (blob.encoding === "base64") { - return data_URI_header + ";base64," + blob.data; - } else if (blob.encoding === "URI") { - return data_URI_header + "," + decodeURIComponent(blob.data); - } if (btoa) { - return data_URI_header + ";base64," + btoa(blob.data); - } else { - return data_URI_header + "," + encodeURIComponent(blob.data); - } - } else if (real_create_object_URL) { - return real_create_object_URL.call(real_URL, blob); - } - }; - URL.revokeObjectURL = function(object_URL) { - if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) { - real_revoke_object_URL.call(real_URL, object_URL); - } - }; - FBB_proto.append = function(data/*, endings*/) { - var bb = this.data; - // decode data to a binary string - if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) { - var - str = "" - , buf = new Uint8Array(data) - , i = 0 - , buf_len = buf.length - ; - for (; i < buf_len; i++) { - str += String.fromCharCode(buf[i]); - } - bb.push(str); - } else if (get_class(data) === "Blob" || get_class(data) === "File") { - if (FileReaderSync) { - var fr = new FileReaderSync; - bb.push(fr.readAsBinaryString(data)); - } else { - // async FileReader won't work as BlobBuilder is sync - throw new FileException("NOT_READABLE_ERR"); - } - } else if (data instanceof FakeBlob) { - if (data.encoding === "base64" && atob) { - bb.push(atob(data.data)); - } else if (data.encoding === "URI") { - bb.push(decodeURIComponent(data.data)); - } else if (data.encoding === "raw") { - bb.push(data.data); - } - } else { - if (typeof data !== "string") { - data += ""; // convert unsupported types to strings - } - // decode UTF-16 to binary string - bb.push(unescape(encodeURIComponent(data))); - } - }; - FBB_proto.getBlob = function(type) { - if (!arguments.length) { - type = null; - } - return new FakeBlob(this.data.join(""), type, "raw"); - }; - FBB_proto.toString = function() { - return "[object BlobBuilder]"; - }; - FB_proto.slice = function(start, end, type) { - var args = arguments.length; - if (args < 3) { - type = null; - } - return new FakeBlob( - this.data.slice(start, args > 1 ? end : this.data.length) - , type - , this.encoding - ); - }; - FB_proto.toString = function() { - return "[object Blob]"; - }; - return FakeBlobBuilder; - }(view)); - - return function Blob(blobParts, options) { - var type = options ? (options.type || "") : ""; - var builder = new BlobBuilder(); - if (blobParts) { - for (var i = 0, len = blobParts.length; i < len; i++) { - builder.append(blobParts[i]); - } - } - return builder.getBlob(type); - }; -}(self)); diff --git a/js/libs/bootstrap-fileupload.js b/js/libs/bootstrap-fileupload.js deleted file mode 100644 index 97a6da5..0000000 --- a/js/libs/bootstrap-fileupload.js +++ /dev/null @@ -1,169 +0,0 @@ -/* =========================================================== - * bootstrap-fileupload.js j2 - * http://jasny.github.com/bootstrap/javascript.html#fileupload - * =========================================================== - * Copyright 2012 Jasny BV, Netherlands. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================== */ - -!function ($) { - - "use strict"; // jshint ;_ - - /* FILEUPLOAD PUBLIC CLASS DEFINITION - * ================================= */ - - var Fileupload = function (element, options) { - this.$element = $(element) - this.type = this.$element.data('uploadtype') || (this.$element.find('.thumbnail').length > 0 ? "image" : "file") - - this.$input = this.$element.find(':file') - if (this.$input.length === 0) return - - this.name = this.$input.attr('name') || options.name - - this.$hidden = this.$element.find('input[type=hidden][name="'+this.name+'"]') - if (this.$hidden.length === 0) { - this.$hidden = $('') - this.$element.prepend(this.$hidden) - } - - this.$preview = this.$element.find('.fileupload-preview') - var height = this.$preview.css('height') - if (this.$preview.css('display') != 'inline' && height != '0px' && height != 'none') this.$preview.css('line-height', height) - - this.original = { - 'exists': this.$element.hasClass('fileupload-exists'), - 'preview': this.$preview.html(), - 'hiddenVal': this.$hidden.val() - } - - this.$remove = this.$element.find('[data-dismiss="fileupload"]') - - this.$element.find('[data-trigger="fileupload"]').on('click.fileupload', $.proxy(this.trigger, this)) - - this.listen() - } - - Fileupload.prototype = { - - listen: function() { - this.$input.on('change.fileupload', $.proxy(this.change, this)) - $(this.$input[0].form).on('reset.fileupload', $.proxy(this.reset, this)) - if (this.$remove) this.$remove.on('click.fileupload', $.proxy(this.clear, this)) - }, - - change: function(e, invoked) { - if (invoked === 'clear') return - - var file = e.target.files !== undefined ? e.target.files[0] : (e.target.value ? { name: e.target.value.replace(/^.+\\/, '') } : null) - - if (!file) { - this.clear() - return - } - - this.$hidden.val('') - this.$hidden.attr('name', '') - this.$input.attr('name', this.name) - - if (this.type === "image" && this.$preview.length > 0 && (typeof file.type !== "undefined" ? file.type.match('image.*') : file.name.match(/\.(gif|png|jpe?g)$/i)) && typeof FileReader !== "undefined") { - var reader = new FileReader() - var preview = this.$preview - var element = this.$element - - reader.onload = function(e) { - preview.html('') - element.addClass('fileupload-exists').removeClass('fileupload-new') - } - - reader.readAsDataURL(file) - } else { - this.$preview.text(file.name) - this.$element.addClass('fileupload-exists').removeClass('fileupload-new') - } - }, - - clear: function(e) { - this.$hidden.val('') - this.$hidden.attr('name', this.name) - this.$input.attr('name', '') - - //ie8+ doesn't support changing the value of input with type=file so clone instead - if (navigator.userAgent.match(/msie/i)){ - var inputClone = this.$input.clone(true); - this.$input.after(inputClone); - this.$input.remove(); - this.$input = inputClone; - }else{ - this.$input.val('') - } - - this.$preview.html('') - this.$element.addClass('fileupload-new').removeClass('fileupload-exists') - - if (e) { - this.$input.trigger('change', [ 'clear' ]) - e.preventDefault() - } - }, - - reset: function(e) { - this.clear() - - this.$hidden.val(this.original.hiddenVal) - this.$preview.html(this.original.preview) - - if (this.original.exists) this.$element.addClass('fileupload-exists').removeClass('fileupload-new') - else this.$element.addClass('fileupload-new').removeClass('fileupload-exists') - }, - - trigger: function(e) { - this.$input.trigger('click') - e.preventDefault() - } - } - - - /* FILEUPLOAD PLUGIN DEFINITION - * =========================== */ - - $.fn.fileupload = function (options) { - return this.each(function () { - var $this = $(this) - , data = $this.data('fileupload') - if (!data) $this.data('fileupload', (data = new Fileupload(this, options))) - if (typeof options == 'string') data[options]() - }) - } - - $.fn.fileupload.Constructor = Fileupload - - - /* FILEUPLOAD DATA-API - * ================== */ - - $(document).on('click.fileupload.data-api', '[data-provides="fileupload"]', function (e) { - var $this = $(this) - if ($this.data('fileupload')) return - $this.fileupload($this.data()) - - var $target = $(e.target).closest('[data-dismiss="fileupload"],[data-trigger="fileupload"]'); - if ($target.length > 0) { - $target.trigger('click.fileupload') - e.preventDefault() - } - }) - -}(window.jQuery); diff --git a/js/libs/bootstrap-popover.js b/js/libs/bootstrap-popover.js deleted file mode 100755 index 924844e..0000000 --- a/js/libs/bootstrap-popover.js +++ /dev/null @@ -1,95 +0,0 @@ -/* =========================================================== - * bootstrap-popover.js v2.0.1 - * http://twitter.github.com/bootstrap/javascript.html#popovers - * =========================================================== - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================================================== */ - - -!function( $ ) { - - "use strict" - - var Popover = function ( element, options ) { - this.init('popover', element, options) - } - - /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js - ========================================== */ - - Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, { - - constructor: Popover - - , setContent: function () { - var $tip = this.tip() - , title = this.getTitle() - , content = this.getContent() - - $tip.find('.popover-title')[ $.type(title) == 'object' ? 'append' : 'html' ](title) - $tip.find('.popover-content > *')[ $.type(content) == 'object' ? 'append' : 'html' ](content) - - $tip.removeClass('fade top bottom left right in') - } - - , hasContent: function () { - return this.getTitle() || this.getContent() - } - - , getContent: function () { - var content - , $e = this.$element - , o = this.options - - content = $e.attr('data-content') - || (typeof o.content == 'function' ? o.content.call($e[0]) : o.content) - - content = content.toString().replace(/(^\s*|\s*$)/, "") - - return content - } - - , tip: function() { - if (!this.$tip) { - this.$tip = $(this.options.template) - } - return this.$tip - } - - }) - - - /* POPOVER PLUGIN DEFINITION - * ======================= */ - - $.fn.popover = function ( option ) { - return this.each(function () { - var $this = $(this) - , data = $this.data('popover') - , options = typeof option == 'object' && option - if (!data) $this.data('popover', (data = new Popover(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - $.fn.popover.Constructor = Popover - - $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, { - placement: 'right' - , content: '' - , template: '

' - }) - -}( window.jQuery ); \ No newline at end of file diff --git a/js/libs/bootstrap-tooltip.js b/js/libs/bootstrap-tooltip.js deleted file mode 100755 index d76e51e..0000000 --- a/js/libs/bootstrap-tooltip.js +++ /dev/null @@ -1,270 +0,0 @@ -/* =========================================================== - * bootstrap-tooltip.js v2.0.1 - * http://twitter.github.com/bootstrap/javascript.html#tooltips - * Inspired by the original jQuery.tipsy by Jason Frame - * =========================================================== - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================== */ - -!function( $ ) { - - "use strict" - - /* TOOLTIP PUBLIC CLASS DEFINITION - * =============================== */ - - var Tooltip = function ( element, options ) { - this.init('tooltip', element, options) - } - - Tooltip.prototype = { - - constructor: Tooltip - - , init: function ( type, element, options ) { - var eventIn - , eventOut - - this.type = type - this.$element = $(element) - this.options = this.getOptions(options) - this.enabled = true - - if (this.options.trigger != 'manual') { - eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus' - eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur' - this.$element.on(eventIn, this.options.selector, $.proxy(this.enter, this)) - this.$element.on(eventOut, this.options.selector, $.proxy(this.leave, this)) - } - - this.options.selector ? - (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : - this.fixTitle() - } - - , getOptions: function ( options ) { - options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data()) - - if (options.delay && typeof options.delay == 'number') { - options.delay = { - show: options.delay - , hide: options.delay - } - } - - return options - } - - , enter: function ( e ) { - var self = $(e.currentTarget)[this.type](this._options).data(this.type) - - if (!self.options.delay || !self.options.delay.show) { - self.show() - } else { - self.hoverState = 'in' - setTimeout(function() { - if (self.hoverState == 'in') { - self.show() - } - }, self.options.delay.show) - } - } - - , leave: function ( e ) { - var self = $(e.currentTarget)[this.type](this._options).data(this.type) - - if (!self.options.delay || !self.options.delay.hide) { - self.hide() - } else { - self.hoverState = 'out' - setTimeout(function() { - if (self.hoverState == 'out') { - self.hide() - } - }, self.options.delay.hide) - } - } - - , show: function () { - var $tip - , inside - , pos - , actualWidth - , actualHeight - , placement - , tp - - if (this.hasContent() && this.enabled) { - $tip = this.tip() - this.setContent() - - if (this.options.animation) { - $tip.addClass('fade') - } - - placement = typeof this.options.placement == 'function' ? - this.options.placement.call(this, $tip[0], this.$element[0]) : - this.options.placement - - inside = /in/.test(placement) - - $tip - .remove() - .css({ top: 0, left: 0, display: 'block' }) - .appendTo(inside ? this.$element : document.body) - - pos = this.getPosition(inside) - - actualWidth = $tip[0].offsetWidth - actualHeight = $tip[0].offsetHeight - - switch (inside ? placement.split(' ')[1] : placement) { - case 'bottom': - tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2} - break - case 'top': - tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2} - break - case 'left': - tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth} - break - case 'right': - tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width} - break - } - - $tip - .css(tp) - .addClass(placement) - .addClass('in') - } - } - - , setContent: function () { - var $tip = this.tip() - $tip.find('.tooltip-inner').html(this.getTitle()) - $tip.removeClass('fade in top bottom left right') - } - - , hide: function () { - var that = this - , $tip = this.tip() - - $tip.removeClass('in') - - function removeWithAnimation() { - var timeout = setTimeout(function () { - $tip.off($.support.transition.end).remove() - }, 500) - - $tip.one($.support.transition.end, function () { - clearTimeout(timeout) - $tip.remove() - }) - } - - $.support.transition && this.$tip.hasClass('fade') ? - removeWithAnimation() : - $tip.remove() - } - - , fixTitle: function () { - var $e = this.$element - if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { - $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title') - } - } - - , hasContent: function () { - return this.getTitle() - } - - , getPosition: function (inside) { - return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), { - width: this.$element[0].offsetWidth - , height: this.$element[0].offsetHeight - }) - } - - , getTitle: function () { - var title - , $e = this.$element - , o = this.options - - title = $e.attr('data-original-title') - || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) - - title = title.toString().replace(/(^\s*|\s*$)/, "") - - return title - } - - , tip: function () { - return this.$tip = this.$tip || $(this.options.template) - } - - , validate: function () { - if (!this.$element[0].parentNode) { - this.hide() - this.$element = null - this.options = null - } - } - - , enable: function () { - this.enabled = true - } - - , disable: function () { - this.enabled = false - } - - , toggleEnabled: function () { - this.enabled = !this.enabled - } - - , toggle: function () { - this[this.tip().hasClass('in') ? 'hide' : 'show']() - } - - } - - - /* TOOLTIP PLUGIN DEFINITION - * ========================= */ - - $.fn.tooltip = function ( option ) { - return this.each(function () { - var $this = $(this) - , data = $this.data('tooltip') - , options = typeof option == 'object' && option - if (!data) $this.data('tooltip', (data = new Tooltip(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - $.fn.tooltip.Constructor = Tooltip - - $.fn.tooltip.defaults = { - animation: true - , delay: 0 - , selector: false - , placement: 'top' - , trigger: 'hover' - , title: '' - , template: '
' - } - -}( window.jQuery ); \ No newline at end of file diff --git a/js/libs/core.js b/js/libs/core.js deleted file mode 100644 index 996aa07..0000000 --- a/js/libs/core.js +++ /dev/null @@ -1,712 +0,0 @@ -/* -CryptoJS v3.1.2 -code.google.com/p/crypto-js -(c) 2009-2013 by Jeff Mott. All rights reserved. -code.google.com/p/crypto-js/wiki/License -*/ -/** - * CryptoJS core components. - */ -var CryptoJS = CryptoJS || (function (Math, undefined) { - /** - * CryptoJS namespace. - */ - var C = {}; - - /** - * Library namespace. - */ - var C_lib = C.lib = {}; - - /** - * Base object for prototypal inheritance. - */ - var Base = C_lib.Base = (function () { - function F() {} - - return { - /** - * Creates a new object that inherits from this object. - * - * @param {Object} overrides Properties to copy into the new object. - * - * @return {Object} The new object. - * - * @static - * - * @example - * - * var MyType = CryptoJS.lib.Base.extend({ - * field: 'value', - * - * method: function () { - * } - * }); - */ - extend: function (overrides) { - // Spawn - F.prototype = this; - var subtype = new F(); - - // Augment - if (overrides) { - subtype.mixIn(overrides); - } - - // Create default initializer - if (!subtype.hasOwnProperty('init')) { - subtype.init = function () { - subtype.$super.init.apply(this, arguments); - }; - } - - // Initializer's prototype is the subtype object - subtype.init.prototype = subtype; - - // Reference supertype - subtype.$super = this; - - return subtype; - }, - - /** - * Extends this object and runs the init method. - * Arguments to create() will be passed to init(). - * - * @return {Object} The new object. - * - * @static - * - * @example - * - * var instance = MyType.create(); - */ - create: function () { - var instance = this.extend(); - instance.init.apply(instance, arguments); - - return instance; - }, - - /** - * Initializes a newly created object. - * Override this method to add some logic when your objects are created. - * - * @example - * - * var MyType = CryptoJS.lib.Base.extend({ - * init: function () { - * // ... - * } - * }); - */ - init: function () { - }, - - /** - * Copies properties into this object. - * - * @param {Object} properties The properties to mix in. - * - * @example - * - * MyType.mixIn({ - * field: 'value' - * }); - */ - mixIn: function (properties) { - for (var propertyName in properties) { - if (properties.hasOwnProperty(propertyName)) { - this[propertyName] = properties[propertyName]; - } - } - - // IE won't copy toString using the loop above - if (properties.hasOwnProperty('toString')) { - this.toString = properties.toString; - } - }, - - /** - * Creates a copy of this object. - * - * @return {Object} The clone. - * - * @example - * - * var clone = instance.clone(); - */ - clone: function () { - return this.init.prototype.extend(this); - } - }; - }()); - - /** - * An array of 32-bit words. - * - * @property {Array} words The array of 32-bit words. - * @property {number} sigBytes The number of significant bytes in this word array. - */ - var WordArray = C_lib.WordArray = Base.extend({ - /** - * Initializes a newly created word array. - * - * @param {Array} words (Optional) An array of 32-bit words. - * @param {number} sigBytes (Optional) The number of significant bytes in the words. - * - * @example - * - * var wordArray = CryptoJS.lib.WordArray.create(); - * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]); - * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6); - */ - init: function (words, sigBytes) { - words = this.words = words || []; - - if (sigBytes != undefined) { - this.sigBytes = sigBytes; - } else { - this.sigBytes = words.length * 4; - } - }, - - /** - * Converts this word array to a string. - * - * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex - * - * @return {string} The stringified word array. - * - * @example - * - * var string = wordArray + ''; - * var string = wordArray.toString(); - * var string = wordArray.toString(CryptoJS.enc.Utf8); - */ - toString: function (encoder) { - return (encoder || Hex).stringify(this); - }, - - /** - * Concatenates a word array to this word array. - * - * @param {WordArray} wordArray The word array to append. - * - * @return {WordArray} This word array. - * - * @example - * - * wordArray1.concat(wordArray2); - */ - concat: function (wordArray) { - // Shortcuts - var thisWords = this.words; - var thatWords = wordArray.words; - var thisSigBytes = this.sigBytes; - var thatSigBytes = wordArray.sigBytes; - - // Clamp excess bits - this.clamp(); - - // Concat - if (thisSigBytes % 4) { - // Copy one byte at a time - for (var i = 0; i < thatSigBytes; i++) { - var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; - thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8); - } - } else if (thatWords.length > 0xffff) { - // Copy one word at a time - for (var i = 0; i < thatSigBytes; i += 4) { - thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2]; - } - } else { - // Copy all words at once - thisWords.push.apply(thisWords, thatWords); - } - this.sigBytes += thatSigBytes; - - // Chainable - return this; - }, - - /** - * Removes insignificant bits. - * - * @example - * - * wordArray.clamp(); - */ - clamp: function () { - // Shortcuts - var words = this.words; - var sigBytes = this.sigBytes; - - // Clamp - words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8); - words.length = Math.ceil(sigBytes / 4); - }, - - /** - * Creates a copy of this word array. - * - * @return {WordArray} The clone. - * - * @example - * - * var clone = wordArray.clone(); - */ - clone: function () { - var clone = Base.clone.call(this); - clone.words = this.words.slice(0); - - return clone; - }, - - /** - * Creates a word array filled with random bytes. - * - * @param {number} nBytes The number of random bytes to generate. - * - * @return {WordArray} The random word array. - * - * @static - * - * @example - * - * var wordArray = CryptoJS.lib.WordArray.random(16); - */ - random: function (nBytes) { - var words = []; - for (var i = 0; i < nBytes; i += 4) { - words.push((Math.random() * 0x100000000) | 0); - } - - return new WordArray.init(words, nBytes); - } - }); - - /** - * Encoder namespace. - */ - var C_enc = C.enc = {}; - - /** - * Hex encoding strategy. - */ - var Hex = C_enc.Hex = { - /** - * Converts a word array to a hex string. - * - * @param {WordArray} wordArray The word array. - * - * @return {string} The hex string. - * - * @static - * - * @example - * - * var hexString = CryptoJS.enc.Hex.stringify(wordArray); - */ - stringify: function (wordArray) { - // Shortcuts - var words = wordArray.words; - var sigBytes = wordArray.sigBytes; - - // Convert - var hexChars = []; - for (var i = 0; i < sigBytes; i++) { - var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; - hexChars.push((bite >>> 4).toString(16)); - hexChars.push((bite & 0x0f).toString(16)); - } - - return hexChars.join(''); - }, - - /** - * Converts a hex string to a word array. - * - * @param {string} hexStr The hex string. - * - * @return {WordArray} The word array. - * - * @static - * - * @example - * - * var wordArray = CryptoJS.enc.Hex.parse(hexString); - */ - parse: function (hexStr) { - // Shortcut - var hexStrLength = hexStr.length; - - // Convert - var words = []; - for (var i = 0; i < hexStrLength; i += 2) { - words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4); - } - - return new WordArray.init(words, hexStrLength / 2); - } - }; - - /** - * Latin1 encoding strategy. - */ - var Latin1 = C_enc.Latin1 = { - /** - * Converts a word array to a Latin1 string. - * - * @param {WordArray} wordArray The word array. - * - * @return {string} The Latin1 string. - * - * @static - * - * @example - * - * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray); - */ - stringify: function (wordArray) { - // Shortcuts - var words = wordArray.words; - var sigBytes = wordArray.sigBytes; - - // Convert - var latin1Chars = []; - for (var i = 0; i < sigBytes; i++) { - var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; - latin1Chars.push(String.fromCharCode(bite)); - } - - return latin1Chars.join(''); - }, - - /** - * Converts a Latin1 string to a word array. - * - * @param {string} latin1Str The Latin1 string. - * - * @return {WordArray} The word array. - * - * @static - * - * @example - * - * var wordArray = CryptoJS.enc.Latin1.parse(latin1String); - */ - parse: function (latin1Str) { - // Shortcut - var latin1StrLength = latin1Str.length; - - // Convert - var words = []; - for (var i = 0; i < latin1StrLength; i++) { - words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8); - } - - return new WordArray.init(words, latin1StrLength); - } - }; - - /** - * UTF-8 encoding strategy. - */ - var Utf8 = C_enc.Utf8 = { - /** - * Converts a word array to a UTF-8 string. - * - * @param {WordArray} wordArray The word array. - * - * @return {string} The UTF-8 string. - * - * @static - * - * @example - * - * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray); - */ - stringify: function (wordArray) { - try { - return decodeURIComponent(escape(Latin1.stringify(wordArray))); - } catch (e) { - throw new Error('Malformed UTF-8 data'); - } - }, - - /** - * Converts a UTF-8 string to a word array. - * - * @param {string} utf8Str The UTF-8 string. - * - * @return {WordArray} The word array. - * - * @static - * - * @example - * - * var wordArray = CryptoJS.enc.Utf8.parse(utf8String); - */ - parse: function (utf8Str) { - return Latin1.parse(unescape(encodeURIComponent(utf8Str))); - } - }; - - /** - * Abstract buffered block algorithm template. - * - * The property blockSize must be implemented in a concrete subtype. - * - * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0 - */ - var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({ - /** - * Resets this block algorithm's data buffer to its initial state. - * - * @example - * - * bufferedBlockAlgorithm.reset(); - */ - reset: function () { - // Initial values - this._data = new WordArray.init(); - this._nDataBytes = 0; - }, - - /** - * Adds new data to this block algorithm's buffer. - * - * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8. - * - * @example - * - * bufferedBlockAlgorithm._append('data'); - * bufferedBlockAlgorithm._append(wordArray); - */ - _append: function (data) { - // Convert string to WordArray, else assume WordArray already - if (typeof data == 'string') { - data = Utf8.parse(data); - } - - // Append - this._data.concat(data); - this._nDataBytes += data.sigBytes; - }, - - /** - * Processes available data blocks. - * - * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype. - * - * @param {boolean} doFlush Whether all blocks and partial blocks should be processed. - * - * @return {WordArray} The processed data. - * - * @example - * - * var processedData = bufferedBlockAlgorithm._process(); - * var processedData = bufferedBlockAlgorithm._process(!!'flush'); - */ - _process: function (doFlush) { - // Shortcuts - var data = this._data; - var dataWords = data.words; - var dataSigBytes = data.sigBytes; - var blockSize = this.blockSize; - var blockSizeBytes = blockSize * 4; - - // Count blocks ready - var nBlocksReady = dataSigBytes / blockSizeBytes; - if (doFlush) { - // Round up to include partial blocks - nBlocksReady = Math.ceil(nBlocksReady); - } else { - // Round down to include only full blocks, - // less the number of blocks that must remain in the buffer - nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0); - } - - // Count words ready - var nWordsReady = nBlocksReady * blockSize; - - // Count bytes ready - var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); - - // Process blocks - if (nWordsReady) { - for (var offset = 0; offset < nWordsReady; offset += blockSize) { - // Perform concrete-algorithm logic - this._doProcessBlock(dataWords, offset); - } - - // Remove processed words - var processedWords = dataWords.splice(0, nWordsReady); - data.sigBytes -= nBytesReady; - } - - // Return processed words - return new WordArray.init(processedWords, nBytesReady); - }, - - /** - * Creates a copy of this object. - * - * @return {Object} The clone. - * - * @example - * - * var clone = bufferedBlockAlgorithm.clone(); - */ - clone: function () { - var clone = Base.clone.call(this); - clone._data = this._data.clone(); - - return clone; - }, - - _minBufferSize: 0 - }); - - /** - * Abstract hasher template. - * - * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits) - */ - var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({ - /** - * Configuration options. - */ - cfg: Base.extend(), - - /** - * Initializes a newly created hasher. - * - * @param {Object} cfg (Optional) The configuration options to use for this hash computation. - * - * @example - * - * var hasher = CryptoJS.algo.SHA256.create(); - */ - init: function (cfg) { - // Apply config defaults - this.cfg = this.cfg.extend(cfg); - - // Set initial values - this.reset(); - }, - - /** - * Resets this hasher to its initial state. - * - * @example - * - * hasher.reset(); - */ - reset: function () { - // Reset data buffer - BufferedBlockAlgorithm.reset.call(this); - - // Perform concrete-hasher logic - this._doReset(); - }, - - /** - * Updates this hasher with a message. - * - * @param {WordArray|string} messageUpdate The message to append. - * - * @return {Hasher} This hasher. - * - * @example - * - * hasher.update('message'); - * hasher.update(wordArray); - */ - update: function (messageUpdate) { - // Append - this._append(messageUpdate); - - // Update the hash - this._process(); - - // Chainable - return this; - }, - - /** - * Finalizes the hash computation. - * Note that the finalize operation is effectively a destructive, read-once operation. - * - * @param {WordArray|string} messageUpdate (Optional) A final message update. - * - * @return {WordArray} The hash. - * - * @example - * - * var hash = hasher.finalize(); - * var hash = hasher.finalize('message'); - * var hash = hasher.finalize(wordArray); - */ - finalize: function (messageUpdate) { - // Final message update - if (messageUpdate) { - this._append(messageUpdate); - } - - // Perform concrete-hasher logic - var hash = this._doFinalize(); - - return hash; - }, - - blockSize: 512/32, - - /** - * Creates a shortcut function to a hasher's object interface. - * - * @param {Hasher} hasher The hasher to create a helper for. - * - * @return {Function} The shortcut function. - * - * @static - * - * @example - * - * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256); - */ - _createHelper: function (hasher) { - return function (message, cfg) { - return new hasher.init(cfg).finalize(message); - }; - }, - - /** - * Creates a shortcut function to the HMAC's object interface. - * - * @param {Hasher} hasher The hasher to use in this HMAC helper. - * - * @return {Function} The shortcut function. - * - * @static - * - * @example - * - * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256); - */ - _createHmacHelper: function (hasher) { - return function (message, key) { - return new C_algo.HMAC.init(hasher, key).finalize(message); - }; - } - }); - - /** - * Algorithm namespace. - */ - var C_algo = C.algo = {}; - - return C; -}(Math)); diff --git a/js/libs/ember-data.js b/js/libs/ember-data.js deleted file mode 100644 index e07c21b..0000000 --- a/js/libs/ember-data.js +++ /dev/null @@ -1,8431 +0,0 @@ -// Last commit: 57d6c01 (2013-03-18 11:27:29 -0700) - - -(function() { -window.DS = Ember.Namespace.create({ - // this one goes past 11 - CURRENT_API_REVISION: 12 -}); - -})(); - - - -(function() { -var DeferredMixin = Ember.DeferredMixin, // ember-runtime/mixins/deferred - Evented = Ember.Evented, // ember-runtime/mixins/evented - run = Ember.run, // ember-metal/run-loop - get = Ember.get; // ember-metal/accessors - -var LoadPromise = Ember.Mixin.create(Evented, DeferredMixin, { - init: function() { - this._super.apply(this, arguments); - this.one('didLoad', function() { - run(this, 'resolve', this); - }); - - if (get(this, 'isLoaded')) { - this.trigger('didLoad'); - } - } -}); - -DS.LoadPromise = LoadPromise; - -})(); - - - -(function() { -var get = Ember.get, set = Ember.set; - -var LoadPromise = DS.LoadPromise; // system/mixins/load_promise - -/** - A record array is an array that contains records of a certain type. The record - array materializes records as needed when they are retrieved for the first - time. You should not create record arrays yourself. Instead, an instance of - DS.RecordArray or its subclasses will be returned by your application's store - in response to queries. -*/ - -DS.RecordArray = Ember.ArrayProxy.extend(Ember.Evented, LoadPromise, { - /** - The model type contained by this record array. - - @type DS.Model - */ - type: null, - - // The array of client ids backing the record array. When a - // record is requested from the record array, the record - // for the client id at the same index is materialized, if - // necessary, by the store. - content: null, - - isLoaded: false, - isUpdating: false, - - // The store that created this record array. - store: null, - - objectAtContent: function(index) { - var content = get(this, 'content'), - reference = content.objectAt(index), - store = get(this, 'store'); - - if (reference) { - return store.recordForReference(reference); - } - }, - - materializedObjectAt: function(index) { - var reference = get(this, 'content').objectAt(index); - if (!reference) { return; } - - if (get(this, 'store').recordIsMaterialized(reference)) { - return this.objectAt(index); - } - }, - - update: function() { - if (get(this, 'isUpdating')) { return; } - - var store = get(this, 'store'), - type = get(this, 'type'); - - store.fetchAll(type, this); - }, - - addReference: function(reference) { - get(this, 'content').addObject(reference); - }, - - removeReference: function(reference) { - get(this, 'content').removeObject(reference); - } -}); - -})(); - - - -(function() { -var get = Ember.get; - -DS.FilteredRecordArray = DS.RecordArray.extend({ - filterFunction: null, - isLoaded: true, - - replace: function() { - var type = get(this, 'type').toString(); - throw new Error("The result of a client-side filter (on " + type + ") is immutable."); - }, - - updateFilter: Ember.observer(function() { - var store = get(this, 'store'); - store.updateRecordArrayFilter(this, get(this, 'type'), get(this, 'filterFunction')); - }, 'filterFunction') -}); - -})(); - - - -(function() { -var get = Ember.get, set = Ember.set; - -DS.AdapterPopulatedRecordArray = DS.RecordArray.extend({ - query: null, - - replace: function() { - var type = get(this, 'type').toString(); - throw new Error("The result of a server query (on " + type + ") is immutable."); - }, - - load: function(references) { - var store = get(this, 'store'), type = get(this, 'type'); - - this.beginPropertyChanges(); - set(this, 'content', Ember.A(references)); - set(this, 'isLoaded', true); - this.endPropertyChanges(); - - var self = this; - // TODO: does triggering didLoad event should be the last action of the runLoop? - Ember.run.once(function() { - self.trigger('didLoad'); - }); - } -}); - -})(); - - - -(function() { -var get = Ember.get, set = Ember.set; - -/** - A ManyArray is a RecordArray that represents the contents of a has-many - relationship. - - The ManyArray is instantiated lazily the first time the relationship is - requested. - - ### Inverses - - Often, the relationships in Ember Data applications will have - an inverse. For example, imagine the following models are - defined: - - App.Post = DS.Model.extend({ - comments: DS.hasMany('App.Comment') - }); - - App.Comment = DS.Model.extend({ - post: DS.belongsTo('App.Post') - }); - - If you created a new instance of `App.Post` and added - a `App.Comment` record to its `comments` has-many - relationship, you would expect the comment's `post` - property to be set to the post that contained - the has-many. - - We call the record to which a relationship belongs the - relationship's _owner_. -*/ -DS.ManyArray = DS.RecordArray.extend({ - init: function() { - this._super.apply(this, arguments); - this._changesToSync = Ember.OrderedSet.create(); - }, - - /** - @private - - The record to which this relationship belongs. - - @property {DS.Model} - */ - owner: null, - - // LOADING STATE - - isLoaded: false, - - loadingRecordsCount: function(count) { - this.loadingRecordsCount = count; - }, - - loadedRecord: function() { - this.loadingRecordsCount--; - if (this.loadingRecordsCount === 0) { - set(this, 'isLoaded', true); - this.trigger('didLoad'); - } - }, - - fetch: function() { - var references = get(this, 'content'), - store = get(this, 'store'), - type = get(this, 'type'), - owner = get(this, 'owner'); - - store.fetchUnloadedReferences(type, references, owner); - }, - - // Overrides Ember.Array's replace method to implement - replaceContent: function(index, removed, added) { - // Map the array of record objects into an array of client ids. - added = added.map(function(record) { - Ember.assert("You can only add records of " + (get(this, 'type') && get(this, 'type').toString()) + " to this relationship.", !get(this, 'type') || (get(this, 'type') === record.constructor)); - return get(record, '_reference'); - }, this); - - this._super(index, removed, added); - }, - - arrangedContentDidChange: function() { - this.fetch(); - }, - - arrayContentWillChange: function(index, removed, added) { - var owner = get(this, 'owner'), - name = get(this, 'name'); - - if (!owner._suspendedRelationships) { - // This code is the first half of code that continues inside - // of arrayContentDidChange. It gets or creates a change from - // the child object, adds the current owner as the old - // parent if this is the first time the object was removed - // from a ManyArray, and sets `newParent` to null. - // - // Later, if the object is added to another ManyArray, - // the `arrayContentDidChange` will set `newParent` on - // the change. - for (var i=index; i "created.uncommitted" - - The `DS.Model` states are themselves stateless. What we mean is that, - though each instance of a record also has a unique instance of a - `DS.StateManager`, the hierarchical states that each of *those* points - to is a shared data structure. For performance reasons, instead of each - record getting its own copy of the hierarchy of states, each state - manager points to this global, immutable shared instance. How does a - state know which record it should be acting on? We pass a reference to - the current state manager as the first parameter to every method invoked - on a state. - - The state manager passed as the first parameter is where you should stash - state about the record if needed; you should never store data on the state - object itself. If you need access to the record being acted on, you can - retrieve the state manager's `record` property. For example, if you had - an event handler `myEvent`: - - myEvent: function(manager) { - var record = manager.get('record'); - record.doSomething(); - } - - For more information about state managers in general, see the Ember.js - documentation on `Ember.StateManager`. - - ### Events, Flags, and Transitions - - A state may implement zero or more events, flags, or transitions. - - #### Events - - Events are named functions that are invoked when sent to a record. The - state manager will first look for a method with the given name on the - current state. If no method is found, it will search the current state's - parent, and then its grandparent, and so on until reaching the top of - the hierarchy. If the root is reached without an event handler being found, - an exception will be raised. This can be very helpful when debugging new - features. - - Here's an example implementation of a state with a `myEvent` event handler: - - aState: DS.State.create({ - myEvent: function(manager, param) { - console.log("Received myEvent with "+param); - } - }) - - To trigger this event: - - record.send('myEvent', 'foo'); - //=> "Received myEvent with foo" - - Note that an optional parameter can be sent to a record's `send()` method, - which will be passed as the second parameter to the event handler. - - Events should transition to a different state if appropriate. This can be - done by calling the state manager's `transitionTo()` method with a path to the - desired state. The state manager will attempt to resolve the state path - relative to the current state. If no state is found at that path, it will - attempt to resolve it relative to the current state's parent, and then its - parent, and so on until the root is reached. For example, imagine a hierarchy - like this: - - * created - * start <-- currentState - * inFlight - * updated - * inFlight - - If we are currently in the `start` state, calling - `transitionTo('inFlight')` would transition to the `created.inFlight` state, - while calling `transitionTo('updated.inFlight')` would transition to - the `updated.inFlight` state. - - Remember that *only events* should ever cause a state transition. You should - never call `transitionTo()` from outside a state's event handler. If you are - tempted to do so, create a new event and send that to the state manager. - - #### Flags - - Flags are Boolean values that can be used to introspect a record's current - state in a more user-friendly way than examining its state path. For example, - instead of doing this: - - var statePath = record.get('stateManager.currentPath'); - if (statePath === 'created.inFlight') { - doSomething(); - } - - You can say: - - if (record.get('isNew') && record.get('isSaving')) { - doSomething(); - } - - If your state does not set a value for a given flag, the value will - be inherited from its parent (or the first place in the state hierarchy - where it is defined). - - The current set of flags are defined below. If you want to add a new flag, - in addition to the area below, you will also need to declare it in the - `DS.Model` class. - - #### Transitions - - Transitions are like event handlers but are called automatically upon - entering or exiting a state. To implement a transition, just call a method - either `enter` or `exit`: - - myState: DS.State.create({ - // Gets called automatically when entering - // this state. - enter: function(manager) { - console.log("Entered myState"); - } - }) - - Note that enter and exit events are called once per transition. If the - current state changes, but changes to another child state of the parent, - the transition event on the parent will not be triggered. -*/ - -var stateProperty = Ember.computed(function(key) { - var parent = get(this, 'parentState'); - if (parent) { - return get(parent, key); - } -}).property(); - -var hasDefinedProperties = function(object) { - for (var name in object) { - if (object.hasOwnProperty(name) && object[name]) { return true; } - } - - return false; -}; - -var didChangeData = function(manager) { - var record = get(manager, 'record'); - record.materializeData(); -}; - -var willSetProperty = function(manager, context) { - context.oldValue = get(get(manager, 'record'), context.name); - - var change = DS.AttributeChange.createChange(context); - get(manager, 'record')._changesToSync[context.attributeName] = change; -}; - -var didSetProperty = function(manager, context) { - var change = get(manager, 'record')._changesToSync[context.attributeName]; - change.value = get(get(manager, 'record'), context.name); - change.sync(); -}; - -DS.State = Ember.State.extend({ - isLoaded: stateProperty, - isReloading: stateProperty, - isDirty: stateProperty, - isSaving: stateProperty, - isDeleted: stateProperty, - isError: stateProperty, - isNew: stateProperty, - isValid: stateProperty, - - // For states that are substates of a - // DirtyState (updated or created), it is - // useful to be able to determine which - // type of dirty state it is. - dirtyType: stateProperty -}); - -// Implementation notes: -// -// Each state has a boolean value for all of the following flags: -// -// * isLoaded: The record has a populated `data` property. When a -// record is loaded via `store.find`, `isLoaded` is false -// until the adapter sets it. When a record is created locally, -// its `isLoaded` property is always true. -// * isDirty: The record has local changes that have not yet been -// saved by the adapter. This includes records that have been -// created (but not yet saved) or deleted. -// * isSaving: The record's transaction has been committed, but -// the adapter has not yet acknowledged that the changes have -// been persisted to the backend. -// * isDeleted: The record was marked for deletion. When `isDeleted` -// is true and `isDirty` is true, the record is deleted locally -// but the deletion was not yet persisted. When `isSaving` is -// true, the change is in-flight. When both `isDirty` and -// `isSaving` are false, the change has persisted. -// * isError: The adapter reported that it was unable to save -// local changes to the backend. This may also result in the -// record having its `isValid` property become false if the -// adapter reported that server-side validations failed. -// * isNew: The record was created on the client and the adapter -// did not yet report that it was successfully saved. -// * isValid: No client-side validations have failed and the -// adapter did not report any server-side validation failures. - -// The dirty state is a abstract state whose functionality is -// shared between the `created` and `updated` states. -// -// The deleted state shares the `isDirty` flag with the -// subclasses of `DirtyState`, but with a very different -// implementation. -// -// Dirty states have three child states: -// -// `uncommitted`: the store has not yet handed off the record -// to be saved. -// `inFlight`: the store has handed off the record to be saved, -// but the adapter has not yet acknowledged success. -// `invalid`: the record has invalid information and cannot be -// send to the adapter yet. -var DirtyState = DS.State.extend({ - initialState: 'uncommitted', - - // FLAGS - isDirty: true, - - // SUBSTATES - - // When a record first becomes dirty, it is `uncommitted`. - // This means that there are local pending changes, but they - // have not yet begun to be saved, and are not invalid. - uncommitted: DS.State.extend({ - // TRANSITIONS - enter: function(manager) { - var dirtyType = get(this, 'dirtyType'), - record = get(manager, 'record'); - - record.withTransaction(function (t) { - t.recordBecameDirty(dirtyType, record); - }); - }, - - // EVENTS - willSetProperty: willSetProperty, - didSetProperty: didSetProperty, - - becomeDirty: Ember.K, - - willCommit: function(manager) { - manager.transitionTo('inFlight'); - }, - - becameClean: function(manager) { - var record = get(manager, 'record'), - dirtyType = get(this, 'dirtyType'); - - record.withTransaction(function(t) { - t.recordBecameClean(dirtyType, record); - }); - - manager.transitionTo('loaded.materializing'); - }, - - becameInvalid: function(manager) { - var dirtyType = get(this, 'dirtyType'), - record = get(manager, 'record'); - - record.withTransaction(function (t) { - t.recordBecameInFlight(dirtyType, record); - }); - - manager.transitionTo('invalid'); - }, - - rollback: function(manager) { - get(manager, 'record').rollback(); - } - }), - - // Once a record has been handed off to the adapter to be - // saved, it is in the 'in flight' state. Changes to the - // record cannot be made during this window. - inFlight: DS.State.extend({ - // FLAGS - isSaving: true, - - // TRANSITIONS - enter: function(manager) { - var dirtyType = get(this, 'dirtyType'), - record = get(manager, 'record'); - - record.becameInFlight(); - - record.withTransaction(function (t) { - t.recordBecameInFlight(dirtyType, record); - }); - }, - - // EVENTS - didCommit: function(manager) { - var dirtyType = get(this, 'dirtyType'), - record = get(manager, 'record'); - - record.withTransaction(function(t) { - t.recordBecameClean('inflight', record); - }); - - manager.transitionTo('saved'); - manager.send('invokeLifecycleCallbacks', dirtyType); - }, - - becameInvalid: function(manager, errors) { - var record = get(manager, 'record'); - - set(record, 'errors', errors); - - manager.transitionTo('invalid'); - manager.send('invokeLifecycleCallbacks'); - }, - - becameError: function(manager) { - manager.transitionTo('error'); - manager.send('invokeLifecycleCallbacks'); - } - }), - - // A record is in the `invalid` state when its client-side - // invalidations have failed, or if the adapter has indicated - // the the record failed server-side invalidations. - invalid: DS.State.extend({ - // FLAGS - isValid: false, - - exit: function(manager) { - var record = get(manager, 'record'); - - record.withTransaction(function (t) { - t.recordBecameClean('inflight', record); - }); - }, - - // EVENTS - deleteRecord: function(manager) { - manager.transitionTo('deleted'); - get(manager, 'record').clearRelationships(); - }, - - willSetProperty: willSetProperty, - - didSetProperty: function(manager, context) { - var record = get(manager, 'record'), - errors = get(record, 'errors'), - key = context.name; - - set(errors, key, null); - - if (!hasDefinedProperties(errors)) { - manager.send('becameValid'); - } - - didSetProperty(manager, context); - }, - - becomeDirty: Ember.K, - - rollback: function(manager) { - manager.send('becameValid'); - manager.send('rollback'); - }, - - becameValid: function(manager) { - manager.transitionTo('uncommitted'); - }, - - invokeLifecycleCallbacks: function(manager) { - var record = get(manager, 'record'); - record.trigger('becameInvalid', record); - } - }) -}); - -// The created and updated states are created outside the state -// chart so we can reopen their substates and add mixins as -// necessary. - -var createdState = DirtyState.create({ - dirtyType: 'created', - - // FLAGS - isNew: true -}); - -var updatedState = DirtyState.create({ - dirtyType: 'updated' -}); - -createdState.states.uncommitted.reopen({ - deleteRecord: function(manager) { - var record = get(manager, 'record'); - - record.withTransaction(function(t) { - t.recordIsMoving('created', record); - }); - - record.clearRelationships(); - manager.transitionTo('deleted.saved'); - } -}); - -createdState.states.uncommitted.reopen({ - rollback: function(manager) { - this._super(manager); - manager.transitionTo('deleted.saved'); - } -}); - -updatedState.states.uncommitted.reopen({ - deleteRecord: function(manager) { - var record = get(manager, 'record'); - - record.withTransaction(function(t) { - t.recordIsMoving('updated', record); - }); - - manager.transitionTo('deleted'); - get(manager, 'record').clearRelationships(); - } -}); - -var states = { - rootState: Ember.State.create({ - // FLAGS - isLoaded: false, - isReloading: false, - isDirty: false, - isSaving: false, - isDeleted: false, - isError: false, - isNew: false, - isValid: true, - - // SUBSTATES - - // A record begins its lifecycle in the `empty` state. - // If its data will come from the adapter, it will - // transition into the `loading` state. Otherwise, if - // the record is being created on the client, it will - // transition into the `created` state. - empty: DS.State.create({ - // EVENTS - loadingData: function(manager) { - manager.transitionTo('loading'); - }, - - loadedData: function(manager) { - manager.transitionTo('loaded.created'); - } - }), - - // A record enters this state when the store askes - // the adapter for its data. It remains in this state - // until the adapter provides the requested data. - // - // Usually, this process is asynchronous, using an - // XHR to retrieve the data. - loading: DS.State.create({ - // EVENTS - loadedData: didChangeData, - - materializingData: function(manager) { - manager.transitionTo('loaded.materializing.firstTime'); - } - }), - - // A record enters this state when its data is populated. - // Most of a record's lifecycle is spent inside substates - // of the `loaded` state. - loaded: DS.State.create({ - initialState: 'saved', - - // FLAGS - isLoaded: true, - - // SUBSTATES - - materializing: DS.State.create({ - // FLAGS - isLoaded: false, - - // EVENTS - willSetProperty: Ember.K, - didSetProperty: Ember.K, - - didChangeData: didChangeData, - - finishedMaterializing: function(manager) { - manager.transitionTo('loaded.saved'); - }, - - // SUBSTATES - firstTime: DS.State.create({ - exit: function(manager) { - var record = get(manager, 'record'); - - once(function() { - record.trigger('didLoad'); - }); - } - }) - }), - - reloading: DS.State.create({ - // FLAGS - isReloading: true, - - // TRANSITIONS - enter: function(manager) { - var record = get(manager, 'record'), - store = get(record, 'store'); - - store.reloadRecord(record); - }, - - exit: function(manager) { - var record = get(manager, 'record'); - - once(record, 'trigger', 'didReload'); - }, - - // EVENTS - loadedData: didChangeData, - - materializingData: function(manager) { - manager.transitionTo('loaded.materializing'); - } - }), - - // If there are no local changes to a record, it remains - // in the `saved` state. - saved: DS.State.create({ - // EVENTS - willSetProperty: willSetProperty, - didSetProperty: didSetProperty, - - didChangeData: didChangeData, - loadedData: didChangeData, - - reloadRecord: function(manager) { - manager.transitionTo('loaded.reloading'); - }, - - materializingData: function(manager) { - manager.transitionTo('loaded.materializing'); - }, - - becomeDirty: function(manager) { - manager.transitionTo('updated'); - }, - - deleteRecord: function(manager) { - manager.transitionTo('deleted'); - get(manager, 'record').clearRelationships(); - }, - - unloadRecord: function(manager) { - manager.transitionTo('deleted.saved'); - get(manager, 'record').clearRelationships(); - }, - - invokeLifecycleCallbacks: function(manager, dirtyType) { - var record = get(manager, 'record'); - if (dirtyType === 'created') { - record.trigger('didCreate', record); - } else { - record.trigger('didUpdate', record); - } - } - }), - - // A record is in this state after it has been locally - // created but before the adapter has indicated that - // it has been saved. - created: createdState, - - // A record is in this state if it has already been - // saved to the server, but there are new local changes - // that have not yet been saved. - updated: updatedState - }), - - // A record is in this state if it was deleted from the store. - deleted: DS.State.create({ - initialState: 'uncommitted', - dirtyType: 'deleted', - - // FLAGS - isDeleted: true, - isLoaded: true, - isDirty: true, - - // TRANSITIONS - setup: function(manager) { - var record = get(manager, 'record'), - store = get(record, 'store'); - - store.removeFromRecordArrays(record); - }, - - // SUBSTATES - - // When a record is deleted, it enters the `start` - // state. It will exit this state when the record's - // transaction starts to commit. - uncommitted: DS.State.create({ - // TRANSITIONS - enter: function(manager) { - var record = get(manager, 'record'); - - record.withTransaction(function(t) { - t.recordBecameDirty('deleted', record); - }); - }, - - // EVENTS - willCommit: function(manager) { - manager.transitionTo('inFlight'); - }, - - rollback: function(manager) { - get(manager, 'record').rollback(); - }, - - becomeDirty: Ember.K, - - becameClean: function(manager) { - var record = get(manager, 'record'); - - record.withTransaction(function(t) { - t.recordBecameClean('deleted', record); - }); - - manager.transitionTo('loaded.materializing'); - } - }), - - // After a record's transaction is committing, but - // before the adapter indicates that the deletion - // has saved to the server, a record is in the - // `inFlight` substate of `deleted`. - inFlight: DS.State.create({ - // FLAGS - isSaving: true, - - // TRANSITIONS - enter: function(manager) { - var record = get(manager, 'record'); - - record.becameInFlight(); - - record.withTransaction(function (t) { - t.recordBecameInFlight('deleted', record); - }); - }, - - // EVENTS - didCommit: function(manager) { - var record = get(manager, 'record'); - - record.withTransaction(function(t) { - t.recordBecameClean('inflight', record); - }); - - manager.transitionTo('saved'); - - manager.send('invokeLifecycleCallbacks'); - } - }), - - // Once the adapter indicates that the deletion has - // been saved, the record enters the `saved` substate - // of `deleted`. - saved: DS.State.create({ - // FLAGS - isDirty: false, - - setup: function(manager) { - var record = get(manager, 'record'), - store = get(record, 'store'); - - store.dematerializeRecord(record); - }, - - invokeLifecycleCallbacks: function(manager) { - var record = get(manager, 'record'); - record.trigger('didDelete', record); - } - }) - }), - - // If the adapter indicates that there was an unknown - // error saving a record, the record enters the `error` - // state. - error: DS.State.create({ - isError: true, - - // EVENTS - - invokeLifecycleCallbacks: function(manager) { - var record = get(manager, 'record'); - record.trigger('becameError', record); - } - }) - }) -}; - -DS.StateManager = Ember.StateManager.extend({ - record: null, - initialState: 'rootState', - states: states, - unhandledEvent: function(manager, originalEvent) { - var record = manager.get('record'), - contexts = [].slice.call(arguments, 2), - errorMessage; - errorMessage = "Attempted to handle event `" + originalEvent + "` "; - errorMessage += "on " + record.toString() + " while in state "; - errorMessage += get(manager, 'currentState.path') + ". Called with "; - errorMessage += arrayMap.call(contexts, function(context){ - return Ember.inspect(context); - }).join(', '); - throw new Ember.Error(errorMessage); - } -}); - -})(); - - - -(function() { -var LoadPromise = DS.LoadPromise; // system/mixins/load_promise - -var get = Ember.get, set = Ember.set, map = Ember.EnumerableUtils.map; - -var retrieveFromCurrentState = Ember.computed(function(key, value) { - return get(get(this, 'stateManager.currentState'), key); -}).property('stateManager.currentState').readOnly(); - -DS.Model = Ember.Object.extend(Ember.Evented, LoadPromise, { - isLoaded: retrieveFromCurrentState, - isReloading: retrieveFromCurrentState, - isDirty: retrieveFromCurrentState, - isSaving: retrieveFromCurrentState, - isDeleted: retrieveFromCurrentState, - isError: retrieveFromCurrentState, - isNew: retrieveFromCurrentState, - isValid: retrieveFromCurrentState, - - clientId: null, - id: null, - transaction: null, - stateManager: null, - errors: null, - - /** - Create a JSON representation of the record, using the serialization - strategy of the store's adapter. - - Available options: - - * `includeId`: `true` if the record's ID should be included in the - JSON representation. - - @param {Object} options - @returns {Object} an object whose values are primitive JSON values only - */ - serialize: function(options) { - var store = get(this, 'store'); - return store.serialize(this, options); - }, - - toJSON: function() { - var serializer = DS.JSONSerializer.create(); - return serializer.serialize(this); - }, - - didLoad: Ember.K, - didReload: Ember.K, - didUpdate: Ember.K, - didCreate: Ember.K, - didDelete: Ember.K, - becameInvalid: Ember.K, - becameError: Ember.K, - - data: Ember.computed(function() { - if (!this._data) { - this.materializeData(); - } - - return this._data; - }).property(), - - materializeData: function() { - this.send('materializingData'); - - get(this, 'store').materializeData(this); - - this.suspendRelationshipObservers(function() { - this.notifyPropertyChange('data'); - }); - }, - - _data: null, - - init: function() { - this._super(); - - var stateManager = DS.StateManager.create({ record: this }); - set(this, 'stateManager', stateManager); - - this._setup(); - - stateManager.goToState('empty'); - }, - - _setup: function() { - this._relationshipChanges = {}; - this._changesToSync = {}; - }, - - send: function(name, context) { - return get(this, 'stateManager').send(name, context); - }, - - withTransaction: function(fn) { - var transaction = get(this, 'transaction'); - if (transaction) { fn(transaction); } - }, - - loadingData: function() { - this.send('loadingData'); - }, - - loadedData: function() { - this.send('loadedData'); - }, - - didChangeData: function() { - this.send('didChangeData'); - }, - - setProperty: function(key, value, oldValue) { - this.send('setProperty', { key: key, value: value, oldValue: oldValue }); - }, - - /** - Reload the record from the adapter. - - This will only work if the record has already finished loading - and has not yet been modified (`isLoaded` but not `isDirty`, - or `isSaving`). - */ - reload: function() { - this.send('reloadRecord'); - }, - - deleteRecord: function() { - this.send('deleteRecord'); - }, - - unloadRecord: function() { - Ember.assert("You can only unload a loaded, non-dirty record.", !get(this, 'isDirty')); - - this.send('unloadRecord'); - }, - - clearRelationships: function() { - this.eachRelationship(function(name, relationship) { - if (relationship.kind === 'belongsTo') { - set(this, name, null); - } else if (relationship.kind === 'hasMany') { - get(this, name).clear(); - } - }, this); - }, - - updateRecordArrays: function() { - var store = get(this, 'store'); - if (store) { - store.dataWasUpdated(this.constructor, get(this, '_reference'), this); - } - }, - - /** - If the adapter did not return a hash in response to a commit, - merge the changed attributes and relationships into the existing - saved data. - */ - adapterDidCommit: function() { - var attributes = get(this, 'data').attributes; - - get(this.constructor, 'attributes').forEach(function(name, meta) { - attributes[name] = get(this, name); - }, this); - - this.send('didCommit'); - this.updateRecordArraysLater(); - }, - - adapterDidDirty: function() { - this.send('becomeDirty'); - this.updateRecordArraysLater(); - }, - - dataDidChange: Ember.observer(function() { - var relationships = get(this.constructor, 'relationshipsByName'); - - this.updateRecordArraysLater(); - - relationships.forEach(function(name, relationship) { - if (relationship.kind === 'hasMany') { - this.hasManyDidChange(relationship.key); - } - }, this); - - this.send('finishedMaterializing'); - }, 'data'), - - hasManyDidChange: function(key) { - var cachedValue = this.cacheFor(key); - - if (cachedValue) { - var type = get(this.constructor, 'relationshipsByName').get(key).type; - var store = get(this, 'store'); - var ids = this._data.hasMany[key] || []; - - var references = map(ids, function(id) { - // if it was already a reference, return the reference - if (typeof id === 'object') { return id; } - return store.referenceForId(type, id); - }); - - set(cachedValue, 'content', Ember.A(references)); - } - }, - - updateRecordArraysLater: function() { - Ember.run.once(this, this.updateRecordArrays); - }, - - setupData: function(prematerialized) { - this._data = { - attributes: {}, - belongsTo: {}, - hasMany: {}, - id: null - }; - }, - - materializeId: function(id) { - set(this, 'id', id); - }, - - materializeAttributes: function(attributes) { - Ember.assert("Must pass a hash of attributes to materializeAttributes", !!attributes); - this._data.attributes = attributes; - }, - - materializeAttribute: function(name, value) { - this._data.attributes[name] = value; - }, - - materializeHasMany: function(name, ids) { - this._data.hasMany[name] = ids; - }, - - materializeBelongsTo: function(name, id) { - this._data.belongsTo[name] = id; - }, - - rollback: function() { - this._setup(); - this.send('becameClean'); - - this.suspendRelationshipObservers(function() { - this.notifyPropertyChange('data'); - }); - }, - - toStringExtension: function() { - return get(this, 'id'); - }, - - /** - @private - - The goal of this method is to temporarily disable specific observers - that take action in response to application changes. - - This allows the system to make changes (such as materialization and - rollback) that should not trigger secondary behavior (such as setting an - inverse relationship or marking records as dirty). - - The specific implementation will likely change as Ember proper provides - better infrastructure for suspending groups of observers, and if Array - observation becomes more unified with regular observers. - */ - suspendRelationshipObservers: function(callback, binding) { - var observers = get(this.constructor, 'relationshipNames').belongsTo; - var self = this; - - try { - this._suspendedRelationships = true; - Ember._suspendObservers(self, observers, null, 'belongsToDidChange', function() { - Ember._suspendBeforeObservers(self, observers, null, 'belongsToWillChange', function() { - callback.call(binding || self); - }); - }); - } finally { - this._suspendedRelationships = false; - } - }, - - becameInFlight: function() { - }, - - // FOR USE BY THE BASIC ADAPTER - - save: function() { - this.get('store').scheduleSave(this); - }, - - // FOR USE DURING COMMIT PROCESS - - adapterDidUpdateAttribute: function(attributeName, value) { - - // If a value is passed in, update the internal attributes and clear - // the attribute cache so it picks up the new value. Otherwise, - // collapse the current value into the internal attributes because - // the adapter has acknowledged it. - if (value !== undefined) { - get(this, 'data.attributes')[attributeName] = value; - this.notifyPropertyChange(attributeName); - } else { - value = get(this, attributeName); - get(this, 'data.attributes')[attributeName] = value; - } - - this.updateRecordArraysLater(); - }, - - _reference: Ember.computed(function() { - return get(this, 'store').referenceForClientId(get(this, 'clientId')); - }), - - adapterDidInvalidate: function(errors) { - this.send('becameInvalid', errors); - }, - - adapterDidError: function() { - this.send('becameError'); - }, - - /** - @private - - Override the default event firing from Ember.Evented to - also call methods with the given name. - */ - trigger: function(name) { - Ember.tryInvoke(this, name, [].slice.call(arguments, 1)); - this._super.apply(this, arguments); - } -}); - -// Helper function to generate store aliases. -// This returns a function that invokes the named alias -// on the default store, but injects the class as the -// first parameter. -var storeAlias = function(methodName) { - return function() { - var store = get(DS, 'defaultStore'), - args = [].slice.call(arguments); - - args.unshift(this); - Ember.assert("Your application does not have a 'Store' property defined. Attempts to call '" + methodName + "' on model classes will fail. Please provide one as with 'YourAppName.Store = DS.Store.extend()'", !!store); - return store[methodName].apply(store, args); - }; -}; - -DS.Model.reopenClass({ - isLoaded: storeAlias('recordIsLoaded'), - find: storeAlias('find'), - all: storeAlias('all'), - query: storeAlias('findQuery'), - filter: storeAlias('filter'), - - _create: DS.Model.create, - - create: function() { - throw new Ember.Error("You should not call `create` on a model. Instead, call `createRecord` with the attributes you would like to set."); - }, - - createRecord: storeAlias('createRecord') -}); - -})(); - - - -(function() { -var get = Ember.get; -DS.Model.reopenClass({ - attributes: Ember.computed(function() { - var map = Ember.Map.create(); - - this.eachComputedProperty(function(name, meta) { - if (meta.isAttribute) { - Ember.assert("You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('')` from " + this.toString(), name !== 'id'); - - meta.name = name; - map.set(name, meta); - } - }); - - return map; - }) -}); - -var AttributeChange = DS.AttributeChange = function(options) { - this.reference = options.reference; - this.store = options.store; - this.name = options.name; - this.oldValue = options.oldValue; -}; - -AttributeChange.createChange = function(options) { - return new AttributeChange(options); -}; - -AttributeChange.prototype = { - sync: function() { - this.store.recordAttributeDidChange(this.reference, this.name, this.value, this.oldValue); - - // TODO: Use this object in the commit process - this.destroy(); - }, - - destroy: function() { - delete this.store.recordForReference(this.reference)._changesToSync[this.name]; - } -}; - -DS.Model.reopen({ - eachAttribute: function(callback, binding) { - get(this.constructor, 'attributes').forEach(function(name, meta) { - callback.call(binding, name, meta); - }, binding); - }, - - attributeWillChange: Ember.beforeObserver(function(record, key) { - var reference = get(record, '_reference'), - store = get(record, 'store'); - - record.send('willSetProperty', { reference: reference, store: store, name: key }); - }), - - attributeDidChange: Ember.observer(function(record, key) { - record.send('didSetProperty', { name: key }); - }) -}); - -function getAttr(record, options, key) { - var attributes = get(record, 'data').attributes; - var value = attributes[key]; - - if (value === undefined) { - value = options.defaultValue; - } - - return value; -} - -DS.attr = function(type, options) { - options = options || {}; - - var meta = { - type: type, - isAttribute: true, - options: options - }; - - return Ember.computed(function(key, value, oldValue) { - if (arguments.length > 1) { - Ember.assert("You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('')` from " + this.constructor.toString(), key !== 'id'); - } else { - value = getAttr(this, options, key); - } - - return value; - // `data` is never set directly. However, it may be - // invalidated from the state manager's setData - // event. - }).property('data').meta(meta); -}; - - -})(); - - - -(function() { - -})(); - - - -(function() { -var get = Ember.get, set = Ember.set, - none = Ember.isNone; - -DS.belongsTo = function(type, options) { - Ember.assert("The first argument DS.belongsTo must be a model type or string, like DS.belongsTo(App.Person)", !!type && (typeof type === 'string' || DS.Model.detect(type))); - - options = options || {}; - - var meta = { type: type, isRelationship: true, options: options, kind: 'belongsTo' }; - - return Ember.computed(function(key, value) { - if (arguments.length === 2) { - return value === undefined ? null : value; - } - - var data = get(this, 'data').belongsTo, - store = get(this, 'store'), id; - - if (typeof type === 'string') { - type = get(this, type, false) || get(Ember.lookup, type); - } - - id = data[key]; - - if(!id) { - return null; - } else if (typeof id === 'object') { - return store.recordForReference(id); - } else { - return store.find(type, id); - } - }).property('data').meta(meta); -}; - -/** - These observers observe all `belongsTo` relationships on the record. See - `relationships/ext` to see how these observers get their dependencies. - -*/ - -DS.Model.reopen({ - /** @private */ - belongsToWillChange: Ember.beforeObserver(function(record, key) { - if (get(record, 'isLoaded')) { - var oldParent = get(record, key); - - var childReference = get(record, '_reference'), - store = get(record, 'store'); - if (oldParent){ - var change = DS.RelationshipChange.createChange(childReference, get(oldParent, '_reference'), store, { key: key, kind:"belongsTo", changeType: "remove" }); - change.sync(); - this._changesToSync[key] = change; - } - } - }), - - /** @private */ - belongsToDidChange: Ember.immediateObserver(function(record, key) { - if (get(record, 'isLoaded')) { - var newParent = get(record, key); - if(newParent){ - var childReference = get(record, '_reference'), - store = get(record, 'store'); - var change = DS.RelationshipChange.createChange(childReference, get(newParent, '_reference'), store, { key: key, kind:"belongsTo", changeType: "add" }); - change.sync(); - if(this._changesToSync[key]){ - DS.OneToManyChange.ensureSameTransaction([change, this._changesToSync[key]], store); - } - } - } - delete this._changesToSync[key]; - }) -}); - -})(); - - - -(function() { -var get = Ember.get, set = Ember.set; -var hasRelationship = function(type, options) { - options = options || {}; - - var meta = { type: type, isRelationship: true, options: options, kind: 'hasMany' }; - - return Ember.computed(function(key, value) { - var data = get(this, 'data').hasMany, - store = get(this, 'store'), - ids, relationship; - - if (typeof type === 'string') { - type = get(this, type, false) || get(Ember.lookup, type); - } - - ids = data[key]; - relationship = store.findMany(type, ids, this, meta); - set(relationship, 'owner', this); - set(relationship, 'name', key); - - return relationship; - }).property().meta(meta); -}; - -DS.hasMany = function(type, options) { - Ember.assert("The type passed to DS.hasMany must be defined", !!type); - return hasRelationship(type, options); -}; - -})(); - - - -(function() { -var get = Ember.get, set = Ember.set; - -/** - @private - - This file defines several extensions to the base `DS.Model` class that - add support for one-to-many relationships. -*/ - -DS.Model.reopen({ - // This Ember.js hook allows an object to be notified when a property - // is defined. - // - // In this case, we use it to be notified when an Ember Data user defines a - // belongs-to relationship. In that case, we need to set up observers for - // each one, allowing us to track relationship changes and automatically - // reflect changes in the inverse has-many array. - // - // This hook passes the class being set up, as well as the key and value - // being defined. So, for example, when the user does this: - // - // DS.Model.extend({ - // parent: DS.belongsTo(App.User) - // }); - // - // This hook would be called with "parent" as the key and the computed - // property returned by `DS.belongsTo` as the value. - didDefineProperty: function(proto, key, value) { - // Check if the value being set is a computed property. - if (value instanceof Ember.Descriptor) { - - // If it is, get the metadata for the relationship. This is - // populated by the `DS.belongsTo` helper when it is creating - // the computed property. - var meta = value.meta(); - - if (meta.isRelationship && meta.kind === 'belongsTo') { - Ember.addObserver(proto, key, null, 'belongsToDidChange'); - Ember.addBeforeObserver(proto, key, null, 'belongsToWillChange'); - } - - if (meta.isAttribute) { - Ember.addObserver(proto, key, null, 'attributeDidChange'); - Ember.addBeforeObserver(proto, key, null, 'attributeWillChange'); - } - - meta.parentType = proto.constructor; - } - } -}); - -/** - These DS.Model extensions add class methods that provide relationship - introspection abilities about relationships. - - A note about the computed properties contained here: - - **These properties are effectively sealed once called for the first time.** - To avoid repeatedly doing expensive iteration over a model's fields, these - values are computed once and then cached for the remainder of the runtime of - your application. - - If your application needs to modify a class after its initial definition - (for example, using `reopen()` to add additional attributes), make sure you - do it before using your model with the store, which uses these properties - extensively. -*/ - -DS.Model.reopenClass({ - /** - For a given relationship name, returns the model type of the relationship. - - For example, if you define a model like this: - - App.Post = DS.Model.extend({ - comments: DS.hasMany(App.Comment) - }); - - Calling `App.Post.typeForRelationship('comments')` will return `App.Comment`. - - @param {String} name the name of the relationship - @return {subclass of DS.Model} the type of the relationship, or undefined - */ - typeForRelationship: function(name) { - var relationship = get(this, 'relationshipsByName').get(name); - return relationship && relationship.type; - }, - - /** - The model's relationships as a map, keyed on the type of the - relationship. The value of each entry is an array containing a descriptor - for each relationship with that type, describing the name of the relationship - as well as the type. - - For example, given the following model definition: - - App.Blog = DS.Model.extend({ - users: DS.hasMany(App.User), - owner: DS.belongsTo(App.User), - posts: DS.hasMany(App.Post) - }); - - This computed property would return a map describing these - relationships, like this: - - var relationships = Ember.get(App.Blog, 'relationships'); - associatons.get(App.User); - //=> [ { name: 'users', kind: 'hasMany' }, - // { name: 'owner', kind: 'belongsTo' } ] - relationships.get(App.Post); - //=> [ { name: 'posts', kind: 'hasMany' } ] - - @type Ember.Map - @readOnly - */ - relationships: Ember.computed(function() { - var map = new Ember.MapWithDefault({ - defaultValue: function() { return []; } - }); - - // Loop through each computed property on the class - this.eachComputedProperty(function(name, meta) { - - // If the computed property is a relationship, add - // it to the map. - if (meta.isRelationship) { - if (typeof meta.type === 'string') { - meta.type = Ember.get(Ember.lookup, meta.type); - } - - var relationshipsForType = map.get(meta.type); - - relationshipsForType.push({ name: name, kind: meta.kind }); - } - }); - - return map; - }), - - /** - A hash containing lists of the model's relationships, grouped - by the relationship kind. For example, given a model with this - definition: - - App.Blog = DS.Model.extend({ - users: DS.hasMany(App.User), - owner: DS.belongsTo(App.User), - - posts: DS.hasMany(App.Post) - }); - - This property would contain the following: - - var relationshipNames = Ember.get(App.Blog, 'relationshipNames'); - relationshipNames.hasMany; - //=> ['users', 'posts'] - relationshipNames.belongsTo; - //=> ['owner'] - - @type Object - @readOnly - */ - relationshipNames: Ember.computed(function() { - var names = { hasMany: [], belongsTo: [] }; - - this.eachComputedProperty(function(name, meta) { - if (meta.isRelationship) { - names[meta.kind].push(name); - } - }); - - return names; - }), - - /** - An array of types directly related to a model. Each type will be - included once, regardless of the number of relationships it has with - the model. - - For example, given a model with this definition: - - App.Blog = DS.Model.extend({ - users: DS.hasMany(App.User), - owner: DS.belongsTo(App.User), - posts: DS.hasMany(App.Post) - }); - - This property would contain the following: - - var relatedTypes = Ember.get(App.Blog, 'relatedTypes'); - //=> [ App.User, App.Post ] - - @type Ember.Array - @readOnly - */ - relatedTypes: Ember.computed(function() { - var type, - types = Ember.A([]); - - // Loop through each computed property on the class, - // and create an array of the unique types involved - // in relationships - this.eachComputedProperty(function(name, meta) { - if (meta.isRelationship) { - type = meta.type; - - if (typeof type === 'string') { - type = get(this, type, false) || get(Ember.lookup, type); - } - - if (!types.contains(type)) { - types.push(type); - } - } - }); - - return types; - }), - - /** - A map whose keys are the relationships of a model and whose values are - relationship descriptors. - - For example, given a model with this - definition: - - App.Blog = DS.Model.extend({ - users: DS.hasMany(App.User), - owner: DS.belongsTo(App.User), - - posts: DS.hasMany(App.Post) - }); - - This property would contain the following: - - var relationshipsByName = Ember.get(App.Blog, 'relationshipsByName'); - relationshipsByName.get('users'); - //=> { key: 'users', kind: 'hasMany', type: App.User } - relationshipsByName.get('owner'); - //=> { key: 'owner', kind: 'belongsTo', type: App.User } - - @type Ember.Map - @readOnly - */ - relationshipsByName: Ember.computed(function() { - var map = Ember.Map.create(), type; - - this.eachComputedProperty(function(name, meta) { - if (meta.isRelationship) { - meta.key = name; - type = meta.type; - - if (typeof type === 'string') { - type = get(this, type, false) || get(Ember.lookup, type); - meta.type = type; - } - - map.set(name, meta); - } - }); - - return map; - }), - - /** - A map whose keys are the fields of the model and whose values are strings - describing the kind of the field. A model's fields are the union of all of its - attributes and relationships. - - For example: - - App.Blog = DS.Model.extend({ - users: DS.hasMany(App.User), - owner: DS.belongsTo(App.User), - - posts: DS.hasMany(App.Post), - - title: DS.attr('string') - }); - - var fields = Ember.get(App.Blog, 'fields'); - fields.forEach(function(field, kind) { - console.log(field, kind); - }); - - // prints: - // users, hasMany - // owner, belongsTo - // posts, hasMany - // title, attribute - - @type Ember.Map - @readOnly - */ - fields: Ember.computed(function() { - var map = Ember.Map.create(), type; - - this.eachComputedProperty(function(name, meta) { - if (meta.isRelationship) { - map.set(name, meta.kind); - } else if (meta.isAttribute) { - map.set(name, 'attribute'); - } - }); - - return map; - }), - - /** - Given a callback, iterates over each of the relationships in the model, - invoking the callback with the name of each relationship and its relationship - descriptor. - - @param {Function} callback the callback to invoke - @param {any} binding the value to which the callback's `this` should be bound - */ - eachRelationship: function(callback, binding) { - get(this, 'relationshipsByName').forEach(function(name, relationship) { - callback.call(binding, name, relationship); - }); - }, - - /** - Given a callback, iterates over each of the types related to a model, - invoking the callback with the related type's class. Each type will be - returned just once, regardless of how many different relationships it has - with a model. - - @param {Function} callback the callback to invoke - @param {any} binding the value to which the callback's `this` should be bound - */ - eachRelatedType: function(callback, binding) { - get(this, 'relatedTypes').forEach(function(type) { - callback.call(binding, type); - }); - } -}); - -DS.Model.reopen({ - /** - Given a callback, iterates over each of the relationships in the model, - invoking the callback with the name of each relationship and its relationship - descriptor. - - @param {Function} callback the callback to invoke - @param {any} binding the value to which the callback's `this` should be bound - */ - eachRelationship: function(callback, binding) { - this.constructor.eachRelationship(callback, binding); - } -}); - -/** - @private - - Helper method to look up the name of the inverse of a relationship. - - In a has-many relationship, there are always two sides: the `belongsTo` side - and the `hasMany` side. When one side changes, the other side should be updated - automatically. - - Given a model, the model of the inverse, and the kind of the relationship, this - helper returns the name of the relationship on the inverse. - - For example, imagine the following two associated models: - - App.Post = DS.Model.extend({ - comments: DS.hasMany('App.Comment') - }); - - App.Comment = DS.Model.extend({ - post: DS.belongsTo('App.Post') - }); - - If the `post` property of a `Comment` was modified, Ember Data would invoke - this helper like this: - - DS._inverseNameFor(App.Comment, App.Post, 'hasMany'); - //=> 'comments' - - Ember Data uses the name of the relationship returned to reflect the changed - relationship on the other side. -*/ -DS._inverseRelationshipFor = function(modelType, inverseModelType) { - var relationshipMap = get(modelType, 'relationships'), - possibleRelationships = relationshipMap.get(inverseModelType), - possible, actual, oldValue; - - if (!possibleRelationships) { return; } - if (possibleRelationships.length > 1) { return; } - return possibleRelationships[0]; -}; - -/** - @private - - Given a model and a relationship name, returns the model type of - the named relationship. - - App.Post = DS.Model.extend({ - comments: DS.hasMany('App.Comment') - }); - - DS._inverseTypeFor(App.Post, 'comments'); - //=> App.Comment - @param {DS.Model class} modelType - @param {String} relationshipName - @return {DS.Model class} -*/ -DS._inverseTypeFor = function(modelType, relationshipName) { - var relationships = get(modelType, 'relationshipsByName'), - relationship = relationships.get(relationshipName); - - if (relationship) { return relationship.type; } -}; - -})(); - - - -(function() { -var get = Ember.get, set = Ember.set; -var forEach = Ember.EnumerableUtils.forEach; - -DS.RelationshipChange = function(options) { - this.parentReference = options.parentReference; - this.childReference = options.childReference; - this.firstRecordReference = options.firstRecordReference; - this.firstRecordKind = options.firstRecordKind; - this.firstRecordName = options.firstRecordName; - this.secondRecordReference = options.secondRecordReference; - this.secondRecordKind = options.secondRecordKind; - this.secondRecordName = options.secondRecordName; - this.store = options.store; - this.committed = {}; - this.changeType = options.changeType; -}; - -DS.RelationshipChangeAdd = function(options){ - DS.RelationshipChange.call(this, options); -}; - -DS.RelationshipChangeRemove = function(options){ - DS.RelationshipChange.call(this, options); -}; - -/** @private */ -DS.RelationshipChange.create = function(options) { - return new DS.RelationshipChange(options); -}; - -/** @private */ -DS.RelationshipChangeAdd.create = function(options) { - return new DS.RelationshipChangeAdd(options); -}; - -/** @private */ -DS.RelationshipChangeRemove.create = function(options) { - return new DS.RelationshipChangeRemove(options); -}; - -DS.OneToManyChange = {}; -DS.OneToNoneChange = {}; -DS.ManyToNoneChange = {}; -DS.OneToOneChange = {}; -DS.ManyToManyChange = {}; - -DS.RelationshipChange._createChange = function(options){ - if(options.changeType === "add"){ - return DS.RelationshipChangeAdd.create(options); - } - if(options.changeType === "remove"){ - return DS.RelationshipChangeRemove.create(options); - } -}; - - -DS.RelationshipChange.determineRelationshipType = function(recordType, knownSide){ - var knownKey = knownSide.key, key, type, otherContainerType,assoc; - var knownContainerType = knownSide.kind; - var options = recordType.metaForProperty(knownKey).options; - var otherType = DS._inverseTypeFor(recordType, knownKey); - - if(options.inverse){ - key = options.inverse; - otherContainerType = get(otherType, 'relationshipsByName').get(key).kind; - } - else if(assoc = DS._inverseRelationshipFor(otherType, recordType)){ - key = assoc.name; - otherContainerType = assoc.kind; - } - if(!key){ - return knownContainerType === "belongsTo" ? "oneToNone" : "manyToNone"; - } - else{ - if(otherContainerType === "belongsTo"){ - return knownContainerType === "belongsTo" ? "oneToOne" : "manyToOne"; - } - else{ - return knownContainerType === "belongsTo" ? "oneToMany" : "manyToMany"; - } - } - -}; - -DS.RelationshipChange.createChange = function(firstRecordReference, secondRecordReference, store, options){ - // Get the type of the child based on the child's client ID - var firstRecordType = firstRecordReference.type, key, changeType; - changeType = DS.RelationshipChange.determineRelationshipType(firstRecordType, options); - if (changeType === "oneToMany"){ - return DS.OneToManyChange.createChange(firstRecordReference, secondRecordReference, store, options); - } - else if (changeType === "manyToOne"){ - return DS.OneToManyChange.createChange(secondRecordReference, firstRecordReference, store, options); - } - else if (changeType === "oneToNone"){ - return DS.OneToNoneChange.createChange(firstRecordReference, secondRecordReference, store, options); - } - else if (changeType === "manyToNone"){ - return DS.ManyToNoneChange.createChange(firstRecordReference, secondRecordReference, store, options); - } - else if (changeType === "oneToOne"){ - return DS.OneToOneChange.createChange(firstRecordReference, secondRecordReference, store, options); - } - else if (changeType === "manyToMany"){ - return DS.ManyToManyChange.createChange(firstRecordReference, secondRecordReference, store, options); - } -}; - -/** @private */ -DS.OneToNoneChange.createChange = function(childReference, parentReference, store, options) { - var key = options.key; - var change = DS.RelationshipChange._createChange({ - parentReference: parentReference, - childReference: childReference, - firstRecordReference: childReference, - store: store, - changeType: options.changeType, - firstRecordName: key, - firstRecordKind: "belongsTo" - }); - - store.addRelationshipChangeFor(childReference, key, parentReference, null, change); - - return change; -}; - -/** @private */ -DS.ManyToNoneChange.createChange = function(childReference, parentReference, store, options) { - var key = options.key; - var change = DS.RelationshipChange._createChange({ - parentReference: childReference, - childReference: parentReference, - secondRecordReference: childReference, - store: store, - changeType: options.changeType, - secondRecordName: options.key, - secondRecordKind: "hasMany" - }); - - store.addRelationshipChangeFor(childReference, key, parentReference, null, change); - return change; -}; - - -/** @private */ -DS.ManyToManyChange.createChange = function(childReference, parentReference, store, options) { - // Get the type of the child based on the child's client ID - var childType = childReference.type, key; - - // If the name of the belongsTo side of the relationship is specified, - // use that - // If the type of the parent is specified, look it up on the child's type - // definition. - key = options.key; - - var change = DS.RelationshipChange._createChange({ - parentReference: parentReference, - childReference: childReference, - firstRecordReference: childReference, - secondRecordReference: parentReference, - firstRecordKind: "hasMany", - secondRecordKind: "hasMany", - store: store, - changeType: options.changeType, - firstRecordName: key - }); - - store.addRelationshipChangeFor(childReference, key, parentReference, null, change); - - - return change; -}; - -/** @private */ -DS.OneToOneChange.createChange = function(childReference, parentReference, store, options) { - // Get the type of the child based on the child's client ID - var childType = childReference.type, key; - - // If the name of the belongsTo side of the relationship is specified, - // use that - // If the type of the parent is specified, look it up on the child's type - // definition. - if (options.parentType) { - key = inverseBelongsToName(options.parentType, childType, options.key); - //DS.OneToOneChange.maintainInvariant( options, store, childReference, key ); - } else if (options.key) { - key = options.key; - } else { - Ember.assert("You must pass either a parentType or belongsToName option to OneToManyChange.forChildAndParent", false); - } - - var change = DS.RelationshipChange._createChange({ - parentReference: parentReference, - childReference: childReference, - firstRecordReference: childReference, - secondRecordReference: parentReference, - firstRecordKind: "belongsTo", - secondRecordKind: "belongsTo", - store: store, - changeType: options.changeType, - firstRecordName: key - }); - - store.addRelationshipChangeFor(childReference, key, parentReference, null, change); - - - return change; -}; - -DS.OneToOneChange.maintainInvariant = function(options, store, childReference, key){ - if (options.changeType === "add" && store.recordIsMaterialized(childReference)) { - var child = store.recordForReference(childReference); - var oldParent = get(child, key); - if (oldParent){ - var correspondingChange = DS.OneToOneChange.createChange(childReference, oldParent.get('_reference'), store, { - parentType: options.parentType, - hasManyName: options.hasManyName, - changeType: "remove", - key: options.key - }); - store.addRelationshipChangeFor(childReference, key, options.parentReference , null, correspondingChange); - correspondingChange.sync(); - } - } -}; - -/** @private */ -DS.OneToManyChange.createChange = function(childReference, parentReference, store, options) { - // Get the type of the child based on the child's client ID - var childType = childReference.type, key; - - // If the name of the belongsTo side of the relationship is specified, - // use that - // If the type of the parent is specified, look it up on the child's type - // definition. - if (options.parentType) { - key = inverseBelongsToName(options.parentType, childType, options.key); - DS.OneToManyChange.maintainInvariant( options, store, childReference, key ); - } else if (options.key) { - key = options.key; - } else { - Ember.assert("You must pass either a parentType or belongsToName option to OneToManyChange.forChildAndParent", false); - } - - var change = DS.RelationshipChange._createChange({ - parentReference: parentReference, - childReference: childReference, - firstRecordReference: childReference, - secondRecordReference: parentReference, - firstRecordKind: "belongsTo", - secondRecordKind: "hasMany", - store: store, - changeType: options.changeType, - firstRecordName: key - }); - - store.addRelationshipChangeFor(childReference, key, parentReference, null, change); - - - return change; -}; - - -DS.OneToManyChange.maintainInvariant = function(options, store, childReference, key){ - if (options.changeType === "add" && store.recordIsMaterialized(childReference)) { - var child = store.recordForReference(childReference); - var oldParent = get(child, key); - if (oldParent){ - var correspondingChange = DS.OneToManyChange.createChange(childReference, oldParent.get('_reference'), store, { - parentType: options.parentType, - hasManyName: options.hasManyName, - changeType: "remove", - key: options.key - }); - store.addRelationshipChangeFor(childReference, key, options.parentReference , null, correspondingChange); - correspondingChange.sync(); - } - } -}; - -DS.OneToManyChange.ensureSameTransaction = function(changes, store){ - var records = Ember.A(); - forEach(changes, function(change){ - records.addObject(change.getSecondRecord()); - records.addObject(change.getFirstRecord()); - }); - var transaction = store.ensureSameTransaction(records); - forEach(changes, function(change){ - change.transaction = transaction; - }); -}; - -DS.RelationshipChange.prototype = { - - getSecondRecordName: function() { - var name = this.secondRecordName, store = this.store, parent; - - if (!name) { - parent = this.secondRecordReference; - if (!parent) { return; } - - var childType = this.firstRecordReference.type; - var inverseType = DS._inverseTypeFor(childType, this.firstRecordName); - name = inverseHasManyName(inverseType, childType, this.firstRecordName); - this.secondRecordName = name; - } - - return name; - }, - - /** - Get the name of the relationship on the belongsTo side. - - @returns {String} - */ - getFirstRecordName: function() { - var name = this.firstRecordName, store = this.store, parent, child; - - if (!name) { - parent = this.secondRecordReference; - child = this.firstRecordReference; - if (!(child && parent)) { return; } - - name = DS._inverseRelationshipFor(child.type, parent.type).name; - - this.firstRecordName = name; - } - - return name; - }, - - /** @private */ - destroy: function() { - var childReference = this.childReference, - belongsToName = this.getFirstRecordName(), - hasManyName = this.getSecondRecordName(), - store = this.store, - child, oldParent, newParent, lastParent, transaction; - - store.removeRelationshipChangeFor(childReference, belongsToName, this.parentReference, hasManyName, this.changeType); - - if (transaction = this.transaction) { - transaction.relationshipBecameClean(this); - } - }, - - /** @private */ - getByReference: function(reference) { - var store = this.store; - - // return null or undefined if the original reference was null or undefined - if (!reference) { return reference; } - - if (store.recordIsMaterialized(reference)) { - return store.recordForReference(reference); - } - }, - - getSecondRecord: function(){ - return this.getByReference(this.secondRecordReference); - }, - - /** @private */ - getFirstRecord: function() { - return this.getByReference(this.firstRecordReference); - }, - - /** - @private - - Make sure that all three parts of the relationship change are part of - the same transaction. If any of the three records is clean and in the - default transaction, and the rest are in a different transaction, move - them all into that transaction. - */ - ensureSameTransaction: function() { - var child = this.getFirstRecord(), - parentRecord = this.getSecondRecord(); - - var transaction = this.store.ensureSameTransaction([child, parentRecord]); - - this.transaction = transaction; - return transaction; - }, - - callChangeEvents: function(){ - var hasManyName = this.getSecondRecordName(), - belongsToName = this.getFirstRecordName(), - child = this.getFirstRecord(), - parentRecord = this.getSecondRecord(); - - var dirtySet = new Ember.OrderedSet(); - - // TODO: This implementation causes a race condition in key-value - // stores. The fix involves buffering changes that happen while - // a record is loading. A similar fix is required for other parts - // of ember-data, and should be done as new infrastructure, not - // a one-off hack. [tomhuda] - if (parentRecord && get(parentRecord, 'isLoaded')) { - this.store.recordHasManyDidChange(dirtySet, parentRecord, this); - } - - if (child) { - this.store.recordBelongsToDidChange(dirtySet, child, this); - } - - dirtySet.forEach(function(record) { - record.adapterDidDirty(); - }); - }, - - coalesce: function(){ - var relationshipPairs = this.store.relationshipChangePairsFor(this.firstRecordReference); - forEach(relationshipPairs, function(pair){ - var addedChange = pair["add"]; - var removedChange = pair["remove"]; - if(addedChange && removedChange) { - addedChange.destroy(); - removedChange.destroy(); - } - }); - } -}; - -DS.RelationshipChangeAdd.prototype = Ember.create(DS.RelationshipChange.create({})); -DS.RelationshipChangeRemove.prototype = Ember.create(DS.RelationshipChange.create({})); - -DS.RelationshipChangeAdd.prototype.changeType = "add"; -DS.RelationshipChangeAdd.prototype.sync = function() { - var secondRecordName = this.getSecondRecordName(), - firstRecordName = this.getFirstRecordName(), - firstRecord = this.getFirstRecord(), - secondRecord = this.getSecondRecord(); - - //Ember.assert("You specified a hasMany (" + hasManyName + ") on " + (!belongsToName && (newParent || oldParent || this.lastParent).constructor) + " but did not specify an inverse belongsTo on " + child.constructor, belongsToName); - //Ember.assert("You specified a belongsTo (" + belongsToName + ") on " + child.constructor + " but did not specify an inverse hasMany on " + (!hasManyName && (newParent || oldParent || this.lastParentRecord).constructor), hasManyName); - - var transaction = this.ensureSameTransaction(); - transaction.relationshipBecameDirty(this); - - this.callChangeEvents(); - - if (secondRecord && firstRecord) { - if(this.secondRecordKind === "belongsTo"){ - secondRecord.suspendRelationshipObservers(function(){ - set(secondRecord, secondRecordName, firstRecord); - }); - - } - else if(this.secondRecordKind === "hasMany"){ - secondRecord.suspendRelationshipObservers(function(){ - get(secondRecord, secondRecordName).addObject(firstRecord); - }); - } - } - - if (firstRecord && secondRecord && get(firstRecord, firstRecordName) !== secondRecord) { - if(this.firstRecordKind === "belongsTo"){ - firstRecord.suspendRelationshipObservers(function(){ - set(firstRecord, firstRecordName, secondRecord); - }); - } - else if(this.firstdRecordKind === "hasMany"){ - firstRecord.suspendRelationshipObservers(function(){ - get(firstRecord, firstRecordName).addObject(secondRecord); - }); - } - } - - this.coalesce(); -}; - -DS.RelationshipChangeRemove.prototype.changeType = "remove"; -DS.RelationshipChangeRemove.prototype.sync = function() { - var secondRecordName = this.getSecondRecordName(), - firstRecordName = this.getFirstRecordName(), - firstRecord = this.getFirstRecord(), - secondRecord = this.getSecondRecord(); - - //Ember.assert("You specified a hasMany (" + hasManyName + ") on " + (!belongsToName && (newParent || oldParent || this.lastParent).constructor) + " but did not specify an inverse belongsTo on " + child.constructor, belongsToName); - //Ember.assert("You specified a belongsTo (" + belongsToName + ") on " + child.constructor + " but did not specify an inverse hasMany on " + (!hasManyName && (newParent || oldParent || this.lastParentRecord).constructor), hasManyName); - - var transaction = this.ensureSameTransaction(firstRecord, secondRecord, secondRecordName, firstRecordName); - transaction.relationshipBecameDirty(this); - - this.callChangeEvents(); - - if (secondRecord && firstRecord) { - if(this.secondRecordKind === "belongsTo"){ - secondRecord.suspendRelationshipObservers(function(){ - set(secondRecord, secondRecordName, null); - }); - } - else if(this.secondRecordKind === "hasMany"){ - secondRecord.suspendRelationshipObservers(function(){ - get(secondRecord, secondRecordName).removeObject(firstRecord); - }); - } - } - - if (firstRecord && get(firstRecord, firstRecordName)) { - if(this.firstRecordKind === "belongsTo"){ - firstRecord.suspendRelationshipObservers(function(){ - set(firstRecord, firstRecordName, null); - }); - } - else if(this.firstdRecordKind === "hasMany"){ - firstRecord.suspendRelationshipObservers(function(){ - get(firstRecord, firstRecordName).removeObject(secondRecord); - }); - } - } - - this.coalesce(); -}; - -function inverseBelongsToName(parentType, childType, hasManyName) { - // Get the options passed to the parent's DS.hasMany() - var options = parentType.metaForProperty(hasManyName).options; - var belongsToName; - - if (belongsToName = options.inverse) { - return belongsToName; - } - - return DS._inverseRelationshipFor(childType, parentType).name; -} - -function inverseHasManyName(parentType, childType, belongsToName) { - var options = childType.metaForProperty(belongsToName).options; - var hasManyName; - - if (hasManyName = options.inverse) { - return hasManyName; - } - - return DS._inverseRelationshipFor(parentType, childType).name; -} - -})(); - - - -(function() { - -})(); - - - -(function() { -var set = Ember.set; - -/** - This code registers an injection for Ember.Application. - - If an Ember.js developer defines a subclass of DS.Store on their application, - this code will automatically instantiate it and make it available on the - router. - - Additionally, after an application's controllers have been injected, they will - each have the store made available to them. - - For example, imagine an Ember.js application with the following classes: - - App.Store = DS.Store.extend({ - adapter: 'App.MyCustomAdapter' - }); - - App.PostsController = Ember.ArrayController.extend({ - // ... - }); - - When the application is initialized, `App.Store` will automatically be - instantiated, and the instance of `App.PostsController` will have its `store` - property set to that instance. - - Note that this code will only be run if the `ember-application` package is - loaded. If Ember Data is being used in an environment other than a - typical application (e.g., node.js where only `ember-runtime` is available), - this code will be ignored. -*/ - -Ember.onLoad('Ember.Application', function(Application) { - if (Application.registerInjection) { - Application.registerInjection({ - name: "store", - before: "controllers", - - // If a store subclass is defined, like App.Store, - // instantiate it and inject it into the router. - injection: function(app, stateManager, property) { - if (!stateManager) { return; } - if (property === 'Store') { - set(stateManager, 'store', app[property].create()); - } - } - }); - - Application.registerInjection({ - name: "giveStoreToControllers", - after: ['store','controllers'], - - // For each controller, set its `store` property - // to the DS.Store instance we created above. - injection: function(app, stateManager, property) { - if (!stateManager) { return; } - if (/^[A-Z].*Controller$/.test(property)) { - var controllerName = property.charAt(0).toLowerCase() + property.substr(1); - var store = stateManager.get('store'); - var controller = stateManager.get(controllerName); - if(!controller) { return; } - - controller.set('store', store); - } - } - }); - } else if (Application.initializer) { - Application.initializer({ - name: "store", - - initialize: function(container, application) { - application.register('store:main', application.Store); - - // Eagerly generate the store so defaultStore is populated. - // TODO: Do this in a finisher hook - container.lookup('store:main'); - } - }); - - Application.initializer({ - name: "injectStore", - - initialize: function(container, application) { - application.inject('controller', 'store', 'store:main'); - application.inject('route', 'store', 'store:main'); - } - }); - } -}); - -})(); - - - -(function() { -var get = Ember.get, set = Ember.set, map = Ember.ArrayPolyfills.map, isNone = Ember.isNone; - -function mustImplement(name) { - return function() { - throw new Ember.Error("Your serializer " + this.toString() + " does not implement the required method " + name); - }; -} - -/** - A serializer is responsible for serializing and deserializing a group of - records. - - `DS.Serializer` is an abstract base class designed to help you build a - serializer that can read to and write from any serialized form. While most - applications will use `DS.JSONSerializer`, which reads and writes JSON, the - serializer architecture allows your adapter to transmit things like XML, - strings, or custom binary data. - - Typically, your application's `DS.Adapter` is responsible for both creating a - serializer as well as calling the appropriate methods when it needs to - materialize data or serialize a record. - - The serializer API is designed as a series of layered hooks that you can - override to customize any of the individual steps of serialization and - deserialization. - - The hooks are organized by the three responsibilities of the serializer: - - 1. Determining naming conventions - 2. Serializing records into a serialized form - 3. Deserializing records from a serialized form - - Because Ember Data lazily materializes records, the deserialization - step, and therefore the hooks you implement, are split into two phases: - - 1. Extraction, where the serialized forms for multiple records are - extracted from a single payload. The IDs of each record are also - extracted for indexing. - 2. Materialization, where a newly-created record has its attributes - and relationships initialized based on the serialized form loaded - by the adapter. - - Additionally, a serializer can convert values from their JavaScript - versions into their serialized versions via a declarative API. - - ## Naming Conventions - - One of the most common uses of the serializer is to map attribute names - from the serialized form to your `DS.Model`. For example, in your model, - you may have an attribute called `firstName`: - - ```javascript - App.Person = DS.Model.extend({ - firstName: DS.attr('string') - }); - ``` - - However, because the web API your adapter is communicating with is - legacy, it calls this attribute `FIRST_NAME`. - - You can determine the attribute name used in the serialized form - by implementing `keyForAttributeName`: - - ```javascript - keyForAttributeName: function(type, name) { - return name.underscore.toUpperCase(); - } - ``` - - If your attribute names are not predictable, you can re-map them - one-by-one using the adapter's `map` API: - - ```javascript - App.Adapter.map('App.Person', { - firstName: { key: '*API_USER_FIRST_NAME*' } - }); - ``` - - This API will also work for relationships and primary keys. For - example: - - ```javascript - App.Adapter.map('App.Person', { - primaryKey: '_id' - }); - ``` - - ## Serialization - - During the serialization process, a record or records are converted - from Ember.js objects into their serialized form. - - These methods are designed in layers, like a delicious 7-layer - cake (but with fewer layers). - - The main entry point for serialization is the `serialize` - method, which takes the record and options. - - The `serialize` method is responsible for: - - * turning the record's attributes (`DS.attr`) into - attributes on the JSON object. - * optionally adding the record's ID onto the hash - * adding relationships (`DS.hasMany` and `DS.belongsTo`) - to the JSON object. - - Depending on the backend, the serializer can choose - whether to include the `hasMany` or `belongsTo` - relationships on the JSON hash. - - For very custom serialization, you can implement your - own `serialize` method. In general, however, you will want - to override the hooks described below. - - ### Adding the ID - - The default `serialize` will optionally call your serializer's - `addId` method with the JSON hash it is creating, the - record's type, and the record's ID. The `serialize` method - will not call `addId` if the record's ID is undefined. - - Your adapter must specifically request ID inclusion by - passing `{ includeId: true }` as an option to `serialize`. - - NOTE: You may not want to include the ID when updating an - existing record, because your server will likely disallow - changing an ID after it is created, and the PUT request - itself will include the record's identification. - - By default, `addId` will: - - 1. Get the primary key name for the record by calling - the serializer's `primaryKey` with the record's type. - Unless you override the `primaryKey` method, this - will be `'id'`. - 2. Assign the record's ID to the primary key in the - JSON hash being built. - - If your backend expects a JSON object with the primary - key at the root, you can just override the `primaryKey` - method on your serializer subclass. - - Otherwise, you can override the `addId` method for - more specialized handling. - - ### Adding Attributes - - By default, the serializer's `serialize` method will call - `addAttributes` with the JSON object it is creating - and the record to serialize. - - The `addAttributes` method will then call `addAttribute` - in turn, with the JSON object, the record to serialize, - the attribute's name and its type. - - Finally, the `addAttribute` method will serialize the - attribute: - - 1. It will call `keyForAttributeName` to determine - the key to use in the JSON hash. - 2. It will get the value from the record. - 3. It will call `serializeValue` with the attribute's - value and attribute type to convert it into a - JSON-compatible value. For example, it will convert a - Date into a String. - - If your backend expects a JSON object with attributes as - keys at the root, you can just override the `serializeValue` - and `keyForAttributeName` methods in your serializer - subclass and let the base class do the heavy lifting. - - If you need something more specialized, you can probably - override `addAttribute` and let the default `addAttributes` - handle the nitty gritty. - - ### Adding Relationships - - By default, `serialize` will call your serializer's - `addRelationships` method with the JSON object that is - being built and the record being serialized. The default - implementation of this method is to loop over all of the - relationships defined on your record type and: - - * If the relationship is a `DS.hasMany` relationship, - call `addHasMany` with the JSON object, the record - and a description of the relationship. - * If the relationship is a `DS.belongsTo` relationship, - call `addBelongsTo` with the JSON object, the record - and a description of the relationship. - - The relationship description has the following keys: - - * `type`: the class of the associated information (the - first parameter to `DS.hasMany` or `DS.belongsTo`) - * `kind`: either `hasMany` or `belongsTo` - - The relationship description may get additional - information in the future if more capabilities or - relationship types are added. However, it will - remain backwards-compatible, so the mere existence - of new features should not break existing adapters. -*/ -DS.Serializer = Ember.Object.extend({ - init: function() { - this.mappings = Ember.Map.create(); - this.configurations = Ember.Map.create(); - this.globalConfigurations = {}; - }, - - extract: mustImplement('extract'), - extractMany: mustImplement('extractMany'), - - extractRecordRepresentation: function(loader, type, json, shouldSideload) { - var mapping = this.mappingForType(type); - var embeddedData, prematerialized = {}, reference; - - if (shouldSideload) { - reference = loader.sideload(type, json); - } else { - reference = loader.load(type, json); - } - - this.eachEmbeddedHasMany(type, function(name, relationship) { - var embeddedData = json[this.keyFor(relationship)]; - if (!isNone(embeddedData)) { - this.extractEmbeddedHasMany(loader, relationship, embeddedData, reference, prematerialized); - } - }, this); - - this.eachEmbeddedBelongsTo(type, function(name, relationship) { - var embeddedData = json[this.keyFor(relationship)]; - if (!isNone(embeddedData)) { - this.extractEmbeddedBelongsTo(loader, relationship, embeddedData, reference, prematerialized); - } - }, this); - - loader.prematerialize(reference, prematerialized); - - return reference; - }, - - extractEmbeddedHasMany: function(loader, relationship, array, parent, prematerialized) { - var references = map.call(array, function(item) { - if (!item) { return; } - - var reference = this.extractRecordRepresentation(loader, relationship.type, item, true); - - // If the embedded record should also be saved back when serializing the parent, - // make sure we set its parent since it will not have an ID. - var embeddedType = this.embeddedType(parent.type, relationship.key); - if (embeddedType === 'always') { - reference.parent = parent; - } - - return reference; - }, this); - - prematerialized[relationship.key] = references; - }, - - extractEmbeddedBelongsTo: function(loader, relationship, data, parent, prematerialized) { - var reference = this.extractRecordRepresentation(loader, relationship.type, data, true); - prematerialized[relationship.key] = reference; - - // If the embedded record should also be saved back when serializing the parent, - // make sure we set its parent since it will not have an ID. - var embeddedType = this.embeddedType(parent.type, relationship.key); - if (embeddedType === 'always') { - reference.parent = parent; - } - }, - - //....................... - //. SERIALIZATION HOOKS - //....................... - - /** - The main entry point for serializing a record. While you can consider this - a hook that can be overridden in your serializer, you will have to manually - handle serialization. For most cases, there are more granular hooks that you - can override. - - If overriding this method, these are the responsibilities that you will need - to implement yourself: - - * If the option hash contains `includeId`, add the record's ID to the serialized form. - By default, `serialize` calls `addId` if appropriate. - * Add the record's attributes to the serialized form. By default, `serialize` calls - `addAttributes`. - * Add the record's relationships to the serialized form. By default, `serialize` calls - `addRelationships`. - - @param {DS.Model} record the record to serialize - @param {Object} [options] a hash of options - @returns {any} the serialized form of the record - */ - serialize: function(record, options) { - options = options || {}; - - var serialized = this.createSerializedForm(), id; - - if (options.includeId) { - if (id = get(record, 'id')) { - this._addId(serialized, record.constructor, id); - } - } - - this.addAttributes(serialized, record); - this.addRelationships(serialized, record); - - return serialized; - }, - - /** - @private - - Given an attribute type and value, convert the value into the - serialized form using the transform registered for that type. - - @param {any} value the value to convert to the serialized form - @param {String} attributeType the registered type (e.g. `string` - or `boolean`) - @returns {any} the serialized form of the value - */ - serializeValue: function(value, attributeType) { - var transform = this.transforms ? this.transforms[attributeType] : null; - - Ember.assert("You tried to use an attribute type (" + attributeType + ") that has not been registered", transform); - return transform.serialize(value); - }, - - /** - A hook you can use to normalize IDs before adding them to the - serialized representation. - - Because the store coerces all IDs to strings for consistency, - this is the opportunity for the serializer to, for example, - convert numerical IDs back into number form. - - @param {String} id the id from the record - @returns {any} the serialized representation of the id - */ - serializeId: function(id) { - if (isNaN(id)) { return id; } - return +id; - }, - - /** - A hook you can use to change how attributes are added to the serialized - representation of a record. - - By default, `addAttributes` simply loops over all of the attributes of the - passed record, maps the attribute name to the key for the serialized form, - and invokes any registered transforms on the value. It then invokes the - more granular `addAttribute` with the key and transformed value. - - Since you can override `keyForAttributeName`, `addAttribute`, and register - custom tranforms, you should rarely need to override this hook. - - @param {any} data the serialized representation that is being built - @param {DS.Model} record the record to serialize - */ - addAttributes: function(data, record) { - record.eachAttribute(function(name, attribute) { - this._addAttribute(data, record, name, attribute.type); - }, this); - }, - - /** - A hook you can use to customize how the key/value pair is added to - the serialized data. - - @param {any} serialized the serialized form being built - @param {String} key the key to add to the serialized data - @param {any} value the value to add to the serialized data - */ - addAttribute: Ember.K, - - /** - A hook you can use to customize how the record's id is added to - the serialized data. - - The `addId` hook is called with: - - * the serialized representation being built - * the resolved primary key (taking configurations and the - `primaryKey` hook into consideration) - * the serialized id (after calling the `serializeId` hook) - - @param {any} data the serialized representation that is being built - @param {String} key the resolved primary key - @param {id} id the serialized id - */ - addId: Ember.K, - - /** - A hook you can use to change how relationships are added to the serialized - representation of a record. - - By default, `addAttributes` loops over all of the relationships of the - passed record, maps the relationship names to the key for the serialized form, - and then invokes the public `addBelongsTo` and `addHasMany` hooks. - - Since you can override `keyForBelongsTo`, `keyForHasMany`, `addBelongsTo`, - `addHasMany`, and register mappings, you should rarely need to override this - hook. - - @param {any} data the serialized representation that is being built - @param {DS.Model} record the record to serialize - */ - addRelationships: function(data, record) { - record.eachRelationship(function(name, relationship) { - if (relationship.kind === 'belongsTo') { - this._addBelongsTo(data, record, name, relationship); - } else if (relationship.kind === 'hasMany') { - this._addHasMany(data, record, name, relationship); - } - }, this); - }, - - /** - A hook you can use to add a `belongsTo` relationship to the - serialized representation. - - The specifics of this hook are very adapter-specific, so there - is no default implementation. You can see `DS.JSONSerializer` - for an example of an implementation of the `addBelongsTo` hook. - - The `belongsTo` relationship object has the following properties: - - * **type** a subclass of DS.Model that is the type of the - relationship. This is the first parameter to DS.belongsTo - * **options** the options passed to the call to DS.belongsTo - * **kind** always `belongsTo` - - Additional properties may be added in the future. - - @param {any} data the serialized representation that is being built - @param {DS.Model} record the record to serialize - @param {String} key the key for the serialized object - @param {Object} relationship an object representing the relationship - */ - addBelongsTo: Ember.K, - - /** - A hook you can use to add a `hasMany` relationship to the - serialized representation. - - The specifics of this hook are very adapter-specific, so there - is no default implementation. You may not need to implement this, - for example, if your backend only expects relationships on the - child of a one to many relationship. - - The `hasMany` relationship object has the following properties: - - * **type** a subclass of DS.Model that is the type of the - relationship. This is the first parameter to DS.hasMany - * **options** the options passed to the call to DS.hasMany - * **kind** always `hasMany` - - Additional properties may be added in the future. - - @param {any} data the serialized representation that is being built - @param {DS.Model} record the record to serialize - @param {String} key the key for the serialized object - @param {Object} relationship an object representing the relationship - */ - addHasMany: Ember.K, - - /** - NAMING CONVENTIONS - - The most commonly overridden APIs of the serializer are - the naming convention methods: - - * `keyForAttributeName`: converts a camelized attribute name - into a key in the adapter-provided data hash. For example, - if the model's attribute name was `firstName`, and the - server used underscored names, you would return `first_name`. - * `primaryKey`: returns the key that should be used to - extract the id from the adapter-provided data hash. It is - also used when serializing a record. - */ - - /** - A hook you can use in your serializer subclass to customize - how an unmapped attribute name is converted into a key. - - By default, this method returns the `name` parameter. - - For example, if the attribute names in your JSON are underscored, - you will want to convert them into JavaScript conventional - camelcase: - - ```javascript - App.MySerializer = DS.Serializer.extend({ - // ... - - keyForAttributeName: function(type, name) { - return name.camelize(); - } - }); - ``` - - @param {DS.Model subclass} type the type of the record with - the attribute name `name` - @param {String} name the attribute name to convert into a key - - @returns {String} the key - */ - keyForAttributeName: function(type, name) { - return name; - }, - - /** - A hook you can use in your serializer to specify a conventional - primary key. - - By default, this method will return the string `id`. - - In general, you should not override this hook to specify a special - primary key for an individual type; use `configure` instead. - - For example, if your primary key is always `__id__`: - - ```javascript - App.MySerializer = DS.Serializer.extend({ - // ... - primaryKey: function(type) { - return '__id__'; - } - }); - ``` - - In another example, if the primary key always includes the - underscored version of the type before the string `id`: - - ```javascript - App.MySerializer = DS.Serializer.extend({ - // ... - primaryKey: function(type) { - // If the type is `BlogPost`, this will return - // `blog_post_id`. - var typeString = type.toString().split(".")[1].underscore(); - return typeString + "_id"; - } - }); - ``` - - @param {DS.Model subclass} type - @returns {String} the primary key for the type - */ - primaryKey: function(type) { - return "id"; - }, - - /** - A hook you can use in your serializer subclass to customize - how an unmapped `belongsTo` relationship is converted into - a key. - - By default, this method calls `keyForAttributeName`, so if - your naming convention is uniform across attributes and - relationships, you can use the default here and override - just `keyForAttributeName` as needed. - - For example, if the `belongsTo` names in your JSON always - begin with `BT_` (e.g. `BT_posts`), you can strip out the - `BT_` prefix:" - - ```javascript - App.MySerializer = DS.Serializer.extend({ - // ... - keyForBelongsTo: function(type, name) { - return name.match(/^BT_(.*)$/)[1].camelize(); - } - }); - ``` - - @param {DS.Model subclass} type the type of the record with - the `belongsTo` relationship. - @param {String} name the relationship name to convert into a key - - @returns {String} the key - */ - keyForBelongsTo: function(type, name) { - return this.keyForAttributeName(type, name); - }, - - /** - A hook you can use in your serializer subclass to customize - how an unmapped `hasMany` relationship is converted into - a key. - - By default, this method calls `keyForAttributeName`, so if - your naming convention is uniform across attributes and - relationships, you can use the default here and override - just `keyForAttributeName` as needed. - - For example, if the `hasMany` names in your JSON always - begin with the "table name" for the current type (e.g. - `post_comments`), you can strip out the prefix:" - - ```javascript - App.MySerializer = DS.Serializer.extend({ - // ... - keyForHasMany: function(type, name) { - // if your App.BlogPost has many App.BlogComment, the key from - // the server would look like: `blog_post_blog_comments` - // - // 1. Convert the type into a string and underscore the - // second part (App.BlogPost -> blog_post) - // 2. Extract the part after `blog_post_` (`blog_comments`) - // 3. Underscore it, to become `blogComments` - var typeString = type.toString().split(".")[1].underscore(); - return name.match(new RegExp("^" + typeString + "_(.*)$"))[1].camelize(); - } - }); - ``` - - @param {DS.Model subclass} type the type of the record with - the `belongsTo` relationship. - @param {String} name the relationship name to convert into a key - - @returns {String} the key - */ - keyForHasMany: function(type, name) { - return this.keyForAttributeName(type, name); - }, - - //......................... - //. MATERIALIZATION HOOKS - //......................... - - materialize: function(record, serialized, prematerialized) { - var id; - if (Ember.isNone(get(record, 'id'))) { - if (prematerialized && prematerialized.hasOwnProperty('id')) { - id = prematerialized.id; - } else { - id = this.extractId(record.constructor, serialized); - } - record.materializeId(id); - } - - this.materializeAttributes(record, serialized, prematerialized); - this.materializeRelationships(record, serialized, prematerialized); - }, - - deserializeValue: function(value, attributeType) { - var transform = this.transforms ? this.transforms[attributeType] : null; - - Ember.assert("You tried to use a attribute type (" + attributeType + ") that has not been registered", transform); - return transform.deserialize(value); - }, - - materializeAttributes: function(record, serialized, prematerialized) { - record.eachAttribute(function(name, attribute) { - if (prematerialized && prematerialized.hasOwnProperty(name)) { - record.materializeAttribute(name, prematerialized[name]); - } else { - this.materializeAttribute(record, serialized, name, attribute.type); - } - }, this); - }, - - materializeAttribute: function(record, serialized, attributeName, attributeType) { - var value = this.extractAttribute(record.constructor, serialized, attributeName); - value = this.deserializeValue(value, attributeType); - - record.materializeAttribute(attributeName, value); - }, - - materializeRelationships: function(record, hash, prematerialized) { - record.eachRelationship(function(name, relationship) { - if (relationship.kind === 'hasMany') { - if (prematerialized && prematerialized.hasOwnProperty(name)) { - record.materializeHasMany(name, prematerialized[name]); - } else { - this.materializeHasMany(name, record, hash, relationship, prematerialized); - } - } else if (relationship.kind === 'belongsTo') { - if (prematerialized && prematerialized.hasOwnProperty(name)) { - record.materializeBelongsTo(name, prematerialized[name]); - } else { - this.materializeBelongsTo(name, record, hash, relationship, prematerialized); - } - } - }, this); - }, - - materializeHasMany: function(name, record, hash, relationship) { - var key = this._keyForHasMany(record.constructor, relationship.key); - record.materializeHasMany(name, this.extractHasMany(record.constructor, hash, key)); - }, - - materializeBelongsTo: function(name, record, hash, relationship) { - var key = this._keyForBelongsTo(record.constructor, relationship.key); - record.materializeBelongsTo(name, this.extractBelongsTo(record.constructor, hash, key)); - }, - - _extractEmbeddedRelationship: function(type, hash, name, relationshipType) { - var key = this['_keyFor' + relationshipType](type, name); - - if (this.embeddedType(type, name)) { - return this['extractEmbedded' + relationshipType](type, hash, key); - } - }, - - _extractEmbeddedBelongsTo: function(type, hash, name) { - return this._extractEmbeddedRelationship(type, hash, name, 'BelongsTo'); - }, - - _extractEmbeddedHasMany: function(type, hash, name) { - return this._extractEmbeddedRelationship(type, hash, name, 'HasMany'); - }, - - /** - @private - - This method is called to get the primary key for a given - type. - - If a primary key configuration exists for this type, this - method will return the configured value. Otherwise, it will - call the public `primaryKey` hook. - - @param {DS.Model subclass} type - @returns {String} the primary key for the type - */ - _primaryKey: function(type) { - var config = this.configurationForType(type), - primaryKey = config && config.primaryKey; - - if (primaryKey) { - return primaryKey; - } else { - return this.primaryKey(type); - } - }, - - /** - @private - - This method looks up the key for the attribute name and transforms the - attribute's value using registered transforms. - - Specifically: - - 1. Look up the key for the attribute name. If available, this will use - any registered mappings. Otherwise, it will invoke the public - `keyForAttributeName` hook. - 2. Get the value from the record using the `attributeName`. - 3. Transform the value using registered transforms for the `attributeType`. - 4. Invoke the public `addAttribute` hook with the hash, key, and - transformed value. - - @param {any} data the serialized representation being built - @param {DS.Model} record the record to serialize - @param {String} attributeName the name of the attribute on the record - @param {String} attributeType the type of the attribute (e.g. `string` - or `boolean`) - */ - _addAttribute: function(data, record, attributeName, attributeType) { - var key = this._keyForAttributeName(record.constructor, attributeName); - var value = get(record, attributeName); - - this.addAttribute(data, key, this.serializeValue(value, attributeType)); - }, - - /** - @private - - This method looks up the primary key for the `type` and invokes - `serializeId` on the `id`. - - It then invokes the public `addId` hook with the primary key and - the serialized id. - - @param {any} data the serialized representation that is being built - @param {Ember.Model subclass} type - @param {any} id the materialized id from the record - */ - _addId: function(hash, type, id) { - var primaryKey = this._primaryKey(type); - - this.addId(hash, primaryKey, this.serializeId(id)); - }, - - /** - @private - - This method is called to get a key used in the data from - an attribute name. It first checks for any mappings before - calling the public hook `keyForAttributeName`. - - @param {DS.Model subclass} type the type of the record with - the attribute name `name` - @param {String} name the attribute name to convert into a key - - @returns {String} the key - */ - _keyForAttributeName: function(type, name) { - return this._keyFromMappingOrHook('keyForAttributeName', type, name); - }, - - /** - @private - - This method is called to get a key used in the data from - a belongsTo relationship. It first checks for any mappings before - calling the public hook `keyForBelongsTo`. - - @param {DS.Model subclass} type the type of the record with - the `belongsTo` relationship. - @param {String} name the relationship name to convert into a key - - @returns {String} the key - */ - _keyForBelongsTo: function(type, name) { - return this._keyFromMappingOrHook('keyForBelongsTo', type, name); - }, - - keyFor: function(description) { - var type = description.parentType, - name = description.key; - - switch (description.kind) { - case 'belongsTo': - return this._keyForBelongsTo(type, name); - case 'hasMany': - return this._keyForHasMany(type, name); - } - }, - - /** - @private - - This method is called to get a key used in the data from - a hasMany relationship. It first checks for any mappings before - calling the public hook `keyForHasMany`. - - @param {DS.Model subclass} type the type of the record with - the `hasMany` relationship. - @param {String} name the relationship name to convert into a key - - @returns {String} the key - */ - _keyForHasMany: function(type, name) { - return this._keyFromMappingOrHook('keyForHasMany', type, name); - }, - /** - @private - - This method converts the relationship name to a key for serialization, - and then invokes the public `addBelongsTo` hook. - - @param {any} data the serialized representation that is being built - @param {DS.Model} record the record to serialize - @param {String} name the relationship name - @param {Object} relationship an object representing the relationship - */ - _addBelongsTo: function(data, record, name, relationship) { - var key = this._keyForBelongsTo(record.constructor, name); - this.addBelongsTo(data, record, key, relationship); - }, - - /** - @private - - This method converts the relationship name to a key for serialization, - and then invokes the public `addHasMany` hook. - - @param {any} data the serialized representation that is being built - @param {DS.Model} record the record to serialize - @param {String} name the relationship name - @param {Object} relationship an object representing the relationship - */ - _addHasMany: function(data, record, name, relationship) { - var key = this._keyForHasMany(record.constructor, name); - this.addHasMany(data, record, key, relationship); - }, - - /** - @private - - An internal method that handles checking whether a mapping - exists for a particular attribute or relationship name before - calling the public hooks. - - If a mapping is found, and the mapping has a key defined, - use that instead of invoking the hook. - - @param {String} publicMethod the public hook to invoke if - a mapping is not found (e.g. `keyForAttributeName`) - @param {DS.Model subclass} type the type of the record with - the attribute or relationship name. - @param {String} name the attribute or relationship name to - convert into a key - */ - _keyFromMappingOrHook: function(publicMethod, type, name) { - var key = this.mappingOption(type, name, 'key'); - - if (key) { - return key; - } else { - return this[publicMethod](type, name); - } - }, - - /** - TRANSFORMS - */ - - registerTransform: function(type, transform) { - this.transforms[type] = transform; - }, - - registerEnumTransform: function(type, objects) { - var transform = { - deserialize: function(deserialized) { - return Ember.A(objects).objectAt(deserialized); - }, - serialize: function(serialized) { - return Ember.EnumerableUtils.indexOf(objects, serialized); - }, - values: objects - }; - this.registerTransform(type, transform); - }, - - /** - MAPPING CONVENIENCE - */ - - map: function(type, mappings) { - this.mappings.set(type, mappings); - }, - - configure: function(type, configuration) { - if (type && !configuration) { - Ember.merge(this.globalConfigurations, type); - return; - } - - var config = Ember.create(this.globalConfigurations); - Ember.merge(config, configuration); - - this.configurations.set(type, config); - }, - - mappingForType: function(type) { - this._reifyMappings(); - return this.mappings.get(type) || {}; - }, - - configurationForType: function(type) { - this._reifyConfigurations(); - return this.configurations.get(type) || this.globalConfigurations; - }, - - _reifyMappings: function() { - if (this._didReifyMappings) { return; } - - var mappings = this.mappings, - reifiedMappings = Ember.Map.create(); - - mappings.forEach(function(key, mapping) { - if (typeof key === 'string') { - var type = Ember.get(Ember.lookup, key); - Ember.assert("Could not find model at path " + key, type); - - reifiedMappings.set(type, mapping); - } else { - reifiedMappings.set(key, mapping); - } - }); - - this.mappings = reifiedMappings; - - this._didReifyMappings = true; - }, - - _reifyConfigurations: function() { - if (this._didReifyConfigurations) { return; } - - var configurations = this.configurations, - reifiedConfigurations = Ember.Map.create(); - - configurations.forEach(function(key, mapping) { - if (typeof key === 'string' && key !== 'plurals') { - var type = Ember.get(Ember.lookup, key); - Ember.assert("Could not find model at path " + key, type); - - reifiedConfigurations.set(type, mapping); - } else { - reifiedConfigurations.set(key, mapping); - } - }); - - this.configurations = reifiedConfigurations; - - this._didReifyConfigurations = true; - }, - - mappingOption: function(type, name, option) { - var mapping = this.mappingForType(type)[name]; - - return mapping && mapping[option]; - }, - - configOption: function(type, option) { - var config = this.configurationForType(type); - - return config[option]; - }, - - // EMBEDDED HELPERS - - embeddedType: function(type, name) { - return this.mappingOption(type, name, 'embedded'); - }, - - eachEmbeddedRecord: function(record, callback, binding) { - this.eachEmbeddedBelongsToRecord(record, callback, binding); - this.eachEmbeddedHasManyRecord(record, callback, binding); - }, - - eachEmbeddedBelongsToRecord: function(record, callback, binding) { - var type = record.constructor; - - this.eachEmbeddedBelongsTo(record.constructor, function(name, relationship, embeddedType) { - var embeddedRecord = get(record, name); - if (embeddedRecord) { callback.call(binding, embeddedRecord, embeddedType); } - }); - }, - - eachEmbeddedHasManyRecord: function(record, callback, binding) { - var type = record.constructor; - - this.eachEmbeddedHasMany(record.constructor, function(name, relationship, embeddedType) { - var array = get(record, name); - for (var i=0, l=get(array, 'length'); i types) before sideloading. - // We can't do this conversion immediately here, because `configure` - // may be called before certain types have been defined. - this.sideloadMapping.normalized = false; - - delete configuration.sideloadAs; - } - - this._super.apply(this, arguments); - }, - - addId: function(data, key, id) { - data[key] = id; - }, - - /** - A hook you can use to customize how the key/value pair is added to - the serialized data. - - @param {any} hash the JSON hash being built - @param {String} key the key to add to the serialized data - @param {any} value the value to add to the serialized data - */ - addAttribute: function(hash, key, value) { - hash[key] = value; - }, - - /** - @private - - Creates an empty hash that will be filled in by the hooks called from the - `serialize()` method. - - @return {Object} - */ - createSerializedForm: function() { - return {}; - }, - - extractAttribute: function(type, hash, attributeName) { - var key = this._keyForAttributeName(type, attributeName); - return hash[key]; - }, - - extractId: function(type, hash) { - var primaryKey = this._primaryKey(type); - - if (hash.hasOwnProperty(primaryKey)) { - // Ensure that we coerce IDs to strings so that record - // IDs remain consistent between application runs; especially - // if the ID is serialized and later deserialized from the URL, - // when type information will have been lost. - return hash[primaryKey]+''; - } else { - return null; - } - }, - - extractHasMany: function(type, hash, key) { - return hash[key]; - }, - - extractBelongsTo: function(type, hash, key) { - return hash[key]; - }, - - addBelongsTo: function(hash, record, key, relationship) { - var type = record.constructor, - name = relationship.key, - value = null, - embeddedChild; - - if (this.embeddedType(type, name)) { - if (embeddedChild = get(record, name)) { - value = this.serialize(embeddedChild, { includeId: true }); - } - - hash[key] = value; - } else { - var id = get(record, relationship.key+'.id'); - if (!Ember.isNone(id)) { hash[key] = id; } - } - }, - - /** - Adds a has-many relationship to the JSON hash being built. - - The default REST semantics are to only add a has-many relationship if it - is embedded. If the relationship was initially loaded by ID, we assume that - that was done as a performance optimization, and that changes to the - has-many should be saved as foreign key changes on the child's belongs-to - relationship. - - @param {Object} hash the JSON being built - @param {DS.Model} record the record being serialized - @param {String} key the JSON key into which the serialized relationship - should be saved - @param {Object} relationship metadata about the relationship being serialized - */ - addHasMany: function(hash, record, key, relationship) { - var type = record.constructor, - name = relationship.key, - serializedHasMany = [], - manyArray, embeddedType; - - // If the has-many is not embedded, there is nothing to do. - embeddedType = this.embeddedType(type, name); - if (embeddedType !== 'always') { return; } - - // Get the DS.ManyArray for the relationship off the record - manyArray = get(record, name); - - // Build up the array of serialized records - manyArray.forEach(function (record) { - serializedHasMany.push(this.serialize(record, { includeId: true })); - }, this); - - // Set the appropriate property of the serialized JSON to the - // array of serialized embedded records - hash[key] = serializedHasMany; - }, - - // EXTRACTION - - extract: function(loader, json, type, record) { - var root = this.rootForType(type); - - this.sideload(loader, type, json, root); - this.extractMeta(loader, type, json); - - if (json[root]) { - if (record) { loader.updateId(record, json[root]); } - this.extractRecordRepresentation(loader, type, json[root]); - } - }, - - extractMany: function(loader, json, type, records) { - var root = this.rootForType(type); - root = this.pluralize(root); - - this.sideload(loader, type, json, root); - this.extractMeta(loader, type, json); - - if (json[root]) { - var objects = json[root], references = []; - if (records) { records = records.toArray(); } - - for (var i = 0; i < objects.length; i++) { - if (records) { loader.updateId(records[i], objects[i]); } - var reference = this.extractRecordRepresentation(loader, type, objects[i]); - references.push(reference); - } - - loader.populateArray(references); - } - }, - - extractMeta: function(loader, type, json) { - var meta = json[this.configOption(type, 'meta')], since; - if (!meta) { return; } - - if (since = meta[this.configOption(type, 'since')]) { - loader.sinceForType(type, since); - } - }, - - /** - @private - - Iterates over the `json` payload and attempts to load any data - included alongside `root`. - - The keys expected for sideloaded data are based upon the types related - to the root model. Recursion is used to ensure that types related to - related types can be loaded as well. Any custom keys specified by - `sideloadAs` mappings will also be respected. - - @param {DS.Store subclass} loader - @param {DS.Model subclass} type - @param {Object} json - @param {String} root - */ - sideload: function(loader, type, json, root) { - var sideloadedType; - - this.normalizeSideloadMappings(); - this.configureSideloadMappingForType(type); - - for (var prop in json) { - if (!json.hasOwnProperty(prop) || - prop === root || - prop === this.configOption(type, 'meta')) { - continue; - } - - sideloadedType = this.sideloadMapping.get(prop); - Ember.assert("Your server returned a hash with the key " + prop + - " but you have no mapping for it", - !!sideloadedType); - - this.loadValue(loader, sideloadedType, json[prop]); - } - }, - - /** - @private - - Iterates over all the `sideloadAs` mappings and converts any that are - strings to their equivalent types. - - This is an optimization used to avoid performing lookups for every - call to `sideload`. - */ - normalizeSideloadMappings: function() { - if (! this.sideloadMapping.normalized) { - this.sideloadMapping.forEach(function(key, value) { - if (typeof value === 'string') { - this.sideloadMapping.set(key, get(Ember.lookup, value)); - } - }, this); - this.sideloadMapping.normalized = true; - } - }, - - /** - @private - - Configures possible sideload mappings for the types related to a - particular model. This recursive method ensures that sideloading - works for related models as well. - - @param {DS.Model subclass} type - @param {Ember.A} configured an array of types that have already been configured - */ - configureSideloadMappingForType: function(type, configured) { - if (!configured) {configured = Ember.A([]);} - configured.pushObject(type); - - type.eachRelatedType(function(relatedType) { - if (!configured.contains(relatedType)) { - var root = this.sideloadMappingForType(relatedType); - if (!root) { - root = this.defaultSideloadRootForType(relatedType); - this.sideloadMapping.set(root, relatedType); - } - this.configureSideloadMappingForType(relatedType, configured); - } - }, this); - }, - - loadValue: function(loader, type, value) { - if (value instanceof Array) { - for (var i=0; i < value.length; i++) { - loader.sideload(type, value[i]); - } - } else { - loader.sideload(type, value); - } - }, - - // HELPERS - - // define a plurals hash in your subclass to define - // special-case pluralization - pluralize: function(name) { - var plurals = this.configurations.get('plurals'); - return (plurals && plurals[name]) || name + "s"; - }, - - // use the same plurals hash to determine - // special-case singularization - singularize: function(name) { - var plurals = this.configurations.get('plurals'); - if (plurals) { - for (var i in plurals) { - if (plurals[i] === name) { - return i; - } - } - } - if (name.lastIndexOf('s') === name.length - 1) { - return name.substring(0, name.length - 1); - } else { - return name; - } - }, - - /** - @private - - Determines the singular root name for a particular type. - - This is an underscored, lowercase version of the model name. - For example, the type `App.UserGroup` will have the root - `user_group`. - - @param {DS.Model subclass} type - @returns {String} name of the root element - */ - rootForType: function(type) { - var typeString = type.toString(); - - Ember.assert("Your model must not be anonymous. It was " + type, typeString.charAt(0) !== '('); - - // use the last part of the name as the URL - var parts = typeString.split("."); - var name = parts[parts.length - 1]; - return name.replace(/([A-Z])/g, '_$1').toLowerCase().slice(1); - }, - - /** - @private - - Determines the root name mapped to a particular sideloaded type. - - @param {DS.Model subclass} type - @returns {String} name of the root element, if any is registered - */ - sideloadMappingForType: function(type) { - this.sideloadMapping.forEach(function(key, value) { - if (type === value) { - return key; - } - }); - }, - - /** - @private - - The default root name for a particular sideloaded type. - - @param {DS.Model subclass} type - @returns {String} name of the root element - */ - defaultSideloadRootForType: function(type) { - return this.pluralize(this.rootForType(type)); - } -}); - -})(); - - - -(function() { -function loaderFor(store) { - return { - load: function(type, data, prematerialized) { - return store.load(type, data, prematerialized); - }, - - loadMany: function(type, array) { - return store.loadMany(type, array); - }, - - updateId: function(record, data) { - return store.updateId(record, data); - }, - - populateArray: Ember.K, - - sideload: function(type, data) { - return store.load(type, data); - }, - - sideloadMany: function(type, array) { - return store.loadMany(type, array); - }, - - prematerialize: function(reference, prematerialized) { - store.prematerialize(reference, prematerialized); - }, - - sinceForType: function(type, since) { - store.sinceForType(type, since); - } - }; -} - -DS.loaderFor = loaderFor; - -/** - An adapter is an object that receives requests from a store and - translates them into the appropriate action to take against your - persistence layer. The persistence layer is usually an HTTP API, but may - be anything, such as the browser's local storage. - - ### Creating an Adapter - - First, create a new subclass of `DS.Adapter`: - - App.MyAdapter = DS.Adapter.extend({ - // ...your code here - }); - - To tell your store which adapter to use, set its `adapter` property: - - App.store = DS.Store.create({ - revision: 3, - adapter: App.MyAdapter.create() - }); - - `DS.Adapter` is an abstract base class that you should override in your - application to customize it for your backend. The minimum set of methods - that you should implement is: - - * `find()` - * `createRecord()` - * `updateRecord()` - * `deleteRecord()` - - To improve the network performance of your application, you can optimize - your adapter by overriding these lower-level methods: - - * `findMany()` - * `createRecords()` - * `updateRecords()` - * `deleteRecords()` - * `commit()` -*/ - -var get = Ember.get, set = Ember.set, merge = Ember.merge; - -DS.Adapter = Ember.Object.extend(DS._Mappable, { - - init: function() { - var serializer = get(this, 'serializer'); - - if (Ember.Object.detect(serializer)) { - serializer = serializer.create(); - set(this, 'serializer', serializer); - } - - this._attributesMap = this.createInstanceMapFor('attributes'); - this._configurationsMap = this.createInstanceMapFor('configurations'); - - this._outstandingOperations = new Ember.MapWithDefault({ - defaultValue: function() { return 0; } - }); - - this._dependencies = new Ember.MapWithDefault({ - defaultValue: function() { return new Ember.OrderedSet(); } - }); - - this.registerSerializerTransforms(this.constructor, serializer, {}); - this.registerSerializerMappings(serializer); - }, - - /** - Loads a payload for a record into the store. - - This method asks the serializer to break the payload into - constituent parts, and then loads them into the store. For example, - if you have a payload that contains embedded records, they will be - extracted by the serializer and loaded into the store. - - For example: - - ```javascript - adapter.load(store, App.Person, { - id: 123, - firstName: "Yehuda", - lastName: "Katz", - occupations: [{ - id: 345, - title: "Tricycle Mechanic" - }] - }); - ``` - - This will load the payload for the `App.Person` with ID `123` and - the embedded `App.Occupation` with ID `345`. - - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {any} payload - */ - load: function(store, type, payload) { - var loader = loaderFor(store); - get(this, 'serializer').extractRecordRepresentation(loader, type, payload); - }, - - /** - Acknowledges that the adapter has finished creating a record. - - Your adapter should call this method from `createRecord` when - it has saved a new record to its persistent storage and received - an acknowledgement. - - If the persistent storage returns a new payload in response to the - creation, and you want to update the existing record with the - new information, pass the payload as the fourth parameter. - - For example, the `RESTAdapter` saves newly created records by - making an Ajax request. When the server returns, the adapter - calls didCreateRecord. If the server returns a response body, - it is passed as the payload. - - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {DS.Model} record - @param {any} payload - */ - didCreateRecord: function(store, type, record, payload) { - store.didSaveRecord(record); - - if (payload) { - var loader = DS.loaderFor(store); - - loader.load = function(type, data, prematerialized) { - store.updateId(record, data); - return store.load(type, data, prematerialized); - }; - - get(this, 'serializer').extract(loader, payload, type); - } - }, - - /** - Acknowledges that the adapter has finished creating several records. - - Your adapter should call this method from `createRecords` when it - has saved multiple created records to its persistent storage - received an acknowledgement. - - If the persistent storage returns a new payload in response to the - creation, and you want to update the existing record with the - new information, pass the payload as the fourth parameter. - - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {DS.Model} record - @param {any} payload - */ - didCreateRecords: function(store, type, records, payload) { - records.forEach(function(record) { - store.didSaveRecord(record); - }, this); - - if (payload) { - var loader = DS.loaderFor(store); - get(this, 'serializer').extractMany(loader, payload, type, records); - } - }, - - /** - @private - - Acknowledges that the adapter has finished updating or deleting a record. - - Your adapter should call this method from `updateRecord` or `deleteRecord` - when it has updated or deleted a record to its persistent storage and - received an acknowledgement. - - If the persistent storage returns a new payload in response to the - update or delete, and you want to update the existing record with the - new information, pass the payload as the fourth parameter. - - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {DS.Model} record - @param {any} payload - */ - didSaveRecord: function(store, type, record, payload) { - store.didSaveRecord(record); - - var serializer = get(this, 'serializer'), - mappings = serializer.mappingForType(type); - - serializer.eachEmbeddedRecord(record, function(embeddedRecord, embeddedType) { - if (embeddedType === 'load') { return; } - - this.didSaveRecord(store, embeddedRecord.constructor, embeddedRecord); - }, this); - - if (payload) { - var loader = DS.loaderFor(store); - serializer.extract(loader, payload, type); - } - }, - - /** - Acknowledges that the adapter has finished updating a record. - - Your adapter should call this method from `updateRecord` when it - has updated a record to its persistent storage and received an - acknowledgement. - - If the persistent storage returns a new payload in response to the - update, pass the payload as the fourth parameter. - - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {DS.Model} record - @param {any} payload - */ - didUpdateRecord: function() { - this.didSaveRecord.apply(this, arguments); - }, - - /** - Acknowledges that the adapter has finished deleting a record. - - Your adapter should call this method from `deleteRecord` when it - has deleted a record from its persistent storage and received an - acknowledgement. - - If the persistent storage returns a new payload in response to the - deletion, pass the payload as the fourth parameter. - - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {DS.Model} record - @param {any} payload - */ - didDeleteRecord: function() { - this.didSaveRecord.apply(this, arguments); - }, - - /** - Acknowledges that the adapter has finished updating or deleting - multiple records. - - Your adapter should call this method from its `updateRecords` or - `deleteRecords` when it has updated or deleted multiple records - to its persistent storage and received an acknowledgement. - - If the persistent storage returns a new payload in response to the - creation, pass the payload as the fourth parameter. - - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {DS.Model} records - @param {any} payload - */ - didSaveRecords: function(store, type, records, payload) { - records.forEach(function(record) { - store.didSaveRecord(record); - }, this); - - if (payload) { - var loader = DS.loaderFor(store); - get(this, 'serializer').extractMany(loader, payload, type); - } - }, - - /** - Acknowledges that the adapter has finished updating multiple records. - - Your adapter should call this method from its `updateRecords` when - it has updated multiple records to its persistent storage and - received an acknowledgement. - - If the persistent storage returns a new payload in response to the - update, pass the payload as the fourth parameter. - - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {DS.Model} records - @param {any} payload - */ - didUpdateRecords: function() { - this.didSaveRecords.apply(this, arguments); - }, - - /** - Acknowledges that the adapter has finished updating multiple records. - - Your adapter should call this method from its `deleteRecords` when - it has deleted multiple records to its persistent storage and - received an acknowledgement. - - If the persistent storage returns a new payload in response to the - deletion, pass the payload as the fourth parameter. - - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {DS.Model} records - @param {any} payload - */ - didDeleteRecords: function() { - this.didSaveRecords.apply(this, arguments); - }, - - /** - Loads the response to a request for a record by ID. - - Your adapter should call this method from its `find` method - with the response from the backend. - - You should pass the same ID to this method that was given - to your find method so that the store knows which record - to associate the new data with. - - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {any} payload - @param {String} id - */ - didFindRecord: function(store, type, payload, id) { - var loader = DS.loaderFor(store); - - loader.load = function(type, data, prematerialized) { - prematerialized = prematerialized || {}; - prematerialized.id = id; - - return store.load(type, data, prematerialized); - }; - - get(this, 'serializer').extract(loader, payload, type); - }, - - /** - Loads the response to a request for all records by type. - - You adapter should call this method from its `findAll` - method with the response from the backend. - - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {any} payload - */ - didFindAll: function(store, type, payload) { - var loader = DS.loaderFor(store), - serializer = get(this, 'serializer'); - - store.didUpdateAll(type); - - serializer.extractMany(loader, payload, type); - }, - - /** - Loads the response to a request for records by query. - - Your adapter should call this method from its `findQuery` - method with the response from the backend. - - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {any} payload - @param {DS.AdapterPopulatedRecordArray} recordArray - */ - didFindQuery: function(store, type, payload, recordArray) { - var loader = DS.loaderFor(store); - - loader.populateArray = function(data) { - recordArray.load(data); - }; - - get(this, 'serializer').extractMany(loader, payload, type); - }, - - /** - Loads the response to a request for many records by ID. - - You adapter should call this method from its `findMany` - method with the response from the backend. - - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {any} payload - */ - didFindMany: function(store, type, payload) { - var loader = DS.loaderFor(store); - - get(this, 'serializer').extractMany(loader, payload, type); - }, - - /** - Notifies the store that a request to the backend returned - an error. - - Your adapter should call this method to indicate that the - backend returned an error for a request. - - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {DS.Model} record - */ - didError: function(store, type, record) { - store.recordWasError(record); - }, - - dirtyRecordsForAttributeChange: function(dirtySet, record, attributeName, newValue, oldValue) { - if (newValue !== oldValue) { - // If this record is embedded, add its parent - // to the dirty set. - this.dirtyRecordsForRecordChange(dirtySet, record); - } - }, - - dirtyRecordsForRecordChange: function(dirtySet, record) { - dirtySet.add(record); - }, - - dirtyRecordsForBelongsToChange: function(dirtySet, child) { - this.dirtyRecordsForRecordChange(dirtySet, child); - }, - - dirtyRecordsForHasManyChange: function(dirtySet, parent) { - this.dirtyRecordsForRecordChange(dirtySet, parent); - }, - - /** - @private - - This method recursively climbs the superclass hierarchy and - registers any class-registered transforms on the adapter's - serializer. - - Once it registers a transform for a given type, it ignores - subsequent transforms for the same attribute type. - - @param {Class} klass the DS.Adapter subclass to extract the - transforms from - @param {DS.Serializer} serializer the serializer to register - the transforms onto - @param {Object} seen a hash of attributes already seen - */ - registerSerializerTransforms: function(klass, serializer, seen) { - var transforms = klass._registeredTransforms, superclass, prop; - - for (prop in transforms) { - if (!transforms.hasOwnProperty(prop) || prop in seen) { continue; } - seen[prop] = true; - - serializer.registerTransform(prop, transforms[prop]); - } - - if (superclass = klass.superclass) { - this.registerSerializerTransforms(superclass, serializer, seen); - } - }, - - /** - @private - - This method recursively climbs the superclass hierarchy and - registers any class-registered mappings on the adapter's - serializer. - - @param {Class} klass the DS.Adapter subclass to extract the - transforms from - @param {DS.Serializer} serializer the serializer to register the - mappings onto - */ - registerSerializerMappings: function(serializer) { - var mappings = this._attributesMap, - configurations = this._configurationsMap; - - mappings.forEach(serializer.map, serializer); - configurations.forEach(serializer.configure, serializer); - }, - - /** - The `find()` method is invoked when the store is asked for a record that - has not previously been loaded. In response to `find()` being called, you - should query your persistence layer for a record with the given ID. Once - found, you can asynchronously call the store's `load()` method to load - the record. - - Here is an example `find` implementation: - - find: function(store, type, id) { - var url = type.url; - url = url.fmt(id); - - jQuery.getJSON(url, function(data) { - // data is a hash of key/value pairs. If your server returns a - // root, simply do something like: - // store.load(type, id, data.person) - store.load(type, id, data); - }); - } - */ - find: null, - - serializer: DS.JSONSerializer, - - registerTransform: function(attributeType, transform) { - get(this, 'serializer').registerTransform(attributeType, transform); - }, - - /** - A public method that allows you to register an enumerated - type on your adapter. This is useful if you want to utilize - a text representation of an integer value. - - Eg: Say you want to utilize "low","medium","high" text strings - in your app, but you want to persist those as 0,1,2 in your backend. - You would first register the transform on your adapter instance: - - adapter.registerEnumTransform('priority', ['low', 'medium', 'high']); - - You would then refer to the 'priority' DS.attr in your model: - App.Task = DS.Model.extend({ - priority: DS.attr('priority') - }); - - And lastly, you would set/get the text representation on your model instance, - but the transformed result will be the index number of the type. - - App: myTask.get('priority') => 'low' - Server Response / Load: { myTask: {priority: 0} } - - @param {String} type of the transform - @param {Array} array of String objects to use for the enumerated values. - This is an ordered list and the index values will be used for the transform. - */ - registerEnumTransform: function(attributeType, objects) { - get(this, 'serializer').registerEnumTransform(attributeType, objects); - }, - - /** - If the globally unique IDs for your records should be generated on the client, - implement the `generateIdForRecord()` method. This method will be invoked - each time you create a new record, and the value returned from it will be - assigned to the record's `primaryKey`. - - Most traditional REST-like HTTP APIs will not use this method. Instead, the ID - of the record will be set by the server, and your adapter will update the store - with the new ID when it calls `didCreateRecord()`. Only implement this method if - you intend to generate record IDs on the client-side. - - The `generateIdForRecord()` method will be invoked with the requesting store as - the first parameter and the newly created record as the second parameter: - - generateIdForRecord: function(store, record) { - var uuid = App.generateUUIDWithStatisticallyLowOddsOfCollision(); - return uuid; - } - */ - generateIdForRecord: null, - - materialize: function(record, data, prematerialized) { - get(this, 'serializer').materialize(record, data, prematerialized); - }, - - serialize: function(record, options) { - return get(this, 'serializer').serialize(record, options); - }, - - extractId: function(type, data) { - return get(this, 'serializer').extractId(type, data); - }, - - groupByType: function(enumerable) { - var map = Ember.MapWithDefault.create({ - defaultValue: function() { return Ember.OrderedSet.create(); } - }); - - enumerable.forEach(function(item) { - map.get(item.constructor).add(item); - }); - - return map; - }, - - commit: function(store, commitDetails) { - this.save(store, commitDetails); - }, - - save: function(store, commitDetails) { - var adapter = this; - - function filter(records) { - var filteredSet = Ember.OrderedSet.create(); - - records.forEach(function(record) { - if (adapter.shouldSave(record)) { - filteredSet.add(record); - } - }); - - return filteredSet; - } - - this.groupByType(commitDetails.created).forEach(function(type, set) { - this.createRecords(store, type, filter(set)); - }, this); - - this.groupByType(commitDetails.updated).forEach(function(type, set) { - this.updateRecords(store, type, filter(set)); - }, this); - - this.groupByType(commitDetails.deleted).forEach(function(type, set) { - this.deleteRecords(store, type, filter(set)); - }, this); - }, - - shouldSave: Ember.K, - - createRecords: function(store, type, records) { - records.forEach(function(record) { - this.createRecord(store, type, record); - }, this); - }, - - updateRecords: function(store, type, records) { - records.forEach(function(record) { - this.updateRecord(store, type, record); - }, this); - }, - - deleteRecords: function(store, type, records) { - records.forEach(function(record) { - this.deleteRecord(store, type, record); - }, this); - }, - - findMany: function(store, type, ids) { - ids.forEach(function(id) { - this.find(store, type, id); - }, this); - } -}); - -DS.Adapter.reopenClass({ - registerTransform: function(attributeType, transform) { - var registeredTransforms = this._registeredTransforms || {}; - - registeredTransforms[attributeType] = transform; - - this._registeredTransforms = registeredTransforms; - }, - - map: DS._Mappable.generateMapFunctionFor('attributes', function(key, newValue, map) { - var existingValue = map.get(key); - - merge(existingValue, newValue); - }), - - configure: DS._Mappable.generateMapFunctionFor('configurations', function(key, newValue, map) { - var existingValue = map.get(key); - - // If a mapping configuration is provided, peel it off and apply it - // using the DS.Adapter.map API. - var mappings = newValue && newValue.mappings; - if (mappings) { - this.map(key, mappings); - delete newValue.mappings; - } - - merge(existingValue, newValue); - }), - - resolveMapConflict: function(oldValue, newValue, mappingsKey) { - merge(newValue, oldValue); - - return newValue; - } -}); - -})(); - - - -(function() { -var get = Ember.get, set = Ember.set; - -DS.FixtureSerializer = DS.Serializer.extend({ - deserializeValue: function(value, attributeType) { - return value; - }, - - serializeValue: function(value, attributeType) { - return value; - }, - - addId: function(data, key, id) { - data[key] = id; - }, - - addAttribute: function(hash, key, value) { - hash[key] = value; - }, - - addBelongsTo: function(hash, record, key, relationship) { - var id = get(record, relationship.key+'.id'); - if (!Ember.isNone(id)) { hash[key] = id; } - }, - - addHasMany: function(hash, record, key, relationship) { - var ids = get(record, relationship.key).map(function(item) { - return item.get('id'); - }); - - hash[relationship.key] = ids; - }, - - /** - @private - - Creates an empty hash that will be filled in by the hooks called from the - `serialize()` method. - - @return {Object} - */ - createSerializedForm: function() { - return {}; - }, - - extract: function(loader, fixture, type, record) { - if (record) { loader.updateId(record, fixture); } - this.extractRecordRepresentation(loader, type, fixture); - }, - - extractMany: function(loader, fixtures, type, records) { - var objects = fixtures, references = []; - if (records) { records = records.toArray(); } - - for (var i = 0; i < objects.length; i++) { - if (records) { loader.updateId(records[i], objects[i]); } - var reference = this.extractRecordRepresentation(loader, type, objects[i]); - references.push(reference); - } - - loader.populateArray(references); - }, - - extractId: function(type, hash) { - var primaryKey = this._primaryKey(type); - - if (hash.hasOwnProperty(primaryKey)) { - // Ensure that we coerce IDs to strings so that record - // IDs remain consistent between application runs; especially - // if the ID is serialized and later deserialized from the URL, - // when type information will have been lost. - return hash[primaryKey]+''; - } else { - return null; - } - }, - - extractAttribute: function(type, hash, attributeName) { - var key = this._keyForAttributeName(type, attributeName); - return hash[key]; - }, - - extractHasMany: function(type, hash, key) { - return hash[key]; - }, - - extractBelongsTo: function(type, hash, key) { - return hash[key]; - } -}); - -})(); - - - -(function() { -var get = Ember.get, fmt = Ember.String.fmt, - dump = Ember.get(window, 'JSON.stringify') || function(object) { return object.toString(); }; - -/** - `DS.FixtureAdapter` is an adapter that loads records from memory. - Its primarily used for development and testing. You can also use - `DS.FixtureAdapter` while working on the API but are not ready to - integrate yet. It is a fully functioning adapter. All CRUD methods - are implemented. You can also implement query logic that a remote - system would do. Its possible to do develop your entire application - with `DS.FixtureAdapter`. - -*/ -DS.FixtureAdapter = DS.Adapter.extend({ - - simulateRemoteResponse: true, - - latency: 50, - - serializer: DS.FixtureSerializer, - - /* - Implement this method in order to provide data associated with a type - */ - fixturesForType: function(type) { - if (type.FIXTURES) { - var fixtures = Ember.A(type.FIXTURES); - return fixtures.map(function(fixture){ - if(!fixture.id){ - throw new Error(fmt('the id property must be defined for fixture %@', [dump(fixture)])); - } - fixture.id = fixture.id + ''; - return fixture; - }); - } - return null; - }, - - /* - Implement this method in order to query fixtures data - */ - queryFixtures: function(fixtures, query, type) { - Ember.assert('Not implemented: You must override the DS.FixtureAdapter::queryFixtures method to support querying the fixture store.'); - }, - - updateFixtures: function(type, fixture) { - if(!type.FIXTURES) { - type.FIXTURES = []; - } - - var fixtures = type.FIXTURES; - - this.deleteLoadedFixture(type, fixture); - - fixtures.push(fixture); - }, - - /* - Implement this method in order to provide provide json for CRUD methods - */ - mockJSON: function(type, record) { - return this.serialize(record, { includeId: true }); - }, - - /* - Adapter methods - */ - generateIdForRecord: function(store, record) { - return Ember.guidFor(record); - }, - - find: function(store, type, id) { - var fixtures = this.fixturesForType(type), - fixture; - - Ember.warn("Unable to find fixtures for model type " + type.toString(), fixtures); - - if (fixtures) { - fixture = Ember.A(fixtures).findProperty('id', id); - } - - if (fixture) { - this.simulateRemoteCall(function() { - this.didFindRecord(store, type, fixture, id); - }, this); - } - }, - - findMany: function(store, type, ids) { - var fixtures = this.fixturesForType(type); - - Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures); - - if (fixtures) { - fixtures = fixtures.filter(function(item) { - return ids.indexOf(item.id) !== -1; - }); - } - - if (fixtures) { - this.simulateRemoteCall(function() { - this.didFindMany(store, type, fixtures); - }, this); - } - }, - - findAll: function(store, type) { - var fixtures = this.fixturesForType(type); - - Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures); - - this.simulateRemoteCall(function() { - this.didFindAll(store, type, fixtures); - }, this); - }, - - findQuery: function(store, type, query, array) { - var fixtures = this.fixturesForType(type); - - Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures); - - fixtures = this.queryFixtures(fixtures, query, type); - - if (fixtures) { - this.simulateRemoteCall(function() { - this.didFindQuery(store, type, fixtures, array); - }, this); - } - }, - - createRecord: function(store, type, record) { - var fixture = this.mockJSON(type, record); - - this.updateFixtures(type, fixture); - - this.simulateRemoteCall(function() { - this.didCreateRecord(store, type, record, fixture); - }, this); - }, - - updateRecord: function(store, type, record) { - var fixture = this.mockJSON(type, record); - - this.updateFixtures(type, fixture); - - this.simulateRemoteCall(function() { - this.didUpdateRecord(store, type, record, fixture); - }, this); - }, - - deleteRecord: function(store, type, record) { - var fixture = this.mockJSON(type, record); - - this.deleteLoadedFixture(type, fixture); - - this.simulateRemoteCall(function() { - this.didDeleteRecord(store, type, record); - }, this); - }, - - /* - @private - */ - deleteLoadedFixture: function(type, record) { - var id = this.extractId(type, record); - - var existingFixture = this.findExistingFixture(type, record); - - if(existingFixture) { - var index = type.FIXTURES.indexOf(existingFixture); - type.FIXTURES.splice(index, 1); - return true; - } - }, - - findExistingFixture: function(type, record) { - var fixtures = this.fixturesForType(type); - var id = this.extractId(type, record); - - return this.findFixtureById(fixtures, id); - }, - - findFixtureById: function(fixtures, id) { - var adapter = this; - - return Ember.A(fixtures).find(function(r) { - if(''+get(r, 'id') === ''+id) { - return true; - } else { - return false; - } - }); - }, - - simulateRemoteCall: function(callback, context) { - if (get(this, 'simulateRemoteResponse')) { - // Schedule with setTimeout - Ember.run.later(context, callback, get(this, 'latency')); - } else { - // Asynchronous, but at the of the runloop with zero latency - Ember.run.once(context, callback); - } - } -}); - -})(); - - - -(function() { -DS.RESTSerializer = DS.JSONSerializer.extend({ - keyForAttributeName: function(type, name) { - return Ember.String.decamelize(name); - }, - - keyForBelongsTo: function(type, name) { - var key = this.keyForAttributeName(type, name); - - if (this.embeddedType(type, name)) { - return key; - } - - return key + "_id"; - }, - - keyForHasMany: function(type, name) { - var key = this.keyForAttributeName(type, name); - - if (this.embeddedType(type, name)) { - return key; - } - - return this.singularize(key) + "_ids"; - } -}); - -})(); - - - -(function() { -/*global jQuery*/ - -var get = Ember.get, set = Ember.set, merge = Ember.merge; - -/** - The REST adapter allows your store to communicate with an HTTP server by - transmitting JSON via XHR. Most Ember.js apps that consume a JSON API - should use the REST adapter. - - This adapter is designed around the idea that the JSON exchanged with - the server should be conventional. - - ## JSON Structure - - The REST adapter expects the JSON returned from your server to follow - these conventions. - - ### Object Root - - The JSON payload should be an object that contains the record inside a - root property. For example, in response to a `GET` request for - `/posts/1`, the JSON should look like this: - - ```js - { - "post": { - title: "I'm Running to Reform the W3C's Tag", - author: "Yehuda Katz" - } - } - ``` - - ### Conventional Names - - Attribute names in your JSON payload should be the underscored versions of - the attributes in your Ember.js models. - - For example, if you have a `Person` model: - - ```js - App.Person = DS.Model.extend({ - firstName: DS.attr('string'), - lastName: DS.attr('string'), - occupation: DS.attr('string') - }); - ``` - - The JSON returned should look like this: - - ```js - { - "person": { - "first_name": "Barack", - "last_name": "Obama", - "occupation": "President" - } - } - ``` -*/ -DS.RESTAdapter = DS.Adapter.extend({ - bulkCommit: false, - since: 'since', - - serializer: DS.RESTSerializer, - - init: function() { - this._super.apply(this, arguments); - }, - - shouldSave: function(record) { - var reference = get(record, '_reference'); - - return !reference.parent; - }, - - createRecord: function(store, type, record) { - var root = this.rootForType(type); - - var data = {}; - data[root] = this.serialize(record, { includeId: true }); - - this.ajax(this.buildURL(root), "POST", { - data: data, - context: this, - success: function(json) { - Ember.run(this, function(){ - this.didCreateRecord(store, type, record, json); - }); - }, - error: function(xhr) { - this.didError(store, type, record, xhr); - } - }); - }, - - dirtyRecordsForRecordChange: function(dirtySet, record) { - this._dirtyTree(dirtySet, record); - }, - - dirtyRecordsForHasManyChange: function(dirtySet, record, relationship) { - var embeddedType = get(this, 'serializer').embeddedType(record.constructor, relationship.secondRecordName); - - if (embeddedType === 'always') { - relationship.childReference.parent = relationship.parentReference; - this._dirtyTree(dirtySet, record); - } - }, - - _dirtyTree: function(dirtySet, record) { - dirtySet.add(record); - - get(this, 'serializer').eachEmbeddedRecord(record, function(embeddedRecord, embeddedType) { - if (embeddedType !== 'always') { return; } - if (dirtySet.has(embeddedRecord)) { return; } - this._dirtyTree(dirtySet, embeddedRecord); - }, this); - - var reference = record.get('_reference'); - - if (reference.parent) { - var store = get(record, 'store'); - var parent = store.recordForReference(reference.parent); - this._dirtyTree(dirtySet, parent); - } - }, - - createRecords: function(store, type, records) { - if (get(this, 'bulkCommit') === false) { - return this._super(store, type, records); - } - - var root = this.rootForType(type), - plural = this.pluralize(root); - - var data = {}; - data[plural] = []; - records.forEach(function(record) { - data[plural].push(this.serialize(record, { includeId: true })); - }, this); - - this.ajax(this.buildURL(root), "POST", { - data: data, - context: this, - success: function(json) { - Ember.run(this, function(){ - this.didCreateRecords(store, type, records, json); - }); - } - }); - }, - - updateRecord: function(store, type, record) { - var id = get(record, 'id'); - var root = this.rootForType(type); - - var data = {}; - data[root] = this.serialize(record); - - this.ajax(this.buildURL(root, id), "PUT", { - data: data, - context: this, - success: function(json) { - Ember.run(this, function(){ - this.didSaveRecord(store, type, record, json); - }); - }, - error: function(xhr) { - this.didError(store, type, record, xhr); - } - }); - }, - - updateRecords: function(store, type, records) { - if (get(this, 'bulkCommit') === false) { - return this._super(store, type, records); - } - - var root = this.rootForType(type), - plural = this.pluralize(root); - - var data = {}; - data[plural] = []; - records.forEach(function(record) { - data[plural].push(this.serialize(record, { includeId: true })); - }, this); - - this.ajax(this.buildURL(root, "bulk"), "PUT", { - data: data, - context: this, - success: function(json) { - Ember.run(this, function(){ - this.didSaveRecords(store, type, records, json); - }); - } - }); - }, - - deleteRecord: function(store, type, record) { - var id = get(record, 'id'); - var root = this.rootForType(type); - - this.ajax(this.buildURL(root, id), "DELETE", { - context: this, - success: function(json) { - Ember.run(this, function(){ - this.didSaveRecord(store, type, record, json); - }); - } - }); - }, - - deleteRecords: function(store, type, records) { - if (get(this, 'bulkCommit') === false) { - return this._super(store, type, records); - } - - var root = this.rootForType(type), - plural = this.pluralize(root), - serializer = get(this, 'serializer'); - - var data = {}; - data[plural] = []; - records.forEach(function(record) { - data[plural].push(serializer.serializeId( get(record, 'id') )); - }); - - this.ajax(this.buildURL(root, 'bulk'), "DELETE", { - data: data, - context: this, - success: function(json) { - Ember.run(this, function(){ - this.didSaveRecords(store, type, records, json); - }); - } - }); - }, - - find: function(store, type, id) { - var root = this.rootForType(type); - - this.ajax(this.buildURL(root, id), "GET", { - success: function(json) { - Ember.run(this, function(){ - this.didFindRecord(store, type, json, id); - }); - } - }); - }, - - findAll: function(store, type, since) { - var root = this.rootForType(type); - - this.ajax(this.buildURL(root), "GET", { - data: this.sinceQuery(since), - success: function(json) { - Ember.run(this, function(){ - this.didFindAll(store, type, json); - }); - } - }); - }, - - findQuery: function(store, type, query, recordArray) { - var root = this.rootForType(type); - - this.ajax(this.buildURL(root), "GET", { - data: query, - success: function(json) { - Ember.run(this, function(){ - this.didFindQuery(store, type, json, recordArray); - }); - } - }); - }, - - findMany: function(store, type, ids, owner) { - var root = this.rootForType(type); - ids = this.serializeIds(ids); - - this.ajax(this.buildURL(root), "GET", { - data: {ids: ids}, - success: function(json) { - Ember.run(this, function(){ - this.didFindMany(store, type, json); - }); - } - }); - }, - - /** - @private - - This method serializes a list of IDs using `serializeId` - - @returns {Array} an array of serialized IDs - */ - serializeIds: function(ids) { - var serializer = get(this, 'serializer'); - - return Ember.EnumerableUtils.map(ids, function(id) { - return serializer.serializeId(id); - }); - }, - - didError: function(store, type, record, xhr) { - if (xhr.status === 422) { - var data = JSON.parse(xhr.responseText); - store.recordWasInvalid(record, data['errors']); - } else { - this._super.apply(this, arguments); - } - }, - - ajax: function(url, type, hash) { - hash.url = url; - hash.type = type; - hash.dataType = 'json'; - hash.contentType = 'application/json; charset=utf-8'; - hash.context = this; - - if (hash.data && type !== 'GET') { - hash.data = JSON.stringify(hash.data); - } - - jQuery.ajax(hash); - }, - - url: "", - - rootForType: function(type) { - var serializer = get(this, 'serializer'); - return serializer.rootForType(type); - }, - - pluralize: function(string) { - var serializer = get(this, 'serializer'); - return serializer.pluralize(string); - }, - - buildURL: function(record, suffix) { - var url = [this.url]; - - Ember.assert("Namespace URL (" + this.namespace + ") must not start with slash", !this.namespace || this.namespace.toString().charAt(0) !== "/"); - Ember.assert("Record URL (" + record + ") must not start with slash", !record || record.toString().charAt(0) !== "/"); - Ember.assert("URL suffix (" + suffix + ") must not start with slash", !suffix || suffix.toString().charAt(0) !== "/"); - - if (this.namespace !== undefined) { - url.push(this.namespace); - } - - url.push(this.pluralize(record)); - if (suffix !== undefined) { - url.push(suffix); - } - - return url.join("/"); - }, - - sinceQuery: function(since) { - var query = {}; - query[get(this, 'since')] = since; - return since ? query : null; - } -}); - - -})(); - - - -(function() { -var camelize = Ember.String.camelize, - capitalize = Ember.String.capitalize, - get = Ember.get, - map = Ember.ArrayPolyfills.map, - registeredTransforms; - -var passthruTransform = { - serialize: function(value) { return value; }, - deserialize: function(value) { return value; } -}; - -var defaultTransforms = { - string: passthruTransform, - boolean: passthruTransform, - number: passthruTransform -}; - -function camelizeKeys(json) { - var value; - - for (var prop in json) { - value = json[prop]; - delete json[prop]; - json[camelize(prop)] = value; - } -} - -function munge(json, callback) { - callback(json); -} - -function applyTransforms(json, type, transformType) { - var transforms = registeredTransforms[transformType]; - - Ember.assert("You are trying to apply the '" + transformType + "' transforms, but you didn't register any transforms with that name", transforms); - - get(type, 'attributes').forEach(function(name, attribute) { - var attributeType = attribute.type, - value = json[name]; - - var transform = transforms[attributeType] || defaultTransforms[attributeType]; - - Ember.assert("Your model specified the '" + attributeType + "' type for the '" + name + "' attribute, but no transform for that type was registered", transform); - - json[name] = transform.deserialize(value); - }); -} - -function ObjectProcessor(json, type, store) { - this.json = json; - this.type = type; - this.store = store; -} - -ObjectProcessor.prototype = { - camelizeKeys: function() { - camelizeKeys(this.json); - return this; - }, - - munge: function(callback) { - munge(this.json, callback); - return this; - }, - - applyTransforms: function(transformType) { - applyTransforms(this.json, this.type, transformType); - return this; - } -}; - -function LoadObjectProcessor() { - ObjectProcessor.apply(this, arguments); -} - -LoadObjectProcessor.prototype = Ember.create(ObjectProcessor.prototype); - -LoadObjectProcessor.prototype.load = function() { - this.store.load(this.type, {}, this.json); -}; - -function loadObjectProcessorFactory(store, type) { - return function(json) { - return new LoadObjectProcessor(json, type, store); - }; -} - -function ArrayProcessor(json, type, array, store) { - this.json = json; - this.type = type; - this.array = array; - this.store = store; -} - -ArrayProcessor.prototype = { - load: function() { - var store = this.store, - type = this.type; - - var references = this.json.map(function(object) { - return store.load(type, {}, object); - }); - - this.array.load(references); - }, - - camelizeKeys: function() { - this.json.forEach(camelizeKeys); - return this; - }, - - munge: function(callback) { - this.json.forEach(function(object) { - munge(object, callback); - }); - return this; - }, - - applyTransforms: function(transformType) { - var type = this.type; - - this.json.forEach(function(object) { - applyTransforms(object, type, transformType); - }); - - return this; - } -}; - -function arrayProcessorFactory(store, type, array) { - return function(json) { - return new ArrayProcessor(json, type, array, store); - }; -} - -var HasManyProcessor = function(json, store, record, relationship) { - this.json = json; - this.store = store; - this.record = record; - this.type = record.constructor; - this.relationship = relationship; -}; - -HasManyProcessor.prototype = Ember.create(ArrayProcessor.prototype); - -HasManyProcessor.prototype.load = function() { - var store = this.store; - var ids = map.call(this.json, function(obj) { return obj.id; }); - - store.loadMany(this.relationship.type, this.json); - store.loadHasMany(this.record, this.relationship.key, ids); -}; - -function hasManyProcessorFactory(store, record, relationship) { - return function(json) { - return new HasManyProcessor(json, store, record, relationship); - }; -} - -function CreateProcessor(record, store, type) { - this.record = record; - ObjectProcessor.call(this, record.toJSON(), type, store); -} - -CreateProcessor.prototype = Ember.create(ObjectProcessor.prototype); - -CreateProcessor.prototype.save = function() {}; - -function createProcessorFactory(store, type) { - return function(record) { - return new CreateProcessor(record, store, type); - }; -} - -DS.BasicAdapter = DS.Adapter.extend({ - find: function(store, type, id) { - var sync = type.sync; - - Ember.assert("You are trying to use the BasicAdapter to find id '" + id + "' of " + type + " but " + type + ".sync was not found", sync); - Ember.assert("The sync code on " + type + " does not implement find(), but you are trying to find id '" + id + "'.", sync.find); - - sync.find(id, loadObjectProcessorFactory(store, type)); - }, - - findQuery: function(store, type, query, recordArray) { - var sync = type.sync; - - Ember.assert("You are trying to use the BasicAdapter to query " + type + " but " + type + ".sync was not found", sync); - Ember.assert("The sync code on " + type + " does not implement query(), but you are trying to query " + type + ".", sync.query); - - sync.query(query, arrayProcessorFactory(store, type, recordArray)); - }, - - findHasMany: function(store, record, relationship, data) { - var name = capitalize(relationship.key), - sync = record.constructor.sync, - processor = hasManyProcessorFactory(store, record, relationship); - - var options = { - relationship: relationship.key, - data: data - }; - - if (sync['find'+name]) { - sync['find' + name](record, options, processor); - } else if (sync.findHasMany) { - sync.findHasMany(record, options, processor); - } else { - Ember.assert("You are trying to use the BasicAdapter to find the " + relationship.key + " has-many relationship, but " + record.constructor + ".sync did not implement findHasMany or find" + name + ".", false); - } - }, - - createRecord: function(store, type, record) { - var sync = type.sync; - - sync.createRecord(record, createProcessorFactory(store, type)); - } -}); - -DS.registerTransforms = function(kind, object) { - registeredTransforms[kind] = object; -}; - -DS.clearTransforms = function() { - registeredTransforms = {}; -}; - -DS.clearTransforms(); - -})(); - - - -(function() { - -})(); - - - -(function() { -//Copyright (C) 2011 by Living Social, Inc. - -//Permission is hereby granted, free of charge, to any person obtaining a copy of -//this software and associated documentation files (the "Software"), to deal in -//the Software without restriction, including without limitation the rights to -//use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -//of the Software, and to permit persons to whom the Software is furnished to do -//so, subject to the following conditions: - -//The above copyright notice and this permission notice shall be included in all -//copies or substantial portions of the Software. - -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -//SOFTWARE. - -})(); - diff --git a/js/libs/ember.js b/js/libs/ember.js deleted file mode 100644 index 7376897..0000000 --- a/js/libs/ember.js +++ /dev/null @@ -1,29735 +0,0 @@ -// Version: v1.0.0-rc.1-223-g5934230 -// Last commit: 5934230 (2013-03-22 22:26:47 -0700) - - -(function() { -/*global __fail__*/ - -/** -Ember Debug - -@module ember -@submodule ember-debug -*/ - -/** -@class Ember -*/ - -if ('undefined' === typeof Ember) { - Ember = {}; - - if ('undefined' !== typeof window) { - window.Em = window.Ember = Em = Ember; - } -} - -Ember.ENV = 'undefined' === typeof ENV ? {} : ENV; - -if (!('MANDATORY_SETTER' in Ember.ENV)) { - Ember.ENV.MANDATORY_SETTER = true; // default to true for debug dist -} - -/** - Define an assertion that will throw an exception if the condition is not - met. Ember build tools will remove any calls to `Ember.assert()` when - doing a production build. Example: - - ```javascript - // Test for truthiness - Ember.assert('Must pass a valid object', obj); - // Fail unconditionally - Ember.assert('This code path should never be run') - ``` - - @method assert - @param {String} desc A description of the assertion. This will become - the text of the Error thrown if the assertion fails. - @param {Boolean} test Must be truthy for the assertion to pass. If - falsy, an exception will be thrown. -*/ -Ember.assert = function(desc, test) { - if (!test) throw new Error("assertion failed: "+desc); -}; - - -/** - Display a warning with the provided message. Ember build tools will - remove any calls to `Ember.warn()` when doing a production build. - - @method warn - @param {String} message A warning to display. - @param {Boolean} test An optional boolean. If falsy, the warning - will be displayed. -*/ -Ember.warn = function(message, test) { - if (!test) { - Ember.Logger.warn("WARNING: "+message); - if ('trace' in Ember.Logger) Ember.Logger.trace(); - } -}; - -/** - Display a debug notice. Ember build tools will remove any calls to - `Ember.debug()` when doing a production build. - - ```javascript - Ember.debug("I'm a debug notice!"); - ``` - - @method debug - @param {String} message A debug message to display. -*/ -Ember.debug = function(message) { - Ember.Logger.debug("DEBUG: "+message); -}; - -/** - Display a deprecation warning with the provided message and a stack trace - (Chrome and Firefox only). Ember build tools will remove any calls to - `Ember.deprecate()` when doing a production build. - - @method deprecate - @param {String} message A description of the deprecation. - @param {Boolean} test An optional boolean. If falsy, the deprecation - will be displayed. -*/ -Ember.deprecate = function(message, test) { - if (Ember && Ember.TESTING_DEPRECATION) { return; } - - if (arguments.length === 1) { test = false; } - if (test) { return; } - - if (Ember && Ember.ENV.RAISE_ON_DEPRECATION) { throw new Error(message); } - - var error; - - // When using new Error, we can't do the arguments check for Chrome. Alternatives are welcome - try { __fail__.fail(); } catch (e) { error = e; } - - if (Ember.LOG_STACKTRACE_ON_DEPRECATION && error.stack) { - var stack, stackStr = ''; - if (error['arguments']) { - // Chrome - stack = error.stack.replace(/^\s+at\s+/gm, ''). - replace(/^([^\(]+?)([\n$])/gm, '{anonymous}($1)$2'). - replace(/^Object.\s*\(([^\)]+)\)/gm, '{anonymous}($1)').split('\n'); - stack.shift(); - } else { - // Firefox - stack = error.stack.replace(/(?:\n@:0)?\s+$/m, ''). - replace(/^\(/gm, '{anonymous}(').split('\n'); - } - - stackStr = "\n " + stack.slice(2).join("\n "); - message = message + stackStr; - } - - Ember.Logger.warn("DEPRECATION: "+message); -}; - - - -/** - Display a deprecation warning with the provided message and a stack trace - (Chrome and Firefox only) when the wrapped method is called. - - Ember build tools will not remove calls to `Ember.deprecateFunc()`, though - no warnings will be shown in production. - - @method deprecateFunc - @param {String} message A description of the deprecation. - @param {Function} func The function to be deprecated. - @return {Function} a new function that wrapped the original function with a deprecation warning -*/ -Ember.deprecateFunc = function(message, func) { - return function() { - Ember.deprecate(message); - return func.apply(this, arguments); - }; -}; - -})(); - -// Version: v1.0.0-rc.1-223-g5934230 -// Last commit: 5934230 (2013-03-22 22:26:47 -0700) - - -(function() { -var define, requireModule; - -(function() { - var registry = {}, seen = {}; - - define = function(name, deps, callback) { - registry[name] = { deps: deps, callback: callback }; - }; - - requireModule = function(name) { - if (seen[name]) { return seen[name]; } - seen[name] = {}; - - var mod = registry[name], - deps = mod.deps, - callback = mod.callback, - reified = [], - exports; - - for (var i=0, l=deps.length; i= 0) { - intersection.push(element); - } - }); - - return intersection; - } -}; - -})(); - - - -(function() { -/*jshint newcap:false*/ -/** -@module ember-metal -*/ - -// NOTE: There is a bug in jshint that doesn't recognize `Object()` without `new` -// as being ok unless both `newcap:false` and not `use strict`. -// https://github.com/jshint/jshint/issues/392 - -// Testing this is not ideal, but we want to use native functions -// if available, but not to use versions created by libraries like Prototype -var isNativeFunc = function(func) { - // This should probably work in all browsers likely to have ES5 array methods - return func && Function.prototype.toString.call(func).indexOf('[native code]') > -1; -}; - -// From: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/map -var arrayMap = isNativeFunc(Array.prototype.map) ? Array.prototype.map : function(fun /*, thisp */) { - //"use strict"; - - if (this === void 0 || this === null) { - throw new TypeError(); - } - - var t = Object(this); - var len = t.length >>> 0; - if (typeof fun !== "function") { - throw new TypeError(); - } - - var res = new Array(len); - var thisp = arguments[1]; - for (var i = 0; i < len; i++) { - if (i in t) { - res[i] = fun.call(thisp, t[i], i, t); - } - } - - return res; -}; - -// From: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/foreach -var arrayForEach = isNativeFunc(Array.prototype.forEach) ? Array.prototype.forEach : function(fun /*, thisp */) { - //"use strict"; - - if (this === void 0 || this === null) { - throw new TypeError(); - } - - var t = Object(this); - var len = t.length >>> 0; - if (typeof fun !== "function") { - throw new TypeError(); - } - - var thisp = arguments[1]; - for (var i = 0; i < len; i++) { - if (i in t) { - fun.call(thisp, t[i], i, t); - } - } -}; - -var arrayIndexOf = isNativeFunc(Array.prototype.indexOf) ? Array.prototype.indexOf : function (obj, fromIndex) { - if (fromIndex === null || fromIndex === undefined) { fromIndex = 0; } - else if (fromIndex < 0) { fromIndex = Math.max(0, this.length + fromIndex); } - for (var i = fromIndex, j = this.length; i < j; i++) { - if (this[i] === obj) { return i; } - } - return -1; -}; - -Ember.ArrayPolyfills = { - map: arrayMap, - forEach: arrayForEach, - indexOf: arrayIndexOf -}; - -if (Ember.SHIM_ES5) { - if (!Array.prototype.map) { - Array.prototype.map = arrayMap; - } - - if (!Array.prototype.forEach) { - Array.prototype.forEach = arrayForEach; - } - - if (!Array.prototype.indexOf) { - Array.prototype.indexOf = arrayIndexOf; - } -} - -})(); - - - -(function() { -/** -@module ember-metal -*/ - -/* - JavaScript (before ES6) does not have a Map implementation. Objects, - which are often used as dictionaries, may only have Strings as keys. - - Because Ember has a way to get a unique identifier for every object - via `Ember.guidFor`, we can implement a performant Map with arbitrary - keys. Because it is commonly used in low-level bookkeeping, Map is - implemented as a pure JavaScript object for performance. - - This implementation follows the current iteration of the ES6 proposal for - maps (http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets), - with two exceptions. First, because we need our implementation to be pleasant - on older browsers, we do not use the `delete` name (using `remove` instead). - Second, as we do not have the luxury of in-VM iteration, we implement a - forEach method for iteration. - - Map is mocked out to look like an Ember object, so you can do - `Ember.Map.create()` for symmetry with other Ember classes. -*/ -var guidFor = Ember.guidFor, - indexOf = Ember.ArrayPolyfills.indexOf; - -var copy = function(obj) { - var output = {}; - - for (var prop in obj) { - if (obj.hasOwnProperty(prop)) { output[prop] = obj[prop]; } - } - - return output; -}; - -var copyMap = function(original, newObject) { - var keys = original.keys.copy(), - values = copy(original.values); - - newObject.keys = keys; - newObject.values = values; - - return newObject; -}; - -/** - This class is used internally by Ember and Ember Data. - Please do not use it at this time. We plan to clean it up - and add many tests soon. - - @class OrderedSet - @namespace Ember - @constructor - @private -*/ -var OrderedSet = Ember.OrderedSet = function() { - this.clear(); -}; - -/** - @method create - @static - @return {Ember.OrderedSet} -*/ -OrderedSet.create = function() { - return new OrderedSet(); -}; - - -OrderedSet.prototype = { - /** - @method clear - */ - clear: function() { - this.presenceSet = {}; - this.list = []; - }, - - /** - @method add - @param obj - */ - add: function(obj) { - var guid = guidFor(obj), - presenceSet = this.presenceSet, - list = this.list; - - if (guid in presenceSet) { return; } - - presenceSet[guid] = true; - list.push(obj); - }, - - /** - @method remove - @param obj - */ - remove: function(obj) { - var guid = guidFor(obj), - presenceSet = this.presenceSet, - list = this.list; - - delete presenceSet[guid]; - - var index = indexOf.call(list, obj); - if (index > -1) { - list.splice(index, 1); - } - }, - - /** - @method isEmpty - @return {Boolean} - */ - isEmpty: function() { - return this.list.length === 0; - }, - - /** - @method has - @param obj - @return {Boolean} - */ - has: function(obj) { - var guid = guidFor(obj), - presenceSet = this.presenceSet; - - return guid in presenceSet; - }, - - /** - @method forEach - @param {Function} fn - @param self - */ - forEach: function(fn, self) { - // allow mutation during iteration - var list = this.list.slice(); - - for (var i = 0, j = list.length; i < j; i++) { - fn.call(self, list[i]); - } - }, - - /** - @method toArray - @return {Array} - */ - toArray: function() { - return this.list.slice(); - }, - - /** - @method copy - @return {Ember.OrderedSet} - */ - copy: function() { - var set = new OrderedSet(); - - set.presenceSet = copy(this.presenceSet); - set.list = this.list.slice(); - - return set; - } -}; - -/** - A Map stores values indexed by keys. Unlike JavaScript's - default Objects, the keys of a Map can be any JavaScript - object. - - Internally, a Map has two data structures: - - 1. `keys`: an OrderedSet of all of the existing keys - 2. `values`: a JavaScript Object indexed by the `Ember.guidFor(key)` - - When a key/value pair is added for the first time, we - add the key to the `keys` OrderedSet, and create or - replace an entry in `values`. When an entry is deleted, - we delete its entry in `keys` and `values`. - - @class Map - @namespace Ember - @private - @constructor -*/ -var Map = Ember.Map = function() { - this.keys = Ember.OrderedSet.create(); - this.values = {}; -}; - -/** - @method create - @static -*/ -Map.create = function() { - return new Map(); -}; - -Map.prototype = { - /** - Retrieve the value associated with a given key. - - @method get - @param {anything} key - @return {anything} the value associated with the key, or `undefined` - */ - get: function(key) { - var values = this.values, - guid = guidFor(key); - - return values[guid]; - }, - - /** - Adds a value to the map. If a value for the given key has already been - provided, the new value will replace the old value. - - @method set - @param {anything} key - @param {anything} value - */ - set: function(key, value) { - var keys = this.keys, - values = this.values, - guid = guidFor(key); - - keys.add(key); - values[guid] = value; - }, - - /** - Removes a value from the map for an associated key. - - @method remove - @param {anything} key - @return {Boolean} true if an item was removed, false otherwise - */ - remove: function(key) { - // don't use ES6 "delete" because it will be annoying - // to use in browsers that are not ES6 friendly; - var keys = this.keys, - values = this.values, - guid = guidFor(key), - value; - - if (values.hasOwnProperty(guid)) { - keys.remove(key); - value = values[guid]; - delete values[guid]; - return true; - } else { - return false; - } - }, - - /** - Check whether a key is present. - - @method has - @param {anything} key - @return {Boolean} true if the item was present, false otherwise - */ - has: function(key) { - var values = this.values, - guid = guidFor(key); - - return values.hasOwnProperty(guid); - }, - - /** - Iterate over all the keys and values. Calls the function once - for each key, passing in the key and value, in that order. - - The keys are guaranteed to be iterated over in insertion order. - - @method forEach - @param {Function} callback - @param {anything} self if passed, the `this` value inside the - callback. By default, `this` is the map. - */ - forEach: function(callback, self) { - var keys = this.keys, - values = this.values; - - keys.forEach(function(key) { - var guid = guidFor(key); - callback.call(self, key, values[guid]); - }); - }, - - /** - @method copy - @return {Ember.Map} - */ - copy: function() { - return copyMap(this, new Map()); - } -}; - -/** - @class MapWithDefault - @namespace Ember - @extends Ember.Map - @private - @constructor - @param [options] - @param {anything} [options.defaultValue] -*/ -var MapWithDefault = Ember.MapWithDefault = function(options) { - Map.call(this); - this.defaultValue = options.defaultValue; -}; - -/** - @method create - @static - @param [options] - @param {anything} [options.defaultValue] - @return {Ember.MapWithDefault|Ember.Map} If options are passed, returns - `Ember.MapWithDefault` otherwise returns `Ember.Map` -*/ -MapWithDefault.create = function(options) { - if (options) { - return new MapWithDefault(options); - } else { - return new Map(); - } -}; - -MapWithDefault.prototype = Ember.create(Map.prototype); - -/** - Retrieve the value associated with a given key. - - @method get - @param {anything} key - @return {anything} the value associated with the key, or the default value -*/ -MapWithDefault.prototype.get = function(key) { - var hasValue = this.has(key); - - if (hasValue) { - return Map.prototype.get.call(this, key); - } else { - var defaultValue = this.defaultValue(key); - this.set(key, defaultValue); - return defaultValue; - } -}; - -/** - @method copy - @return {Ember.MapWithDefault} -*/ -MapWithDefault.prototype.copy = function() { - return copyMap(this, new MapWithDefault({ - defaultValue: this.defaultValue - })); -}; - -})(); - - - -(function() { -/** -@module ember-metal -*/ - -var META_KEY = Ember.META_KEY, get, set; - -var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER; - -var IS_GLOBAL = /^([A-Z$]|([0-9][A-Z$]))/; -var IS_GLOBAL_PATH = /^([A-Z$]|([0-9][A-Z$])).*[\.\*]/; -var HAS_THIS = /^this[\.\*]/; -var FIRST_KEY = /^([^\.\*]+)/; - -// .......................................................... -// GET AND SET -// -// If we are on a platform that supports accessors we can use those. -// Otherwise simulate accessors by looking up the property directly on the -// object. - -/** - Gets the value of a property on an object. If the property is computed, - the function will be invoked. If the property is not defined but the - object implements the `unknownProperty` method then that will be invoked. - - If you plan to run on IE8 and older browsers then you should use this - method anytime you want to retrieve a property on an object that you don't - know for sure is private. (Properties beginning with an underscore '_' - are considered private.) - - On all newer browsers, you only need to use this method to retrieve - properties if the property might not be defined on the object and you want - to respect the `unknownProperty` handler. Otherwise you can ignore this - method. - - Note that if the object itself is `undefined`, this method will throw - an error. - - @method get - @for Ember - @param {Object} obj The object to retrieve from. - @param {String} keyName The property key to retrieve - @return {Object} the property value or `null`. -*/ -get = function get(obj, keyName) { - // Helpers that operate with 'this' within an #each - if (keyName === '') { - return obj; - } - - if (!keyName && 'string'===typeof obj) { - keyName = obj; - obj = null; - } - - if (!obj || keyName.indexOf('.') !== -1) { - Ember.assert("Cannot call get with '"+ keyName +"' on an undefined object.", obj !== undefined); - return getPath(obj, keyName); - } - - Ember.assert("You need to provide an object and key to `get`.", !!obj && keyName); - - var meta = obj[META_KEY], desc = meta && meta.descs[keyName], ret; - if (desc) { - return desc.get(obj, keyName); - } else { - if (MANDATORY_SETTER && meta && meta.watching[keyName] > 0) { - ret = meta.values[keyName]; - } else { - ret = obj[keyName]; - } - - if (ret === undefined && - 'object' === typeof obj && !(keyName in obj) && 'function' === typeof obj.unknownProperty) { - return obj.unknownProperty(keyName); - } - - return ret; - } -}; - -/** - Sets the value of a property on an object, respecting computed properties - and notifying observers and other listeners of the change. If the - property is not defined but the object implements the `unknownProperty` - method then that will be invoked as well. - - If you plan to run on IE8 and older browsers then you should use this - method anytime you want to set a property on an object that you don't - know for sure is private. (Properties beginning with an underscore '_' - are considered private.) - - On all newer browsers, you only need to use this method to set - properties if the property might not be defined on the object and you want - to respect the `unknownProperty` handler. Otherwise you can ignore this - method. - - @method set - @for Ember - @param {Object} obj The object to modify. - @param {String} keyName The property key to set - @param {Object} value The value to set - @return {Object} the passed value. -*/ -set = function set(obj, keyName, value, tolerant) { - if (typeof obj === 'string') { - Ember.assert("Path '" + obj + "' must be global if no obj is given.", IS_GLOBAL.test(obj)); - value = keyName; - keyName = obj; - obj = null; - } - - if (!obj || keyName.indexOf('.') !== -1) { - return setPath(obj, keyName, value, tolerant); - } - - Ember.assert("You need to provide an object and key to `set`.", !!obj && keyName !== undefined); - Ember.assert('calling set on destroyed object', !obj.isDestroyed); - - var meta = obj[META_KEY], desc = meta && meta.descs[keyName], - isUnknown, currentValue; - if (desc) { - desc.set(obj, keyName, value); - } else { - isUnknown = 'object' === typeof obj && !(keyName in obj); - - // setUnknownProperty is called if `obj` is an object, - // the property does not already exist, and the - // `setUnknownProperty` method exists on the object - if (isUnknown && 'function' === typeof obj.setUnknownProperty) { - obj.setUnknownProperty(keyName, value); - } else if (meta && meta.watching[keyName] > 0) { - if (MANDATORY_SETTER) { - currentValue = meta.values[keyName]; - } else { - currentValue = obj[keyName]; - } - // only trigger a change if the value has changed - if (value !== currentValue) { - Ember.propertyWillChange(obj, keyName); - if (MANDATORY_SETTER) { - if (currentValue === undefined && !(keyName in obj)) { - Ember.defineProperty(obj, keyName, null, value); // setup mandatory setter - } else { - meta.values[keyName] = value; - } - } else { - obj[keyName] = value; - } - Ember.propertyDidChange(obj, keyName); - } - } else { - obj[keyName] = value; - } - } - return value; -}; - -// Currently used only by Ember Data tests -if (Ember.config.overrideAccessors) { - Ember.get = get; - Ember.set = set; - Ember.config.overrideAccessors(); - get = Ember.get; - set = Ember.set; -} - -function firstKey(path) { - return path.match(FIRST_KEY)[0]; -} - -// assumes path is already normalized -function normalizeTuple(target, path) { - var hasThis = HAS_THIS.test(path), - isGlobal = !hasThis && IS_GLOBAL_PATH.test(path), - key; - - if (!target || isGlobal) target = Ember.lookup; - if (hasThis) path = path.slice(5); - - if (target === Ember.lookup) { - key = firstKey(path); - target = get(target, key); - path = path.slice(key.length+1); - } - - // must return some kind of path to be valid else other things will break. - if (!path || path.length===0) throw new Error('Invalid Path'); - - return [ target, path ]; -} - -function getPath(root, path) { - var hasThis, parts, tuple, idx, len; - - // If there is no root and path is a key name, return that - // property from the global object. - // E.g. get('Ember') -> Ember - if (root === null && path.indexOf('.') === -1) { return get(Ember.lookup, path); } - - // detect complicated paths and normalize them - hasThis = HAS_THIS.test(path); - - if (!root || hasThis) { - tuple = normalizeTuple(root, path); - root = tuple[0]; - path = tuple[1]; - tuple.length = 0; - } - - parts = path.split("."); - len = parts.length; - for (idx=0; root && idx 0; - - if (existingDesc instanceof Ember.Descriptor) { - existingDesc.teardown(obj, keyName); - } - - if (desc instanceof Ember.Descriptor) { - value = desc; - - descs[keyName] = desc; - if (MANDATORY_SETTER && watching) { - objectDefineProperty(obj, keyName, { - configurable: true, - enumerable: true, - writable: true, - value: undefined // make enumerable - }); - } else { - obj[keyName] = undefined; // make enumerable - } - desc.setup(obj, keyName); - } else { - descs[keyName] = undefined; // shadow descriptor in proto - if (desc == null) { - value = data; - - if (MANDATORY_SETTER && watching) { - meta.values[keyName] = data; - objectDefineProperty(obj, keyName, { - configurable: true, - enumerable: true, - set: MANDATORY_SETTER_FUNCTION, - get: DEFAULT_GETTER_FUNCTION(keyName) - }); - } else { - obj[keyName] = data; - } - } else { - value = desc; - - // compatibility with ES5 - objectDefineProperty(obj, keyName, desc); - } - } - - // if key is being watched, override chains that - // were initialized with the prototype - if (watching) { Ember.overrideChains(obj, keyName, meta); } - - // The `value` passed to the `didDefineProperty` hook is - // either the descriptor or data, whichever was passed. - if (obj.didDefineProperty) { obj.didDefineProperty(obj, keyName, value); } - - return this; -}; - - -})(); - - - -(function() { -// Ember.tryFinally -/** -@module ember-metal -*/ - -var AFTER_OBSERVERS = ':change'; -var BEFORE_OBSERVERS = ':before'; - -var guidFor = Ember.guidFor; - -var deferred = 0; - -/* - this.observerSet = { - [senderGuid]: { // variable name: `keySet` - [keyName]: listIndex - } - }, - this.observers = [ - { - sender: obj, - keyName: keyName, - eventName: eventName, - listeners: [ - [target, method, onceFlag, suspendedFlag] - ] - }, - ... - ] -*/ -function ObserverSet() { - this.clear(); -} - -ObserverSet.prototype.add = function(sender, keyName, eventName) { - var observerSet = this.observerSet, - observers = this.observers, - senderGuid = Ember.guidFor(sender), - keySet = observerSet[senderGuid], - index; - - if (!keySet) { - observerSet[senderGuid] = keySet = {}; - } - index = keySet[keyName]; - if (index === undefined) { - index = observers.push({ - sender: sender, - keyName: keyName, - eventName: eventName, - listeners: [] - }) - 1; - keySet[keyName] = index; - } - return observers[index].listeners; -}; - -ObserverSet.prototype.flush = function() { - var observers = this.observers, i, len, observer, sender; - this.clear(); - for (i=0, len=observers.length; i < len; ++i) { - observer = observers[i]; - sender = observer.sender; - if (sender.isDestroying || sender.isDestroyed) { continue; } - Ember.sendEvent(sender, observer.eventName, [sender, observer.keyName], observer.listeners); - } -}; - -ObserverSet.prototype.clear = function() { - this.observerSet = {}; - this.observers = []; -}; - -var beforeObserverSet = new ObserverSet(), observerSet = new ObserverSet(); - -/** - @method beginPropertyChanges - @chainable -*/ -Ember.beginPropertyChanges = function() { - deferred++; -}; - -/** - @method endPropertyChanges -*/ -Ember.endPropertyChanges = function() { - deferred--; - if (deferred<=0) { - beforeObserverSet.clear(); - observerSet.flush(); - } -}; - -/** - Make a series of property changes together in an - exception-safe way. - - ```javascript - Ember.changeProperties(function() { - obj1.set('foo', mayBlowUpWhenSet); - obj2.set('bar', baz); - }); - ``` - - @method changeProperties - @param {Function} callback - @param [binding] -*/ -Ember.changeProperties = function(cb, binding){ - Ember.beginPropertyChanges(); - Ember.tryFinally(cb, Ember.endPropertyChanges, binding); -}; - -/** - Set a list of properties on an object. These properties are set inside - a single `beginPropertyChanges` and `endPropertyChanges` batch, so - observers will be buffered. - - @method setProperties - @param target - @param {Hash} properties - @return target -*/ -Ember.setProperties = function(self, hash) { - Ember.changeProperties(function(){ - for(var prop in hash) { - if (hash.hasOwnProperty(prop)) Ember.set(self, prop, hash[prop]); - } - }); - return self; -}; - - -function changeEvent(keyName) { - return keyName+AFTER_OBSERVERS; -} - -function beforeEvent(keyName) { - return keyName+BEFORE_OBSERVERS; -} - -/** - @method addObserver - @param obj - @param {String} path - @param {Object|Function} targetOrMethod - @param {Function|String} [method] -*/ -Ember.addObserver = function(obj, path, target, method) { - Ember.addListener(obj, changeEvent(path), target, method); - Ember.watch(obj, path); - return this; -}; - -Ember.observersFor = function(obj, path) { - return Ember.listenersFor(obj, changeEvent(path)); -}; - -/** - @method removeObserver - @param obj - @param {String} path - @param {Object|Function} targetOrMethod - @param {Function|String} [method] -*/ -Ember.removeObserver = function(obj, path, target, method) { - Ember.unwatch(obj, path); - Ember.removeListener(obj, changeEvent(path), target, method); - return this; -}; - -/** - @method addBeforeObserver - @param obj - @param {String} path - @param {Object|Function} targetOrMethod - @param {Function|String} [method] -*/ -Ember.addBeforeObserver = function(obj, path, target, method) { - Ember.addListener(obj, beforeEvent(path), target, method); - Ember.watch(obj, path); - return this; -}; - -// Suspend observer during callback. -// -// This should only be used by the target of the observer -// while it is setting the observed path. -Ember._suspendBeforeObserver = function(obj, path, target, method, callback) { - return Ember._suspendListener(obj, beforeEvent(path), target, method, callback); -}; - -Ember._suspendObserver = function(obj, path, target, method, callback) { - return Ember._suspendListener(obj, changeEvent(path), target, method, callback); -}; - -var map = Ember.ArrayPolyfills.map; - -Ember._suspendBeforeObservers = function(obj, paths, target, method, callback) { - var events = map.call(paths, beforeEvent); - return Ember._suspendListeners(obj, events, target, method, callback); -}; - -Ember._suspendObservers = function(obj, paths, target, method, callback) { - var events = map.call(paths, changeEvent); - return Ember._suspendListeners(obj, events, target, method, callback); -}; - -Ember.beforeObserversFor = function(obj, path) { - return Ember.listenersFor(obj, beforeEvent(path)); -}; - -/** - @method removeBeforeObserver - @param obj - @param {String} path - @param {Object|Function} targetOrMethod - @param {Function|String} [method] -*/ -Ember.removeBeforeObserver = function(obj, path, target, method) { - Ember.unwatch(obj, path); - Ember.removeListener(obj, beforeEvent(path), target, method); - return this; -}; - -Ember.notifyBeforeObservers = function(obj, keyName) { - if (obj.isDestroying) { return; } - - var eventName = beforeEvent(keyName), listeners, listenersDiff; - if (deferred) { - listeners = beforeObserverSet.add(obj, keyName, eventName); - listenersDiff = Ember.listenersDiff(obj, eventName, listeners); - Ember.sendEvent(obj, eventName, [obj, keyName], listenersDiff); - } else { - Ember.sendEvent(obj, eventName, [obj, keyName]); - } -}; - -Ember.notifyObservers = function(obj, keyName) { - if (obj.isDestroying) { return; } - - var eventName = changeEvent(keyName), listeners; - if (deferred) { - listeners = observerSet.add(obj, keyName, eventName); - Ember.listenersUnion(obj, eventName, listeners); - } else { - Ember.sendEvent(obj, eventName, [obj, keyName]); - } -}; - -})(); - - - -(function() { -/** -@module ember-metal -*/ - -var guidFor = Ember.guidFor, // utils.js - metaFor = Ember.meta, // utils.js - get = Ember.get, // accessors.js - set = Ember.set, // accessors.js - normalizeTuple = Ember.normalizeTuple, // accessors.js - GUID_KEY = Ember.GUID_KEY, // utils.js - META_KEY = Ember.META_KEY, // utils.js - // circular reference observer depends on Ember.watch - // we should move change events to this file or its own property_events.js - forEach = Ember.ArrayPolyfills.forEach, // array.js - FIRST_KEY = /^([^\.\*]+)/, - IS_PATH = /[\.\*]/; - -var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER, -o_defineProperty = Ember.platform.defineProperty; - -function firstKey(path) { - return path.match(FIRST_KEY)[0]; -} - -// returns true if the passed path is just a keyName -function isKeyName(path) { - return path==='*' || !IS_PATH.test(path); -} - -// .......................................................... -// DEPENDENT KEYS -// - -function iterDeps(method, obj, depKey, seen, meta) { - - var guid = guidFor(obj); - if (!seen[guid]) seen[guid] = {}; - if (seen[guid][depKey]) return; - seen[guid][depKey] = true; - - var deps = meta.deps; - deps = deps && deps[depKey]; - if (deps) { - for(var key in deps) { - var desc = meta.descs[key]; - if (desc && desc._suspended === obj) continue; - method(obj, key); - } - } -} - - -var WILL_SEEN, DID_SEEN; - -// called whenever a property is about to change to clear the cache of any dependent keys (and notify those properties of changes, etc...) -function dependentKeysWillChange(obj, depKey, meta) { - if (obj.isDestroying) { return; } - - var seen = WILL_SEEN, top = !seen; - if (top) { seen = WILL_SEEN = {}; } - iterDeps(propertyWillChange, obj, depKey, seen, meta); - if (top) { WILL_SEEN = null; } -} - -// called whenever a property has just changed to update dependent keys -function dependentKeysDidChange(obj, depKey, meta) { - if (obj.isDestroying) { return; } - - var seen = DID_SEEN, top = !seen; - if (top) { seen = DID_SEEN = {}; } - iterDeps(propertyDidChange, obj, depKey, seen, meta); - if (top) { DID_SEEN = null; } -} - -// .......................................................... -// CHAIN -// - -function addChainWatcher(obj, keyName, node) { - if (!obj || ('object' !== typeof obj)) { return; } // nothing to do - - var m = metaFor(obj), nodes = m.chainWatchers; - - if (!m.hasOwnProperty('chainWatchers')) { - nodes = m.chainWatchers = {}; - } - - if (!nodes[keyName]) { nodes[keyName] = []; } - nodes[keyName].push(node); - Ember.watch(obj, keyName); -} - -function removeChainWatcher(obj, keyName, node) { - if (!obj || 'object' !== typeof obj) { return; } // nothing to do - - var m = metaFor(obj, false); - if (!m.hasOwnProperty('chainWatchers')) { return; } // nothing to do - - var nodes = m.chainWatchers; - - if (nodes[keyName]) { - nodes = nodes[keyName]; - for (var i = 0, l = nodes.length; i < l; i++) { - if (nodes[i] === node) { nodes.splice(i, 1); } - } - } - Ember.unwatch(obj, keyName); -} - -var pendingQueue = []; - -// attempts to add the pendingQueue chains again. If some of them end up -// back in the queue and reschedule is true, schedules a timeout to try -// again. -function flushPendingChains() { - if (pendingQueue.length === 0) { return; } // nothing to do - - var queue = pendingQueue; - pendingQueue = []; - - forEach.call(queue, function(q) { q[0].add(q[1]); }); - - Ember.warn('Watching an undefined global, Ember expects watched globals to be setup by the time the run loop is flushed, check for typos', pendingQueue.length === 0); -} - -function isProto(pvalue) { - return metaFor(pvalue, false).proto === pvalue; -} - -// A ChainNode watches a single key on an object. If you provide a starting -// value for the key then the node won't actually watch it. For a root node -// pass null for parent and key and object for value. -var ChainNode = function(parent, key, value) { - var obj; - this._parent = parent; - this._key = key; - - // _watching is true when calling get(this._parent, this._key) will - // return the value of this node. - // - // It is false for the root of a chain (because we have no parent) - // and for global paths (because the parent node is the object with - // the observer on it) - this._watching = value===undefined; - - this._value = value; - this._paths = {}; - if (this._watching) { - this._object = parent.value(); - if (this._object) { addChainWatcher(this._object, this._key, this); } - } - - // Special-case: the EachProxy relies on immediate evaluation to - // establish its observers. - // - // TODO: Replace this with an efficient callback that the EachProxy - // can implement. - if (this._parent && this._parent._key === '@each') { - this.value(); - } -}; - -var ChainNodePrototype = ChainNode.prototype; - -ChainNodePrototype.value = function() { - if (this._value === undefined && this._watching) { - var obj = this._parent.value(); - this._value = (obj && !isProto(obj)) ? get(obj, this._key) : undefined; - } - return this._value; -}; - -ChainNodePrototype.destroy = function() { - if (this._watching) { - var obj = this._object; - if (obj) { removeChainWatcher(obj, this._key, this); } - this._watching = false; // so future calls do nothing - } -}; - -// copies a top level object only -ChainNodePrototype.copy = function(obj) { - var ret = new ChainNode(null, null, obj), - paths = this._paths, path; - for (path in paths) { - if (paths[path] <= 0) { continue; } // this check will also catch non-number vals. - ret.add(path); - } - return ret; -}; - -// called on the root node of a chain to setup watchers on the specified -// path. -ChainNodePrototype.add = function(path) { - var obj, tuple, key, src, paths; - - paths = this._paths; - paths[path] = (paths[path] || 0) + 1; - - obj = this.value(); - tuple = normalizeTuple(obj, path); - - // the path was a local path - if (tuple[0] && tuple[0] === obj) { - path = tuple[1]; - key = firstKey(path); - path = path.slice(key.length+1); - - // global path, but object does not exist yet. - // put into a queue and try to connect later. - } else if (!tuple[0]) { - pendingQueue.push([this, path]); - tuple.length = 0; - return; - - // global path, and object already exists - } else { - src = tuple[0]; - key = path.slice(0, 0-(tuple[1].length+1)); - path = tuple[1]; - } - - tuple.length = 0; - this.chain(key, path, src); -}; - -// called on the root node of a chain to teardown watcher on the specified -// path -ChainNodePrototype.remove = function(path) { - var obj, tuple, key, src, paths; - - paths = this._paths; - if (paths[path] > 0) { paths[path]--; } - - obj = this.value(); - tuple = normalizeTuple(obj, path); - if (tuple[0] === obj) { - path = tuple[1]; - key = firstKey(path); - path = path.slice(key.length+1); - } else { - src = tuple[0]; - key = path.slice(0, 0-(tuple[1].length+1)); - path = tuple[1]; - } - - tuple.length = 0; - this.unchain(key, path); -}; - -ChainNodePrototype.count = 0; - -ChainNodePrototype.chain = function(key, path, src) { - var chains = this._chains, node; - if (!chains) { chains = this._chains = {}; } - - node = chains[key]; - if (!node) { node = chains[key] = new ChainNode(this, key, src); } - node.count++; // count chains... - - // chain rest of path if there is one - if (path && path.length>0) { - key = firstKey(path); - path = path.slice(key.length+1); - node.chain(key, path); // NOTE: no src means it will observe changes... - } -}; - -ChainNodePrototype.unchain = function(key, path) { - var chains = this._chains, node = chains[key]; - - // unchain rest of path first... - if (path && path.length>1) { - key = firstKey(path); - path = path.slice(key.length+1); - node.unchain(key, path); - } - - // delete node if needed. - node.count--; - if (node.count<=0) { - delete chains[node._key]; - node.destroy(); - } - -}; - -ChainNodePrototype.willChange = function() { - var chains = this._chains; - if (chains) { - for(var key in chains) { - if (!chains.hasOwnProperty(key)) { continue; } - chains[key].willChange(); - } - } - - if (this._parent) { this._parent.chainWillChange(this, this._key, 1); } -}; - -ChainNodePrototype.chainWillChange = function(chain, path, depth) { - if (this._key) { path = this._key + '.' + path; } - - if (this._parent) { - this._parent.chainWillChange(this, path, depth+1); - } else { - if (depth > 1) { Ember.propertyWillChange(this.value(), path); } - path = 'this.' + path; - if (this._paths[path] > 0) { Ember.propertyWillChange(this.value(), path); } - } -}; - -ChainNodePrototype.chainDidChange = function(chain, path, depth) { - if (this._key) { path = this._key + '.' + path; } - if (this._parent) { - this._parent.chainDidChange(this, path, depth+1); - } else { - if (depth > 1) { Ember.propertyDidChange(this.value(), path); } - path = 'this.' + path; - if (this._paths[path] > 0) { Ember.propertyDidChange(this.value(), path); } - } -}; - -ChainNodePrototype.didChange = function(suppressEvent) { - // invalidate my own value first. - if (this._watching) { - var obj = this._parent.value(); - if (obj !== this._object) { - removeChainWatcher(this._object, this._key, this); - this._object = obj; - addChainWatcher(obj, this._key, this); - } - this._value = undefined; - - // Special-case: the EachProxy relies on immediate evaluation to - // establish its observers. - if (this._parent && this._parent._key === '@each') - this.value(); - } - - // then notify chains... - var chains = this._chains; - if (chains) { - for(var key in chains) { - if (!chains.hasOwnProperty(key)) { continue; } - chains[key].didChange(suppressEvent); - } - } - - if (suppressEvent) { return; } - - // and finally tell parent about my path changing... - if (this._parent) { this._parent.chainDidChange(this, this._key, 1); } -}; - -// get the chains for the current object. If the current object has -// chains inherited from the proto they will be cloned and reconfigured for -// the current object. -function chainsFor(obj) { - var m = metaFor(obj), ret = m.chains; - if (!ret) { - ret = m.chains = new ChainNode(null, null, obj); - } else if (ret.value() !== obj) { - ret = m.chains = ret.copy(obj); - } - return ret; -} - -Ember.overrideChains = function(obj, keyName, m) { - chainsDidChange(obj, keyName, m, true); -}; - -function chainsWillChange(obj, keyName, m, arg) { - if (!m.hasOwnProperty('chainWatchers')) { return; } // nothing to do - - var nodes = m.chainWatchers; - - nodes = nodes[keyName]; - if (!nodes) { return; } - - for(var i = 0, l = nodes.length; i < l; i++) { - nodes[i].willChange(arg); - } -} - -function chainsDidChange(obj, keyName, m, arg) { - if (!m.hasOwnProperty('chainWatchers')) { return; } // nothing to do - - var nodes = m.chainWatchers; - - nodes = nodes[keyName]; - if (!nodes) { return; } - - // looping in reverse because the chainWatchers array can be modified inside didChange - for (var i = nodes.length - 1; i >= 0; i--) { - nodes[i].didChange(arg); - } -} - -// .......................................................... -// WATCH -// - -/** - @private - - Starts watching a property on an object. Whenever the property changes, - invokes `Ember.propertyWillChange` and `Ember.propertyDidChange`. This is the - primitive used by observers and dependent keys; usually you will never call - this method directly but instead use higher level methods like - `Ember.addObserver()` - - @method watch - @for Ember - @param obj - @param {String} keyName -*/ -Ember.watch = function(obj, keyName) { - // can't watch length on Array - it is special... - if (keyName === 'length' && Ember.typeOf(obj) === 'array') { return this; } - - var m = metaFor(obj), watching = m.watching, desc; - - // activate watching first time - if (!watching[keyName]) { - watching[keyName] = 1; - if (isKeyName(keyName)) { - desc = m.descs[keyName]; - if (desc && desc.willWatch) { desc.willWatch(obj, keyName); } - - if ('function' === typeof obj.willWatchProperty) { - obj.willWatchProperty(keyName); - } - - if (MANDATORY_SETTER && keyName in obj) { - m.values[keyName] = obj[keyName]; - o_defineProperty(obj, keyName, { - configurable: true, - enumerable: true, - set: Ember.MANDATORY_SETTER_FUNCTION, - get: Ember.DEFAULT_GETTER_FUNCTION(keyName) - }); - } - } else { - chainsFor(obj).add(keyName); - } - - } else { - watching[keyName] = (watching[keyName] || 0) + 1; - } - return this; -}; - -Ember.isWatching = function isWatching(obj, key) { - var meta = obj[META_KEY]; - return (meta && meta.watching[key]) > 0; -}; - -Ember.watch.flushPending = flushPendingChains; - -Ember.unwatch = function(obj, keyName) { - // can't watch length on Array - it is special... - if (keyName === 'length' && Ember.typeOf(obj) === 'array') { return this; } - - var m = metaFor(obj), watching = m.watching, desc; - - if (watching[keyName] === 1) { - watching[keyName] = 0; - - if (isKeyName(keyName)) { - desc = m.descs[keyName]; - if (desc && desc.didUnwatch) { desc.didUnwatch(obj, keyName); } - - if ('function' === typeof obj.didUnwatchProperty) { - obj.didUnwatchProperty(keyName); - } - - if (MANDATORY_SETTER && keyName in obj) { - o_defineProperty(obj, keyName, { - configurable: true, - enumerable: true, - writable: true, - value: m.values[keyName] - }); - delete m.values[keyName]; - } - } else { - chainsFor(obj).remove(keyName); - } - - } else if (watching[keyName]>1) { - watching[keyName]--; - } - - return this; -}; - -/** - @private - - Call on an object when you first beget it from another object. This will - setup any chained watchers on the object instance as needed. This method is - safe to call multiple times. - - @method rewatch - @for Ember - @param obj -*/ -Ember.rewatch = function(obj) { - var m = metaFor(obj, false), chains = m.chains; - - // make sure the object has its own guid. - if (GUID_KEY in obj && !obj.hasOwnProperty(GUID_KEY)) { - Ember.generateGuid(obj, 'ember'); - } - - // make sure any chained watchers update. - if (chains && chains.value() !== obj) { - m.chains = chains.copy(obj); - } - - return this; -}; - -Ember.finishChains = function(obj) { - var m = metaFor(obj, false), chains = m.chains; - if (chains) { - if (chains.value() !== obj) { - m.chains = chains = chains.copy(obj); - } - chains.didChange(true); - } -}; - -// .......................................................... -// PROPERTY CHANGES -// - -/** - This function is called just before an object property is about to change. - It will notify any before observers and prepare caches among other things. - - Normally you will not need to call this method directly but if for some - reason you can't directly watch a property you can invoke this method - manually along with `Ember.propertyDidChange()` which you should call just - after the property value changes. - - @method propertyWillChange - @for Ember - @param {Object} obj The object with the property that will change - @param {String} keyName The property key (or path) that will change. - @return {void} -*/ -function propertyWillChange(obj, keyName) { - var m = metaFor(obj, false), - watching = m.watching[keyName] > 0 || keyName === 'length', - proto = m.proto, - desc = m.descs[keyName]; - - if (!watching) { return; } - if (proto === obj) { return; } - if (desc && desc.willChange) { desc.willChange(obj, keyName); } - dependentKeysWillChange(obj, keyName, m); - chainsWillChange(obj, keyName, m); - Ember.notifyBeforeObservers(obj, keyName); -} - -Ember.propertyWillChange = propertyWillChange; - -/** - This function is called just after an object property has changed. - It will notify any observers and clear caches among other things. - - Normally you will not need to call this method directly but if for some - reason you can't directly watch a property you can invoke this method - manually along with `Ember.propertyWilLChange()` which you should call just - before the property value changes. - - @method propertyDidChange - @for Ember - @param {Object} obj The object with the property that will change - @param {String} keyName The property key (or path) that will change. - @return {void} -*/ -function propertyDidChange(obj, keyName) { - var m = metaFor(obj, false), - watching = m.watching[keyName] > 0 || keyName === 'length', - proto = m.proto, - desc = m.descs[keyName]; - - if (proto === obj) { return; } - - // shouldn't this mean that we're watching this key? - if (desc && desc.didChange) { desc.didChange(obj, keyName); } - if (!watching && keyName !== 'length') { return; } - - dependentKeysDidChange(obj, keyName, m); - chainsDidChange(obj, keyName, m); - Ember.notifyObservers(obj, keyName); -} - -Ember.propertyDidChange = propertyDidChange; - -var NODE_STACK = []; - -/** - Tears down the meta on an object so that it can be garbage collected. - Multiple calls will have no effect. - - @method destroy - @for Ember - @param {Object} obj the object to destroy - @return {void} -*/ -Ember.destroy = function (obj) { - var meta = obj[META_KEY], node, nodes, key, nodeObject; - if (meta) { - obj[META_KEY] = null; - // remove chainWatchers to remove circular references that would prevent GC - node = meta.chains; - if (node) { - NODE_STACK.push(node); - // process tree - while (NODE_STACK.length > 0) { - node = NODE_STACK.pop(); - // push children - nodes = node._chains; - if (nodes) { - for (key in nodes) { - if (nodes.hasOwnProperty(key)) { - NODE_STACK.push(nodes[key]); - } - } - } - // remove chainWatcher in node object - if (node._watching) { - nodeObject = node._object; - if (nodeObject) { - removeChainWatcher(nodeObject, node._key, node); - } - } - } - } - } -}; - -})(); - - - -(function() { -/** -@module ember-metal -*/ - -Ember.warn("The CP_DEFAULT_CACHEABLE flag has been removed and computed properties are always cached by default. Use `volatile` if you don't want caching.", Ember.ENV.CP_DEFAULT_CACHEABLE !== false); - - -var get = Ember.get, - set = Ember.set, - metaFor = Ember.meta, - a_slice = [].slice, - o_create = Ember.create, - META_KEY = Ember.META_KEY, - watch = Ember.watch, - unwatch = Ember.unwatch; - -// .......................................................... -// DEPENDENT KEYS -// - -// data structure: -// meta.deps = { -// 'depKey': { -// 'keyName': count, -// } -// } - -/* - This function returns a map of unique dependencies for a - given object and key. -*/ -function keysForDep(obj, depsMeta, depKey) { - var keys = depsMeta[depKey]; - if (!keys) { - // if there are no dependencies yet for a the given key - // create a new empty list of dependencies for the key - keys = depsMeta[depKey] = {}; - } else if (!depsMeta.hasOwnProperty(depKey)) { - // otherwise if the dependency list is inherited from - // a superclass, clone the hash - keys = depsMeta[depKey] = o_create(keys); - } - return keys; -} - -function metaForDeps(obj, meta) { - return keysForDep(obj, meta, 'deps'); -} - -function addDependentKeys(desc, obj, keyName, meta) { - // the descriptor has a list of dependent keys, so - // add all of its dependent keys. - var depKeys = desc._dependentKeys, depsMeta, idx, len, depKey, keys; - if (!depKeys) return; - - depsMeta = metaForDeps(obj, meta); - - for(idx = 0, len = depKeys.length; idx < len; idx++) { - depKey = depKeys[idx]; - // Lookup keys meta for depKey - keys = keysForDep(obj, depsMeta, depKey); - // Increment the number of times depKey depends on keyName. - keys[keyName] = (keys[keyName] || 0) + 1; - // Watch the depKey - watch(obj, depKey); - } -} - -function removeDependentKeys(desc, obj, keyName, meta) { - // the descriptor has a list of dependent keys, so - // add all of its dependent keys. - var depKeys = desc._dependentKeys, depsMeta, idx, len, depKey, keys; - if (!depKeys) return; - - depsMeta = metaForDeps(obj, meta); - - for(idx = 0, len = depKeys.length; idx < len; idx++) { - depKey = depKeys[idx]; - // Lookup keys meta for depKey - keys = keysForDep(obj, depsMeta, depKey); - // Increment the number of times depKey depends on keyName. - keys[keyName] = (keys[keyName] || 0) - 1; - // Watch the depKey - unwatch(obj, depKey); - } -} - -// .......................................................... -// COMPUTED PROPERTY -// - -/** - @class ComputedProperty - @namespace Ember - @extends Ember.Descriptor - @constructor -*/ -function ComputedProperty(func, opts) { - this.func = func; - - this._cacheable = (opts && opts.cacheable !== undefined) ? opts.cacheable : true; - this._dependentKeys = opts && opts.dependentKeys; - this._readOnly = opts && (opts.readOnly !== undefined || !!opts.readOnly); -} - -Ember.ComputedProperty = ComputedProperty; -ComputedProperty.prototype = new Ember.Descriptor(); - -var ComputedPropertyPrototype = ComputedProperty.prototype; - -/** - Call on a computed property to set it into cacheable mode. When in this - mode the computed property will automatically cache the return value of - your function until one of the dependent keys changes. - - ```javascript - MyApp.president = Ember.Object.create({ - fullName: function() { - return this.get('firstName') + ' ' + this.get('lastName'); - - // After calculating the value of this function, Ember will - // return that value without re-executing this function until - // one of the dependent properties change. - }.property('firstName', 'lastName') - }); - ``` - - Properties are cacheable by default. - - @method cacheable - @param {Boolean} aFlag optional set to `false` to disable caching - @return {Ember.ComputedProperty} this - @chainable -*/ -ComputedPropertyPrototype.cacheable = function(aFlag) { - this._cacheable = aFlag !== false; - return this; -}; - -/** - Call on a computed property to set it into non-cached mode. When in this - mode the computed property will not automatically cache the return value. - - ```javascript - MyApp.outsideService = Ember.Object.create({ - value: function() { - return OutsideService.getValue(); - }.property().volatile() - }); - ``` - - @method volatile - @return {Ember.ComputedProperty} this - @chainable -*/ -ComputedPropertyPrototype.volatile = function() { - return this.cacheable(false); -}; - -/** - Call on a computed property to set it into read-only mode. When in this - mode the computed property will throw an error when set. - - ```javascript - MyApp.person = Ember.Object.create({ - guid: function() { - return 'guid-guid-guid'; - }.property().readOnly() - }); - - MyApp.person.set('guid', 'new-guid'); // will throw an exception - ``` - - @method readOnly - @return {Ember.ComputedProperty} this - @chainable -*/ -ComputedPropertyPrototype.readOnly = function(readOnly) { - this._readOnly = readOnly === undefined || !!readOnly; - return this; -}; - -/** - Sets the dependent keys on this computed property. Pass any number of - arguments containing key paths that this computed property depends on. - - ```javascript - MyApp.president = Ember.Object.create({ - fullName: Ember.computed(function() { - return this.get('firstName') + ' ' + this.get('lastName'); - - // Tell Ember that this computed property depends on firstName - // and lastName - }).property('firstName', 'lastName') - }); - ``` - - @method property - @param {String} path* zero or more property paths - @return {Ember.ComputedProperty} this - @chainable -*/ -ComputedPropertyPrototype.property = function() { - var args = []; - for (var i = 0, l = arguments.length; i < l; i++) { - args.push(arguments[i]); - } - this._dependentKeys = args; - return this; -}; - -/** - In some cases, you may want to annotate computed properties with additional - metadata about how they function or what values they operate on. For example, - computed property functions may close over variables that are then no longer - available for introspection. - - You can pass a hash of these values to a computed property like this: - - ``` - person: function() { - var personId = this.get('personId'); - return App.Person.create({ id: personId }); - }.property().meta({ type: App.Person }) - ``` - - The hash that you pass to the `meta()` function will be saved on the - computed property descriptor under the `_meta` key. Ember runtime - exposes a public API for retrieving these values from classes, - via the `metaForProperty()` function. - - @method meta - @param {Hash} meta - @chainable -*/ - -ComputedPropertyPrototype.meta = function(meta) { - if (arguments.length === 0) { - return this._meta || {}; - } else { - this._meta = meta; - return this; - } -}; - -/* impl descriptor API */ -ComputedPropertyPrototype.willWatch = function(obj, keyName) { - // watch already creates meta for this instance - var meta = obj[META_KEY]; - Ember.assert('watch should have setup meta to be writable', meta.source === obj); - if (!(keyName in meta.cache)) { - addDependentKeys(this, obj, keyName, meta); - } -}; - -ComputedPropertyPrototype.didUnwatch = function(obj, keyName) { - var meta = obj[META_KEY]; - Ember.assert('unwatch should have setup meta to be writable', meta.source === obj); - if (!(keyName in meta.cache)) { - // unwatch already creates meta for this instance - removeDependentKeys(this, obj, keyName, meta); - } -}; - -/* impl descriptor API */ -ComputedPropertyPrototype.didChange = function(obj, keyName) { - // _suspended is set via a CP.set to ensure we don't clear - // the cached value set by the setter - if (this._cacheable && this._suspended !== obj) { - var meta = metaFor(obj); - if (keyName in meta.cache) { - delete meta.cache[keyName]; - if (!meta.watching[keyName]) { - removeDependentKeys(this, obj, keyName, meta); - } - } - } -}; - -/* impl descriptor API */ -ComputedPropertyPrototype.get = function(obj, keyName) { - var ret, cache, meta; - if (this._cacheable) { - meta = metaFor(obj); - cache = meta.cache; - if (keyName in cache) { return cache[keyName]; } - ret = cache[keyName] = this.func.call(obj, keyName); - if (!meta.watching[keyName]) { - addDependentKeys(this, obj, keyName, meta); - } - } else { - ret = this.func.call(obj, keyName); - } - return ret; -}; - -/* impl descriptor API */ -ComputedPropertyPrototype.set = function(obj, keyName, value) { - var cacheable = this._cacheable, - func = this.func, - meta = metaFor(obj, cacheable), - watched = meta.watching[keyName], - oldSuspended = this._suspended, - hadCachedValue = false, - cache = meta.cache, - cachedValue, ret; - - if (this._readOnly) { - throw new Error('Cannot Set: ' + keyName + ' on: ' + obj.toString() ); - } - - this._suspended = obj; - - try { - - if (cacheable && cache.hasOwnProperty(keyName)) { - cachedValue = cache[keyName]; - hadCachedValue = true; - } - - // Check if the CP has been wrapped - if (func.wrappedFunction) { func = func.wrappedFunction; } - - // For backwards-compatibility with computed properties - // that check for arguments.length === 2 to determine if - // they are being get or set, only pass the old cached - // value if the computed property opts into a third - // argument. - if (func.length === 3) { - ret = func.call(obj, keyName, value, cachedValue); - } else if (func.length === 2) { - ret = func.call(obj, keyName, value); - } else { - Ember.defineProperty(obj, keyName, null, cachedValue); - Ember.set(obj, keyName, value); - return; - } - - if (hadCachedValue && cachedValue === ret) { return; } - - if (watched) { Ember.propertyWillChange(obj, keyName); } - - if (hadCachedValue) { - delete cache[keyName]; - } - - if (cacheable) { - if (!watched && !hadCachedValue) { - addDependentKeys(this, obj, keyName, meta); - } - cache[keyName] = ret; - } - - if (watched) { Ember.propertyDidChange(obj, keyName); } - } finally { - this._suspended = oldSuspended; - } - return ret; -}; - -/* called when property is defined */ -ComputedPropertyPrototype.setup = function(obj, keyName) { - var meta = obj[META_KEY]; - if (meta && meta.watching[keyName]) { - addDependentKeys(this, obj, keyName, metaFor(obj)); - } -}; - -/* called before property is overridden */ -ComputedPropertyPrototype.teardown = function(obj, keyName) { - var meta = metaFor(obj); - - if (meta.watching[keyName] || keyName in meta.cache) { - removeDependentKeys(this, obj, keyName, meta); - } - - if (this._cacheable) { delete meta.cache[keyName]; } - - return null; // no value to restore -}; - - -/** - This helper returns a new property descriptor that wraps the passed - computed property function. You can use this helper to define properties - with mixins or via `Ember.defineProperty()`. - - The function you pass will be used to both get and set property values. - The function should accept two parameters, key and value. If value is not - undefined you should set the value first. In either case return the - current value of the property. - - @method computed - @for Ember - @param {Function} func The computed property function. - @return {Ember.ComputedProperty} property descriptor instance -*/ -Ember.computed = function(func) { - var args; - - if (arguments.length > 1) { - args = a_slice.call(arguments, 0, -1); - func = a_slice.call(arguments, -1)[0]; - } - - if ( typeof func !== "function" ) { - throw new Error("Computed Property declared without a property function"); - } - - var cp = new ComputedProperty(func); - - if (args) { - cp.property.apply(cp, args); - } - - return cp; -}; - -/** - Returns the cached value for a property, if one exists. - This can be useful for peeking at the value of a computed - property that is generated lazily, without accidentally causing - it to be created. - - @method cacheFor - @for Ember - @param {Object} obj the object whose property you want to check - @param {String} key the name of the property whose cached value you want - to return - @return {any} the cached value -*/ -Ember.cacheFor = function cacheFor(obj, key) { - var cache = metaFor(obj, false).cache; - - if (cache && key in cache) { - return cache[key]; - } -}; - -/** - @method computed.not - @for Ember - @param {String} dependentKey - @return {Ember.ComputedProperty} computed property which negate the original value for property -*/ -Ember.computed.not = function(dependentKey) { - return Ember.computed(dependentKey, function(key) { - return !get(this, dependentKey); - }); -}; - -/** - @method computed.none - @for Ember - @param {String} dependentKey -*/ -Ember.computed.none = function(dependentKey) { - return Ember.computed(dependentKey, function(key) { - var val = get(this, dependentKey); - return Ember.isNone(val); - }); -}; - -/** - @method computed.empty - @for Ember - @param {String} dependentKey -*/ -Ember.computed.empty = function(dependentKey) { - return Ember.computed(dependentKey, function(key) { - var val = get(this, dependentKey); - return Ember.isEmpty(val); - }); -}; - -/** - @method computed.bool - @for Ember - @param {String} dependentKey - @return {Ember.ComputedProperty} computed property which convert to boolean the original value for property -*/ -Ember.computed.bool = function(dependentKey) { - return Ember.computed(dependentKey, function(key) { - return !!get(this, dependentKey); - }); -}; - -/** - @method computed.alias - @for Ember - - @param {String} dependentKey -*/ -Ember.computed.alias = function(dependentKey) { - return Ember.computed(dependentKey, function(key, value){ - if (arguments.length > 1) { - set(this, dependentKey, value); - return value; - } else { - return get(this, dependentKey); - } - }); -}; - -})(); - - - -(function() { -/** -@module ember-metal -*/ - -var o_create = Ember.create, - metaFor = Ember.meta, - META_KEY = Ember.META_KEY; - -/* - The event system uses a series of nested hashes to store listeners on an - object. When a listener is registered, or when an event arrives, these - hashes are consulted to determine which target and action pair to invoke. - - The hashes are stored in the object's meta hash, and look like this: - - // Object's meta hash - { - listeners: { // variable name: `listenerSet` - "foo:changed": [ // variable name: `actions` - [target, method, onceFlag, suspendedFlag] - ] - } - } - -*/ - -function indexOf(array, target, method) { - var index = -1; - for (var i = 0, l = array.length; i < l; i++) { - if (target === array[i][0] && method === array[i][1]) { index = i; break; } - } - return index; -} - -function actionsFor(obj, eventName) { - var meta = metaFor(obj, true), - actions; - - if (!meta.listeners) { meta.listeners = {}; } - - if (!meta.hasOwnProperty('listeners')) { - // setup inherited copy of the listeners object - meta.listeners = o_create(meta.listeners); - } - - actions = meta.listeners[eventName]; - - // if there are actions, but the eventName doesn't exist in our listeners, then copy them from the prototype - if (actions && !meta.listeners.hasOwnProperty(eventName)) { - actions = meta.listeners[eventName] = meta.listeners[eventName].slice(); - } else if (!actions) { - actions = meta.listeners[eventName] = []; - } - - return actions; -} - -function actionsUnion(obj, eventName, otherActions) { - var meta = obj[META_KEY], - actions = meta && meta.listeners && meta.listeners[eventName]; - - if (!actions) { return; } - for (var i = actions.length - 1; i >= 0; i--) { - var target = actions[i][0], - method = actions[i][1], - once = actions[i][2], - suspended = actions[i][3], - actionIndex = indexOf(otherActions, target, method); - - if (actionIndex === -1) { - otherActions.push([target, method, once, suspended]); - } - } -} - -function actionsDiff(obj, eventName, otherActions) { - var meta = obj[META_KEY], - actions = meta && meta.listeners && meta.listeners[eventName], - diffActions = []; - - if (!actions) { return; } - for (var i = actions.length - 1; i >= 0; i--) { - var target = actions[i][0], - method = actions[i][1], - once = actions[i][2], - suspended = actions[i][3], - actionIndex = indexOf(otherActions, target, method); - - if (actionIndex !== -1) { continue; } - - otherActions.push([target, method, once, suspended]); - diffActions.push([target, method, once, suspended]); - } - - return diffActions; -} - -/** - Add an event listener - - @method addListener - @for Ember - @param obj - @param {String} eventName - @param {Object|Function} targetOrMethod A target object or a function - @param {Function|String} method A function or the name of a function to be called on `target` - @param {Boolean} once A flag whether a function should only be called once -*/ -function addListener(obj, eventName, target, method, once) { - Ember.assert("You must pass at least an object and event name to Ember.addListener", !!obj && !!eventName); - - if (!method && 'function' === typeof target) { - method = target; - target = null; - } - - var actions = actionsFor(obj, eventName), - actionIndex = indexOf(actions, target, method); - - if (actionIndex !== -1) { return; } - - actions.push([target, method, once, undefined]); - - if ('function' === typeof obj.didAddListener) { - obj.didAddListener(eventName, target, method); - } -} - -/** - Remove an event listener - - Arguments should match those passed to {{#crossLink "Ember/addListener"}}{{/crossLink}} - - @method removeListener - @for Ember - @param obj - @param {String} eventName - @param {Object|Function} targetOrMethod A target object or a function - @param {Function|String} method A function or the name of a function to be called on `target` -*/ -function removeListener(obj, eventName, target, method) { - Ember.assert("You must pass at least an object and event name to Ember.removeListener", !!obj && !!eventName); - - if (!method && 'function' === typeof target) { - method = target; - target = null; - } - - function _removeListener(target, method, once) { - var actions = actionsFor(obj, eventName), - actionIndex = indexOf(actions, target, method); - - // action doesn't exist, give up silently - if (actionIndex === -1) { return; } - - actions.splice(actionIndex, 1); - - if ('function' === typeof obj.didRemoveListener) { - obj.didRemoveListener(eventName, target, method); - } - } - - if (method) { - _removeListener(target, method); - } else { - var meta = obj[META_KEY], - actions = meta && meta.listeners && meta.listeners[eventName]; - - if (!actions) { return; } - for (var i = actions.length - 1; i >= 0; i--) { - _removeListener(actions[i][0], actions[i][1]); - } - } -} - -/** - @private - - Suspend listener during callback. - - This should only be used by the target of the event listener - when it is taking an action that would cause the event, e.g. - an object might suspend its property change listener while it is - setting that property. - - @method suspendListener - @for Ember - @param obj - @param {String} eventName - @param {Object|Function} targetOrMethod A target object or a function - @param {Function|String} method A function or the name of a function to be called on `target` - @param {Function} callback -*/ -function suspendListener(obj, eventName, target, method, callback) { - if (!method && 'function' === typeof target) { - method = target; - target = null; - } - - var actions = actionsFor(obj, eventName), - actionIndex = indexOf(actions, target, method), - action; - - if (actionIndex !== -1) { - action = actions[actionIndex].slice(); // copy it, otherwise we're modifying a shared object - action[3] = true; // mark the action as suspended - actions[actionIndex] = action; // replace the shared object with our copy - } - - function tryable() { return callback.call(target); } - function finalizer() { if (action) { action[3] = undefined; } } - - return Ember.tryFinally(tryable, finalizer); -} - -/** - @private - - Suspend listener during callback. - - This should only be used by the target of the event listener - when it is taking an action that would cause the event, e.g. - an object might suspend its property change listener while it is - setting that property. - - @method suspendListener - @for Ember - @param obj - @param {Array} eventName Array of event names - @param {Object|Function} targetOrMethod A target object or a function - @param {Function|String} method A function or the name of a function to be called on `target` - @param {Function} callback -*/ -function suspendListeners(obj, eventNames, target, method, callback) { - if (!method && 'function' === typeof target) { - method = target; - target = null; - } - - var suspendedActions = [], - eventName, actions, action, i, l; - - for (i=0, l=eventNames.length; i= 0; i--) { // looping in reverse for once listeners - if (!actions[i] || actions[i][3] === true) { continue; } - - var target = actions[i][0], - method = actions[i][1], - once = actions[i][2]; - - if (once) { removeListener(obj, eventName, target, method); } - if (!target) { target = obj; } - if ('string' === typeof method) { method = target[method]; } - if (params) { - method.apply(target, params); - } else { - method.call(target); - } - } - return true; -} - -/** - @private - @method hasListeners - @for Ember - @param obj - @param {String} eventName -*/ -function hasListeners(obj, eventName) { - var meta = obj[META_KEY], - actions = meta && meta.listeners && meta.listeners[eventName]; - - return !!(actions && actions.length); -} - -/** - @private - @method listenersFor - @for Ember - @param obj - @param {String} eventName -*/ -function listenersFor(obj, eventName) { - var ret = []; - var meta = obj[META_KEY], - actions = meta && meta.listeners && meta.listeners[eventName]; - - if (!actions) { return ret; } - - for (var i = 0, l = actions.length; i < l; i++) { - var target = actions[i][0], - method = actions[i][1]; - ret.push([target, method]); - } - - return ret; -} - -Ember.addListener = addListener; -Ember.removeListener = removeListener; -Ember._suspendListener = suspendListener; -Ember._suspendListeners = suspendListeners; -Ember.sendEvent = sendEvent; -Ember.hasListeners = hasListeners; -Ember.watchedEvents = watchedEvents; -Ember.listenersFor = listenersFor; -Ember.listenersDiff = actionsDiff; -Ember.listenersUnion = actionsUnion; - -})(); - - - -(function() { -// Ember.Logger -// Ember.watch.flushPending -// Ember.beginPropertyChanges, Ember.endPropertyChanges -// Ember.guidFor, Ember.tryFinally - -/** -@module ember-metal -*/ - -// .......................................................... -// HELPERS -// - -var slice = [].slice, - forEach = Ember.ArrayPolyfills.forEach; - -// invokes passed params - normalizing so you can pass target/func, -// target/string or just func -function invoke(target, method, args, ignore) { - - if (method === undefined) { - method = target; - target = undefined; - } - - if ('string' === typeof method) { method = target[method]; } - if (args && ignore > 0) { - args = args.length > ignore ? slice.call(args, ignore) : null; - } - - return Ember.handleErrors(function() { - // IE8's Function.prototype.apply doesn't accept undefined/null arguments. - return method.apply(target || this, args || []); - }, this); -} - - -// .......................................................... -// RUNLOOP -// - -var timerMark; // used by timers... - -/** -Ember RunLoop (Private) - -@class RunLoop -@namespace Ember -@private -@constructor -*/ -var RunLoop = function(prev) { - this._prev = prev || null; - this.onceTimers = {}; -}; - -RunLoop.prototype = { - /** - @method end - */ - end: function() { - this.flush(); - }, - - /** - @method prev - */ - prev: function() { - return this._prev; - }, - - // .......................................................... - // Delayed Actions - // - - /** - @method schedule - @param {String} queueName - @param target - @param method - */ - schedule: function(queueName, target, method) { - var queues = this._queues, queue; - if (!queues) { queues = this._queues = {}; } - queue = queues[queueName]; - if (!queue) { queue = queues[queueName] = []; } - - var args = arguments.length > 3 ? slice.call(arguments, 3) : null; - queue.push({ target: target, method: method, args: args }); - return this; - }, - - /** - @method flush - @param {String} queueName - */ - flush: function(queueName) { - var queueNames, idx, len, queue, log; - - if (!this._queues) { return this; } // nothing to do - - function iter(item) { - invoke(item.target, item.method, item.args); - } - - function tryable() { - forEach.call(queue, iter); - } - - Ember.watch.flushPending(); // make sure all chained watchers are setup - - if (queueName) { - while (this._queues && (queue = this._queues[queueName])) { - this._queues[queueName] = null; - - // the sync phase is to allow property changes to propagate. don't - // invoke observers until that is finished. - if (queueName === 'sync') { - log = Ember.LOG_BINDINGS; - if (log) { Ember.Logger.log('Begin: Flush Sync Queue'); } - - Ember.beginPropertyChanges(); - - Ember.tryFinally(tryable, Ember.endPropertyChanges); - - if (log) { Ember.Logger.log('End: Flush Sync Queue'); } - - } else { - forEach.call(queue, iter); - } - } - - } else { - queueNames = Ember.run.queues; - len = queueNames.length; - idx = 0; - - outerloop: - while (idx < len) { - queueName = queueNames[idx]; - queue = this._queues && this._queues[queueName]; - delete this._queues[queueName]; - - if (queue) { - // the sync phase is to allow property changes to propagate. don't - // invoke observers until that is finished. - if (queueName === 'sync') { - log = Ember.LOG_BINDINGS; - if (log) { Ember.Logger.log('Begin: Flush Sync Queue'); } - - Ember.beginPropertyChanges(); - - Ember.tryFinally(tryable, Ember.endPropertyChanges); - - if (log) { Ember.Logger.log('End: Flush Sync Queue'); } - } else { - forEach.call(queue, iter); - } - } - - // Loop through prior queues - for (var i = 0; i <= idx; i++) { - if (this._queues && this._queues[queueNames[i]]) { - // Start over at the first queue with contents - idx = i; - continue outerloop; - } - } - - idx++; - } - } - - timerMark = null; - - return this; - } - -}; - -Ember.RunLoop = RunLoop; - -// .......................................................... -// Ember.run - this is ideally the only public API the dev sees -// - -/** - Runs the passed target and method inside of a RunLoop, ensuring any - deferred actions including bindings and views updates are flushed at the - end. - - Normally you should not need to invoke this method yourself. However if - you are implementing raw event handlers when interfacing with other - libraries or plugins, you should probably wrap all of your code inside this - call. - - ```javascript - Ember.run(function(){ - // code to be execute within a RunLoop - }); - ``` - - @class run - @namespace Ember - @static - @constructor - @param {Object} [target] target of method to call - @param {Function|String} method Method to invoke. - May be a function or a string. If you pass a string - then it will be looked up on the passed target. - @param {Object} [args*] Any additional arguments you wish to pass to the method. - @return {Object} return value from invoking the passed function. -*/ -Ember.run = function(target, method) { - var args = arguments; - run.begin(); - - function tryable() { - if (target || method) { - return invoke(target, method, args, 2); - } - } - - return Ember.tryFinally(tryable, run.end); -}; - -var run = Ember.run; - - -/** - Begins a new RunLoop. Any deferred actions invoked after the begin will - be buffered until you invoke a matching call to `Ember.run.end()`. This is - a lower-level way to use a RunLoop instead of using `Ember.run()`. - - ```javascript - Ember.run.begin(); - // code to be execute within a RunLoop - Ember.run.end(); - ``` - - @method begin - @return {void} -*/ -Ember.run.begin = function() { - run.currentRunLoop = new RunLoop(run.currentRunLoop); -}; - -/** - Ends a RunLoop. This must be called sometime after you call - `Ember.run.begin()` to flush any deferred actions. This is a lower-level way - to use a RunLoop instead of using `Ember.run()`. - - ```javascript - Ember.run.begin(); - // code to be execute within a RunLoop - Ember.run.end(); - ``` - - @method end - @return {void} -*/ -Ember.run.end = function() { - Ember.assert('must have a current run loop', run.currentRunLoop); - - function tryable() { run.currentRunLoop.end(); } - function finalizer() { run.currentRunLoop = run.currentRunLoop.prev(); } - - Ember.tryFinally(tryable, finalizer); -}; - -/** - Array of named queues. This array determines the order in which queues - are flushed at the end of the RunLoop. You can define your own queues by - simply adding the queue name to this array. Normally you should not need - to inspect or modify this property. - - @property queues - @type Array - @default ['sync', 'actions', 'destroy'] -*/ -Ember.run.queues = ['sync', 'actions', 'destroy']; - -/** - Adds the passed target/method and any optional arguments to the named - queue to be executed at the end of the RunLoop. If you have not already - started a RunLoop when calling this method one will be started for you - automatically. - - At the end of a RunLoop, any methods scheduled in this way will be invoked. - Methods will be invoked in an order matching the named queues defined in - the `run.queues` property. - - ```javascript - Ember.run.schedule('sync', this, function(){ - // this will be executed in the first RunLoop queue, when bindings are synced - console.log("scheduled on sync queue"); - }); - - Ember.run.schedule('actions', this, function(){ - // this will be executed in the 'actions' queue, after bindings have synced. - console.log("scheduled on actions queue"); - }); - - // Note the functions will be run in order based on the run queues order. Output would be: - // scheduled on sync queue - // scheduled on actions queue - ``` - - @method schedule - @param {String} queue The name of the queue to schedule against. - Default queues are 'sync' and 'actions' - @param {Object} [target] target object to use as the context when invoking a method. - @param {String|Function} method The method to invoke. If you pass a string it - will be resolved on the target object at the time the scheduled item is - invoked allowing you to change the target function. - @param {Object} [arguments*] Optional arguments to be passed to the queued method. - @return {void} -*/ -Ember.run.schedule = function(queue, target, method) { - var loop = run.autorun(); - loop.schedule.apply(loop, arguments); -}; - -var scheduledAutorun; -function autorun() { - scheduledAutorun = null; - if (run.currentRunLoop) { run.end(); } -} - -// Used by global test teardown -Ember.run.hasScheduledTimers = function() { - return !!(scheduledAutorun || scheduledLater); -}; - -// Used by global test teardown -Ember.run.cancelTimers = function () { - if (scheduledAutorun) { - clearTimeout(scheduledAutorun); - scheduledAutorun = null; - } - if (scheduledLater) { - clearTimeout(scheduledLater); - scheduledLater = null; - } - timers = {}; -}; - -/** - Begins a new RunLoop if necessary and schedules a timer to flush the - RunLoop at a later time. This method is used by parts of Ember to - ensure the RunLoop always finishes. You normally do not need to call this - method directly. Instead use `Ember.run()` - - @method autorun - @example - Ember.run.autorun(); - @return {Ember.RunLoop} the new current RunLoop -*/ -Ember.run.autorun = function() { - if (!run.currentRunLoop) { - Ember.assert("You have turned on testing mode, which disabled the run-loop's autorun. You will need to wrap any code with asynchronous side-effects in an Ember.run", !Ember.testing); - - run.begin(); - - if (!scheduledAutorun) { - scheduledAutorun = setTimeout(autorun, 1); - } - } - - return run.currentRunLoop; -}; - -/** - Immediately flushes any events scheduled in the 'sync' queue. Bindings - use this queue so this method is a useful way to immediately force all - bindings in the application to sync. - - You should call this method anytime you need any changed state to propagate - throughout the app immediately without repainting the UI (which happens - in the later 'render' queue added by the `ember-views` package). - - ```javascript - Ember.run.sync(); - ``` - - @method sync - @return {void} -*/ -Ember.run.sync = function() { - run.autorun(); - run.currentRunLoop.flush('sync'); -}; - -// .......................................................... -// TIMERS -// - -var timers = {}; // active timers... - -var scheduledLater, scheduledLaterExpires; -function invokeLaterTimers() { - scheduledLater = null; - run(function() { - var now = (+ new Date()), earliest = -1; - for (var key in timers) { - if (!timers.hasOwnProperty(key)) { continue; } - var timer = timers[key]; - if (timer && timer.expires) { - if (now >= timer.expires) { - delete timers[key]; - invoke(timer.target, timer.method, timer.args, 2); - } else { - if (earliest < 0 || (timer.expires < earliest)) { earliest = timer.expires; } - } - } - } - - // schedule next timeout to fire when the earliest timer expires - if (earliest > 0) { - scheduledLater = setTimeout(invokeLaterTimers, earliest - now); - scheduledLaterExpires = earliest; - } - }); -} - -/** - Invokes the passed target/method and optional arguments after a specified - period if time. The last parameter of this method must always be a number - of milliseconds. - - You should use this method whenever you need to run some action after a - period of time instead of using `setTimeout()`. This method will ensure that - items that expire during the same script execution cycle all execute - together, which is often more efficient than using a real setTimeout. - - ```javascript - Ember.run.later(myContext, function(){ - // code here will execute within a RunLoop in about 500ms with this == myContext - }, 500); - ``` - - @method later - @param {Object} [target] target of method to invoke - @param {Function|String} method The method to invoke. - If you pass a string it will be resolved on the - target at the time the method is invoked. - @param {Object} [args*] Optional arguments to pass to the timeout. - @param {Number} wait Number of milliseconds to wait. - @return {String} a string you can use to cancel the timer in - {{#crossLink "Ember/run.cancel"}}{{/crossLink}} later. -*/ -Ember.run.later = function(target, method) { - var args, expires, timer, guid, wait; - - // setTimeout compatibility... - if (arguments.length===2 && 'function' === typeof target) { - wait = method; - method = target; - target = undefined; - args = [target, method]; - } else { - args = slice.call(arguments); - wait = args.pop(); - } - - expires = (+ new Date()) + wait; - timer = { target: target, method: method, expires: expires, args: args }; - guid = Ember.guidFor(timer); - timers[guid] = timer; - - if(scheduledLater && expires < scheduledLaterExpires) { - // Cancel later timer (then reschedule earlier timer below) - clearTimeout(scheduledLater); - scheduledLater = null; - } - - if (!scheduledLater) { - // Schedule later timers to be run. - scheduledLater = setTimeout(invokeLaterTimers, wait); - scheduledLaterExpires = expires; - } - - return guid; -}; - -function invokeOnceTimer(guid, onceTimers) { - if (onceTimers[this.tguid]) { delete onceTimers[this.tguid][this.mguid]; } - if (timers[guid]) { invoke(this.target, this.method, this.args); } - delete timers[guid]; -} - -function scheduleOnce(queue, target, method, args) { - var tguid = Ember.guidFor(target), - mguid = Ember.guidFor(method), - onceTimers = run.autorun().onceTimers, - guid = onceTimers[tguid] && onceTimers[tguid][mguid], - timer; - - if (guid && timers[guid]) { - timers[guid].args = args; // replace args - } else { - timer = { - target: target, - method: method, - args: args, - tguid: tguid, - mguid: mguid - }; - - guid = Ember.guidFor(timer); - timers[guid] = timer; - if (!onceTimers[tguid]) { onceTimers[tguid] = {}; } - onceTimers[tguid][mguid] = guid; // so it isn't scheduled more than once - - run.schedule(queue, timer, invokeOnceTimer, guid, onceTimers); - } - - return guid; -} - -/** - Schedules an item to run one time during the current RunLoop. Calling - this method with the same target/method combination will have no effect. - - Note that although you can pass optional arguments these will not be - considered when looking for duplicates. New arguments will replace previous - calls. - - ```javascript - Ember.run(function(){ - var doFoo = function() { foo(); } - Ember.run.once(myContext, doFoo); - Ember.run.once(myContext, doFoo); - // doFoo will only be executed once at the end of the RunLoop - }); - ``` - - Also note that passing an anonymous function to `Ember.run.once` will - not prevent additional calls with an identical anonymous function from - scheduling the items multiple times, e.g.: - - ```javascript - function scheduleIt() { - Ember.run.once(myContext, function() { console.log("Closure"); }); - } - scheduleIt(); - scheduleIt(); - // "Closure" will print twice, even though we're using `Ember.run.once`, - // because the function we pass to it is anonymous and won't match the - // previously scheduled operation. - ``` - - @method once - @param {Object} [target] target of method to invoke - @param {Function|String} method The method to invoke. - If you pass a string it will be resolved on the - target at the time the method is invoked. - @param {Object} [args*] Optional arguments to pass to the timeout. - @return {Object} timer -*/ -Ember.run.once = function(target, method) { - return scheduleOnce('actions', target, method, slice.call(arguments, 2)); -}; - -Ember.run.scheduleOnce = function(queue, target, method, args) { - return scheduleOnce(queue, target, method, slice.call(arguments, 3)); -}; - -/** - Schedules an item to run from within a separate run loop, after - control has been returned to the system. This is equivalent to calling - `Ember.run.later` with a wait time of 1ms. - - ```javascript - Ember.run.next(myContext, function(){ - // code to be executed in the next run loop, which will be scheduled after the current one - }); - ``` - - Multiple operations scheduled with `Ember.run.next` will coalesce - into the same later run loop, along with any other operations - scheduled by `Ember.run.later` that expire right around the same - time that `Ember.run.next` operations will fire. - - Note that there are often alternatives to using `Ember.run.next`. - For instance, if you'd like to schedule an operation to happen - after all DOM element operations have completed within the current - run loop, you can make use of the `afterRender` run loop queue (added - by the `ember-views` package, along with the preceding `render` queue - where all the DOM element operations happen). Example: - - ```javascript - App.MyCollectionView = Ember.CollectionView.extend({ - didInsertElement: function() { - Ember.run.scheduleOnce('afterRender', this, 'processChildElements'); - }, - processChildElements: function() { - // ... do something with collectionView's child view - // elements after they've finished rendering, which - // can't be done within the CollectionView's - // `didInsertElement` hook because that gets run - // before the child elements have been added to the DOM. - } - }); - ``` - - One benefit of the above approach compared to using `Ember.run.next` is - that you will be able to perform DOM/CSS operations before unprocessed - elements are rendered to the screen, which may prevent flickering or - other artifacts caused by delaying processing until after rendering. - - The other major benefit to the above approach is that `Ember.run.next` - introduces an element of non-determinism, which can make things much - harder to test, due to its reliance on `setTimeout`; it's much harder - to guarantee the order of scheduled operations when they are scheduled - outside of the current run loop, i.e. with `Ember.run.next`. - - @method next - @param {Object} [target] target of method to invoke - @param {Function|String} method The method to invoke. - If you pass a string it will be resolved on the - target at the time the method is invoked. - @param {Object} [args*] Optional arguments to pass to the timeout. - @return {Object} timer -*/ -Ember.run.next = function() { - var args = slice.call(arguments); - args.push(1); // 1 millisecond wait - return run.later.apply(this, args); -}; - -/** - Cancels a scheduled item. Must be a value returned by `Ember.run.later()`, - `Ember.run.once()`, or `Ember.run.next()`. - - ```javascript - var runNext = Ember.run.next(myContext, function(){ - // will not be executed - }); - Ember.run.cancel(runNext); - - var runLater = Ember.run.later(myContext, function(){ - // will not be executed - }, 500); - Ember.run.cancel(runLater); - - var runOnce = Ember.run.once(myContext, function(){ - // will not be executed - }); - Ember.run.cancel(runOnce); - ``` - - @method cancel - @param {Object} timer Timer object to cancel - @return {void} -*/ -Ember.run.cancel = function(timer) { - delete timers[timer]; -}; - -})(); - - - -(function() { -// Ember.Logger -// get, set, trySet -// guidFor, isArray, meta -// addObserver, removeObserver -// Ember.run.schedule -/** -@module ember-metal -*/ - -// .......................................................... -// CONSTANTS -// - -/** - Debug parameter you can turn on. This will log all bindings that fire to - the console. This should be disabled in production code. Note that you - can also enable this from the console or temporarily. - - @property LOG_BINDINGS - @for Ember - @type Boolean - @default false -*/ -Ember.LOG_BINDINGS = false || !!Ember.ENV.LOG_BINDINGS; - -var get = Ember.get, - set = Ember.set, - guidFor = Ember.guidFor, - isGlobalPath = Ember.isGlobalPath; - - -function getWithGlobals(obj, path) { - return get(isGlobalPath(path) ? Ember.lookup : obj, path); -} - -// .......................................................... -// BINDING -// - -var Binding = function(toPath, fromPath) { - this._direction = 'fwd'; - this._from = fromPath; - this._to = toPath; - this._directionMap = Ember.Map.create(); -}; - -/** -@class Binding -@namespace Ember -*/ - -Binding.prototype = { - /** - This copies the Binding so it can be connected to another object. - - @method copy - @return {Ember.Binding} - */ - copy: function () { - var copy = new Binding(this._to, this._from); - if (this._oneWay) { copy._oneWay = true; } - return copy; - }, - - // .......................................................... - // CONFIG - // - - /** - This will set `from` property path to the specified value. It will not - attempt to resolve this property path to an actual object until you - connect the binding. - - The binding will search for the property path starting at the root object - you pass when you `connect()` the binding. It follows the same rules as - `get()` - see that method for more information. - - @method from - @param {String} path the property path to connect to - @return {Ember.Binding} `this` - */ - from: function(path) { - this._from = path; - return this; - }, - - /** - This will set the `to` property path to the specified value. It will not - attempt to resolve this property path to an actual object until you - connect the binding. - - The binding will search for the property path starting at the root object - you pass when you `connect()` the binding. It follows the same rules as - `get()` - see that method for more information. - - @method to - @param {String|Tuple} path A property path or tuple - @return {Ember.Binding} `this` - */ - to: function(path) { - this._to = path; - return this; - }, - - /** - Configures the binding as one way. A one-way binding will relay changes - on the `from` side to the `to` side, but not the other way around. This - means that if you change the `to` side directly, the `from` side may have - a different value. - - @method oneWay - @return {Ember.Binding} `this` - */ - oneWay: function() { - this._oneWay = true; - return this; - }, - - /** - @method toString - @return {String} string representation of binding - */ - toString: function() { - var oneWay = this._oneWay ? '[oneWay]' : ''; - return "Ember.Binding<" + guidFor(this) + ">(" + this._from + " -> " + this._to + ")" + oneWay; - }, - - // .......................................................... - // CONNECT AND SYNC - // - - /** - Attempts to connect this binding instance so that it can receive and relay - changes. This method will raise an exception if you have not set the - from/to properties yet. - - @method connect - @param {Object} obj The root object for this binding. - @return {Ember.Binding} `this` - */ - connect: function(obj) { - Ember.assert('Must pass a valid object to Ember.Binding.connect()', !!obj); - - var fromPath = this._from, toPath = this._to; - Ember.trySet(obj, toPath, getWithGlobals(obj, fromPath)); - - // add an observer on the object to be notified when the binding should be updated - Ember.addObserver(obj, fromPath, this, this.fromDidChange); - - // if the binding is a two-way binding, also set up an observer on the target - if (!this._oneWay) { Ember.addObserver(obj, toPath, this, this.toDidChange); } - - this._readyToSync = true; - - return this; - }, - - /** - Disconnects the binding instance. Changes will no longer be relayed. You - will not usually need to call this method. - - @method disconnect - @param {Object} obj The root object you passed when connecting the binding. - @return {Ember.Binding} `this` - */ - disconnect: function(obj) { - Ember.assert('Must pass a valid object to Ember.Binding.disconnect()', !!obj); - - var twoWay = !this._oneWay; - - // remove an observer on the object so we're no longer notified of - // changes that should update bindings. - Ember.removeObserver(obj, this._from, this, this.fromDidChange); - - // if the binding is two-way, remove the observer from the target as well - if (twoWay) { Ember.removeObserver(obj, this._to, this, this.toDidChange); } - - this._readyToSync = false; // disable scheduled syncs... - return this; - }, - - // .......................................................... - // PRIVATE - // - - /* called when the from side changes */ - fromDidChange: function(target) { - this._scheduleSync(target, 'fwd'); - }, - - /* called when the to side changes */ - toDidChange: function(target) { - this._scheduleSync(target, 'back'); - }, - - _scheduleSync: function(obj, dir) { - var directionMap = this._directionMap; - var existingDir = directionMap.get(obj); - - // if we haven't scheduled the binding yet, schedule it - if (!existingDir) { - Ember.run.schedule('sync', this, this._sync, obj); - directionMap.set(obj, dir); - } - - // If both a 'back' and 'fwd' sync have been scheduled on the same object, - // default to a 'fwd' sync so that it remains deterministic. - if (existingDir === 'back' && dir === 'fwd') { - directionMap.set(obj, 'fwd'); - } - }, - - _sync: function(obj) { - var log = Ember.LOG_BINDINGS; - - // don't synchronize destroyed objects or disconnected bindings - if (obj.isDestroyed || !this._readyToSync) { return; } - - // get the direction of the binding for the object we are - // synchronizing from - var directionMap = this._directionMap; - var direction = directionMap.get(obj); - - var fromPath = this._from, toPath = this._to; - - directionMap.remove(obj); - - // if we're synchronizing from the remote object... - if (direction === 'fwd') { - var fromValue = getWithGlobals(obj, this._from); - if (log) { - Ember.Logger.log(' ', this.toString(), '->', fromValue, obj); - } - if (this._oneWay) { - Ember.trySet(obj, toPath, fromValue); - } else { - Ember._suspendObserver(obj, toPath, this, this.toDidChange, function () { - Ember.trySet(obj, toPath, fromValue); - }); - } - // if we're synchronizing *to* the remote object - } else if (direction === 'back') { - var toValue = get(obj, this._to); - if (log) { - Ember.Logger.log(' ', this.toString(), '<-', toValue, obj); - } - Ember._suspendObserver(obj, fromPath, this, this.fromDidChange, function () { - Ember.trySet(Ember.isGlobalPath(fromPath) ? Ember.lookup : obj, fromPath, toValue); - }); - } - } - -}; - -function mixinProperties(to, from) { - for (var key in from) { - if (from.hasOwnProperty(key)) { - to[key] = from[key]; - } - } -} - -mixinProperties(Binding, { - - /** - See {{#crossLink "Ember.Binding/from"}}{{/crossLink}} - - @method from - @static - */ - from: function() { - var C = this, binding = new C(); - return binding.from.apply(binding, arguments); - }, - - /** - See {{#crossLink "Ember.Binding/to"}}{{/crossLink}} - - @method to - @static - */ - to: function() { - var C = this, binding = new C(); - return binding.to.apply(binding, arguments); - }, - - /** - Creates a new Binding instance and makes it apply in a single direction. - A one-way binding will relay changes on the `from` side object (supplied - as the `from` argument) the `to` side, but not the other way around. - This means that if you change the "to" side directly, the "from" side may have - a different value. - - See {{#crossLink "Binding/oneWay"}}{{/crossLink}} - - @method oneWay - @param {String} from from path. - @param {Boolean} [flag] (Optional) passing nothing here will make the - binding `oneWay`. You can instead pass `false` to disable `oneWay`, making the - binding two way again. - */ - oneWay: function(from, flag) { - var C = this, binding = new C(null, from); - return binding.oneWay(flag); - } - -}); - -/** - An `Ember.Binding` connects the properties of two objects so that whenever - the value of one property changes, the other property will be changed also. - - ## Automatic Creation of Bindings with `/^*Binding/`-named Properties - - You do not usually create Binding objects directly but instead describe - bindings in your class or object definition using automatic binding - detection. - - Properties ending in a `Binding` suffix will be converted to `Ember.Binding` - instances. The value of this property should be a string representing a path - to another object or a custom binding instanced created using Binding helpers - (see "Customizing Your Bindings"): - - ``` - valueBinding: "MyApp.someController.title" - ``` - - This will create a binding from `MyApp.someController.title` to the `value` - property of your object instance automatically. Now the two values will be - kept in sync. - - ## One Way Bindings - - One especially useful binding customization you can use is the `oneWay()` - helper. This helper tells Ember that you are only interested in - receiving changes on the object you are binding from. For example, if you - are binding to a preference and you want to be notified if the preference - has changed, but your object will not be changing the preference itself, you - could do: - - ``` - bigTitlesBinding: Ember.Binding.oneWay("MyApp.preferencesController.bigTitles") - ``` - - This way if the value of `MyApp.preferencesController.bigTitles` changes the - `bigTitles` property of your object will change also. However, if you - change the value of your `bigTitles` property, it will not update the - `preferencesController`. - - One way bindings are almost twice as fast to setup and twice as fast to - execute because the binding only has to worry about changes to one side. - - You should consider using one way bindings anytime you have an object that - may be created frequently and you do not intend to change a property; only - to monitor it for changes. (such as in the example above). - - ## Adding Bindings Manually - - All of the examples above show you how to configure a custom binding, but the - result of these customizations will be a binding template, not a fully active - Binding instance. The binding will actually become active only when you - instantiate the object the binding belongs to. It is useful however, to - understand what actually happens when the binding is activated. - - For a binding to function it must have at least a `from` property and a `to` - property. The `from` property path points to the object/key that you want to - bind from while the `to` path points to the object/key you want to bind to. - - When you define a custom binding, you are usually describing the property - you want to bind from (such as `MyApp.someController.value` in the examples - above). When your object is created, it will automatically assign the value - you want to bind `to` based on the name of your binding key. In the - examples above, during init, Ember objects will effectively call - something like this on your binding: - - ```javascript - binding = Ember.Binding.from(this.valueBinding).to("value"); - ``` - - This creates a new binding instance based on the template you provide, and - sets the to path to the `value` property of the new object. Now that the - binding is fully configured with a `from` and a `to`, it simply needs to be - connected to become active. This is done through the `connect()` method: - - ```javascript - binding.connect(this); - ``` - - Note that when you connect a binding you pass the object you want it to be - connected to. This object will be used as the root for both the from and - to side of the binding when inspecting relative paths. This allows the - binding to be automatically inherited by subclassed objects as well. - - Now that the binding is connected, it will observe both the from and to side - and relay changes. - - If you ever needed to do so (you almost never will, but it is useful to - understand this anyway), you could manually create an active binding by - using the `Ember.bind()` helper method. (This is the same method used by - to setup your bindings on objects): - - ```javascript - Ember.bind(MyApp.anotherObject, "value", "MyApp.someController.value"); - ``` - - Both of these code fragments have the same effect as doing the most friendly - form of binding creation like so: - - ```javascript - MyApp.anotherObject = Ember.Object.create({ - valueBinding: "MyApp.someController.value", - - // OTHER CODE FOR THIS OBJECT... - }); - ``` - - Ember's built in binding creation method makes it easy to automatically - create bindings for you. You should always use the highest-level APIs - available, even if you understand how it works underneath. - - @class Binding - @namespace Ember - @since Ember 0.9 -*/ -Ember.Binding = Binding; - - -/** - Global helper method to create a new binding. Just pass the root object - along with a `to` and `from` path to create and connect the binding. - - @method bind - @for Ember - @param {Object} obj The root object of the transform. - @param {String} to The path to the 'to' side of the binding. - Must be relative to obj. - @param {String} from The path to the 'from' side of the binding. - Must be relative to obj or a global path. - @return {Ember.Binding} binding instance -*/ -Ember.bind = function(obj, to, from) { - return new Ember.Binding(to, from).connect(obj); -}; - -/** - @method oneWay - @for Ember - @param {Object} obj The root object of the transform. - @param {String} to The path to the 'to' side of the binding. - Must be relative to obj. - @param {String} from The path to the 'from' side of the binding. - Must be relative to obj or a global path. - @return {Ember.Binding} binding instance -*/ -Ember.oneWay = function(obj, to, from) { - return new Ember.Binding(to, from).oneWay().connect(obj); -}; - -})(); - - - -(function() { -/** -@module ember-metal -*/ - -var Mixin, REQUIRED, Alias, - a_map = Ember.ArrayPolyfills.map, - a_indexOf = Ember.ArrayPolyfills.indexOf, - a_forEach = Ember.ArrayPolyfills.forEach, - a_slice = [].slice, - o_create = Ember.create, - defineProperty = Ember.defineProperty, - guidFor = Ember.guidFor; - -function mixinsMeta(obj) { - var m = Ember.meta(obj, true), ret = m.mixins; - if (!ret) { - ret = m.mixins = {}; - } else if (!m.hasOwnProperty('mixins')) { - ret = m.mixins = o_create(ret); - } - return ret; -} - -function initMixin(mixin, args) { - if (args && args.length > 0) { - mixin.mixins = a_map.call(args, function(x) { - if (x instanceof Mixin) { return x; } - - // Note: Manually setup a primitive mixin here. This is the only - // way to actually get a primitive mixin. This way normal creation - // of mixins will give you combined mixins... - var mixin = new Mixin(); - mixin.properties = x; - return mixin; - }); - } - return mixin; -} - -function isMethod(obj) { - return 'function' === typeof obj && - obj.isMethod !== false && - obj !== Boolean && obj !== Object && obj !== Number && obj !== Array && obj !== Date && obj !== String; -} - -var CONTINUE = {}; - -function mixinProperties(mixinsMeta, mixin) { - var guid; - - if (mixin instanceof Mixin) { - guid = guidFor(mixin); - if (mixinsMeta[guid]) { return CONTINUE; } - mixinsMeta[guid] = mixin; - return mixin.properties; - } else { - return mixin; // apply anonymous mixin properties - } -} - -function concatenatedProperties(props, values, base) { - var concats; - - // reset before adding each new mixin to pickup concats from previous - concats = values.concatenatedProperties || base.concatenatedProperties; - if (props.concatenatedProperties) { - concats = concats ? concats.concat(props.concatenatedProperties) : props.concatenatedProperties; - } - - return concats; -} - -function giveDescriptorSuper(meta, key, property, values, descs) { - var superProperty; - - // Computed properties override methods, and do not call super to them - if (values[key] === undefined) { - // Find the original descriptor in a parent mixin - superProperty = descs[key]; - } - - // If we didn't find the original descriptor in a parent mixin, find - // it on the original object. - superProperty = superProperty || meta.descs[key]; - - if (!superProperty || !(superProperty instanceof Ember.ComputedProperty)) { - return property; - } - - // Since multiple mixins may inherit from the same parent, we need - // to clone the computed property so that other mixins do not receive - // the wrapped version. - property = o_create(property); - property.func = Ember.wrap(property.func, superProperty.func); - - return property; -} - -function giveMethodSuper(obj, key, method, values, descs) { - var superMethod; - - // Methods overwrite computed properties, and do not call super to them. - if (descs[key] === undefined) { - // Find the original method in a parent mixin - superMethod = values[key]; - } - - // If we didn't find the original value in a parent mixin, find it in - // the original object - superMethod = superMethod || obj[key]; - - // Only wrap the new method if the original method was a function - if ('function' !== typeof superMethod) { - return method; - } - - return Ember.wrap(method, superMethod); -} - -function applyConcatenatedProperties(obj, key, value, values) { - var baseValue = values[key] || obj[key]; - - if (baseValue) { - if ('function' === typeof baseValue.concat) { - return baseValue.concat(value); - } else { - return Ember.makeArray(baseValue).concat(value); - } - } else { - return Ember.makeArray(value); - } -} - -function addNormalizedProperty(base, key, value, meta, descs, values, concats) { - if (value instanceof Ember.Descriptor) { - if (value === REQUIRED && descs[key]) { return CONTINUE; } - - // Wrap descriptor function to implement - // _super() if needed - if (value.func) { - value = giveDescriptorSuper(meta, key, value, values, descs); - } - - descs[key] = value; - values[key] = undefined; - } else { - // impl super if needed... - if (isMethod(value)) { - value = giveMethodSuper(base, key, value, values, descs); - } else if ((concats && a_indexOf.call(concats, key) >= 0) || key === 'concatenatedProperties') { - value = applyConcatenatedProperties(base, key, value, values); - } - - descs[key] = undefined; - values[key] = value; - } -} - -function mergeMixins(mixins, m, descs, values, base) { - var mixin, props, key, concats, meta; - - function removeKeys(keyName) { - delete descs[keyName]; - delete values[keyName]; - } - - for(var i=0, l=mixins.length; i= 0) { - if (_detect(mixins[loc], targetMixin, seen)) { return true; } - } - return false; -} - -/** - @method detect - @param obj - @return {Boolean} -*/ -MixinPrototype.detect = function(obj) { - if (!obj) { return false; } - if (obj instanceof Mixin) { return _detect(obj, this, {}); } - var mixins = Ember.meta(obj, false).mixins; - if (mixins) { - return !!mixins[guidFor(this)]; - } - return false; -}; - -MixinPrototype.without = function() { - var ret = new Mixin(this); - ret._without = a_slice.call(arguments); - return ret; -}; - -function _keys(ret, mixin, seen) { - if (seen[guidFor(mixin)]) { return; } - seen[guidFor(mixin)] = true; - - if (mixin.properties) { - var props = mixin.properties; - for (var key in props) { - if (props.hasOwnProperty(key)) { ret[key] = true; } - } - } else if (mixin.mixins) { - a_forEach.call(mixin.mixins, function(x) { _keys(ret, x, seen); }); - } -} - -MixinPrototype.keys = function() { - var keys = {}, seen = {}, ret = []; - _keys(keys, this, seen); - for(var key in keys) { - if (keys.hasOwnProperty(key)) { ret.push(key); } - } - return ret; -}; - -// returns the mixins currently applied to the specified object -// TODO: Make Ember.mixin -Mixin.mixins = function(obj) { - var mixins = Ember.meta(obj, false).mixins, ret = []; - - if (!mixins) { return ret; } - - for (var key in mixins) { - var mixin = mixins[key]; - - // skip primitive mixins since these are always anonymous - if (!mixin.properties) { ret.push(mixin); } - } - - return ret; -}; - -REQUIRED = new Ember.Descriptor(); -REQUIRED.toString = function() { return '(Required Property)'; }; - -/** - Denotes a required property for a mixin - - @method required - @for Ember -*/ -Ember.required = function() { - return REQUIRED; -}; - -Alias = function(methodName) { - this.methodName = methodName; -}; -Alias.prototype = new Ember.Descriptor(); - -/** - Makes a property or method available via an additional name. - - ```javascript - App.PaintSample = Ember.Object.extend({ - color: 'red', - colour: Ember.alias('color'), - name: function(){ - return "Zed"; - }, - moniker: Ember.alias("name") - }); - - var paintSample = App.PaintSample.create() - paintSample.get('colour'); // 'red' - paintSample.moniker(); // 'Zed' - ``` - - @method alias - @for Ember - @param {String} methodName name of the method or property to alias - @return {Ember.Descriptor} - @deprecated Use `Ember.aliasMethod` or `Ember.computed.alias` instead -*/ -Ember.alias = function(methodName) { - return new Alias(methodName); -}; - -Ember.deprecateFunc("Ember.alias is deprecated. Please use Ember.aliasMethod or Ember.computed.alias instead.", Ember.alias); - -/** - Makes a method available via an additional name. - - ```javascript - App.Person = Ember.Object.extend({ - name: function(){ - return 'Tomhuda Katzdale'; - }, - moniker: Ember.aliasMethod('name') - }); - - var goodGuy = App.Person.create() - ``` - - @method aliasMethod - @for Ember - @param {String} methodName name of the method to alias - @return {Ember.Descriptor} -*/ -Ember.aliasMethod = function(methodName) { - return new Alias(methodName); -}; - -// .......................................................... -// OBSERVER HELPER -// - -/** - @method observer - @for Ember - @param {Function} func - @param {String} propertyNames* - @return func -*/ -Ember.observer = function(func) { - var paths = a_slice.call(arguments, 1); - func.__ember_observes__ = paths; - return func; -}; - -// If observers ever become asynchronous, Ember.immediateObserver -// must remain synchronous. -/** - @method immediateObserver - @for Ember - @param {Function} func - @param {String} propertyNames* - @return func -*/ -Ember.immediateObserver = function() { - for (var i=0, l=arguments.length; i w. -*/ -Ember.compare = function compare(v, w) { - if (v === w) { return 0; } - - var type1 = Ember.typeOf(v); - var type2 = Ember.typeOf(w); - - var Comparable = Ember.Comparable; - if (Comparable) { - if (type1==='instance' && Comparable.detect(v.constructor)) { - return v.constructor.compare(v, w); - } - - if (type2 === 'instance' && Comparable.detect(w.constructor)) { - return 1-w.constructor.compare(w, v); - } - } - - // If we haven't yet generated a reverse-mapping of Ember.ORDER_DEFINITION, - // do so now. - var mapping = Ember.ORDER_DEFINITION_MAPPING; - if (!mapping) { - var order = Ember.ORDER_DEFINITION; - mapping = Ember.ORDER_DEFINITION_MAPPING = {}; - var idx, len; - for (idx = 0, len = order.length; idx < len; ++idx) { - mapping[order[idx]] = idx; - } - - // We no longer need Ember.ORDER_DEFINITION. - delete Ember.ORDER_DEFINITION; - } - - var type1Index = mapping[type1]; - var type2Index = mapping[type2]; - - if (type1Index < type2Index) { return -1; } - if (type1Index > type2Index) { return 1; } - - // types are equal - so we have to check values now - switch (type1) { - case 'boolean': - case 'number': - if (v < w) { return -1; } - if (v > w) { return 1; } - return 0; - - case 'string': - var comp = v.localeCompare(w); - if (comp < 0) { return -1; } - if (comp > 0) { return 1; } - return 0; - - case 'array': - var vLen = v.length; - var wLen = w.length; - var l = Math.min(vLen, wLen); - var r = 0; - var i = 0; - while (r === 0 && i < l) { - r = compare(v[i],w[i]); - i++; - } - if (r !== 0) { return r; } - - // all elements are equal now - // shorter array should be ordered first - if (vLen < wLen) { return -1; } - if (vLen > wLen) { return 1; } - // arrays are equal now - return 0; - - case 'instance': - if (Ember.Comparable && Ember.Comparable.detect(v)) { - return v.compare(v, w); - } - return 0; - - case 'date': - var vNum = v.getTime(); - var wNum = w.getTime(); - if (vNum < wNum) { return -1; } - if (vNum > wNum) { return 1; } - return 0; - - default: - return 0; - } -}; - -function _copy(obj, deep, seen, copies) { - var ret, loc, key; - - // primitive data types are immutable, just return them. - if ('object' !== typeof obj || obj===null) return obj; - - // avoid cyclical loops - if (deep && (loc=indexOf(seen, obj))>=0) return copies[loc]; - - Ember.assert('Cannot clone an Ember.Object that does not implement Ember.Copyable', !(obj instanceof Ember.Object) || (Ember.Copyable && Ember.Copyable.detect(obj))); - - // IMPORTANT: this specific test will detect a native array only. Any other - // object will need to implement Copyable. - if (Ember.typeOf(obj) === 'array') { - ret = obj.slice(); - if (deep) { - loc = ret.length; - while(--loc>=0) ret[loc] = _copy(ret[loc], deep, seen, copies); - } - } else if (Ember.Copyable && Ember.Copyable.detect(obj)) { - ret = obj.copy(deep, seen, copies); - } else { - ret = {}; - for(key in obj) { - if (!obj.hasOwnProperty(key)) continue; - - // Prevents browsers that don't respect non-enumerability from - // copying internal Ember properties - if (key.substring(0,2) === '__') continue; - - ret[key] = deep ? _copy(obj[key], deep, seen, copies) : obj[key]; - } - } - - if (deep) { - seen.push(obj); - copies.push(ret); - } - - return ret; -} - -/** - Creates a clone of the passed object. This function can take just about - any type of object and create a clone of it, including primitive values - (which are not actually cloned because they are immutable). - - If the passed object implements the `clone()` method, then this function - will simply call that method and return the result. - - @method copy - @for Ember - @param {Object} obj The object to clone - @param {Boolean} deep If true, a deep copy of the object is made - @return {Object} The cloned object -*/ -Ember.copy = function(obj, deep) { - // fast paths - if ('object' !== typeof obj || obj===null) return obj; // can't copy primitives - if (Ember.Copyable && Ember.Copyable.detect(obj)) return obj.copy(deep); - return _copy(obj, deep, deep ? [] : null, deep ? [] : null); -}; - -/** - Convenience method to inspect an object. This method will attempt to - convert the object into a useful string description. - - It is a pretty simple implementation. If you want something more robust, - use something like JSDump: https://github.com/NV/jsDump - - @method inspect - @for Ember - @param {Object} obj The object you want to inspect. - @return {String} A description of the object -*/ -Ember.inspect = function(obj) { - if (typeof obj !== 'object' || obj === null) { - return obj + ''; - } - - var v, ret = []; - for(var key in obj) { - if (obj.hasOwnProperty(key)) { - v = obj[key]; - if (v === 'toString') { continue; } // ignore useless items - if (Ember.typeOf(v) === 'function') { v = "function() { ... }"; } - ret.push(key + ": " + v); - } - } - return "{" + ret.join(", ") + "}"; -}; - -/** - Compares two objects, returning true if they are logically equal. This is - a deeper comparison than a simple triple equal. For sets it will compare the - internal objects. For any other object that implements `isEqual()` it will - respect that method. - - ```javascript - Ember.isEqual('hello', 'hello'); // true - Ember.isEqual(1, 2); // false - Ember.isEqual([4,2], [4,2]); // false - ``` - - @method isEqual - @for Ember - @param {Object} a first object to compare - @param {Object} b second object to compare - @return {Boolean} -*/ -Ember.isEqual = function(a, b) { - if (a && 'function'===typeof a.isEqual) return a.isEqual(b); - return a === b; -}; - -// Used by Ember.compare -Ember.ORDER_DEFINITION = Ember.ENV.ORDER_DEFINITION || [ - 'undefined', - 'null', - 'boolean', - 'number', - 'string', - 'array', - 'object', - 'instance', - 'function', - 'class', - 'date' -]; - -/** - Returns all of the keys defined on an object or hash. This is useful - when inspecting objects for debugging. On browsers that support it, this - uses the native `Object.keys` implementation. - - @method keys - @for Ember - @param {Object} obj - @return {Array} Array containing keys of obj -*/ -Ember.keys = Object.keys; - -if (!Ember.keys) { - Ember.keys = function(obj) { - var ret = []; - for(var key in obj) { - if (obj.hasOwnProperty(key)) { ret.push(key); } - } - return ret; - }; -} - -// .......................................................... -// ERROR -// - -var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack']; - -/** - A subclass of the JavaScript Error object for use in Ember. - - @class Error - @namespace Ember - @extends Error - @constructor -*/ -Ember.Error = function() { - var tmp = Error.prototype.constructor.apply(this, arguments); - - // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work. - for (var idx = 0; idx < errorProps.length; idx++) { - this[errorProps[idx]] = tmp[errorProps[idx]]; - } -}; - -Ember.Error.prototype = Ember.create(Error.prototype); - -})(); - - - -(function() { -/** - Expose RSVP implementation - - @class RSVP - @namespace Ember - @constructor -*/ -Ember.RSVP = requireModule('rsvp'); - -})(); - - - -(function() { -/** -@module ember -@submodule ember-runtime -*/ - -var STRING_DASHERIZE_REGEXP = (/[ _]/g); -var STRING_DASHERIZE_CACHE = {}; -var STRING_DECAMELIZE_REGEXP = (/([a-z])([A-Z])/g); -var STRING_CAMELIZE_REGEXP = (/(\-|_|\.|\s)+(.)?/g); -var STRING_UNDERSCORE_REGEXP_1 = (/([a-z\d])([A-Z]+)/g); -var STRING_UNDERSCORE_REGEXP_2 = (/\-|\s+/g); - -/** - Defines the hash of localized strings for the current language. Used by - the `Ember.String.loc()` helper. To localize, add string values to this - hash. - - @property STRINGS - @for Ember - @type Hash -*/ -Ember.STRINGS = {}; - -/** - Defines string helper methods including string formatting and localization. - Unless `Ember.EXTEND_PROTOTYPES.String` is `false` these methods will also be - added to the `String.prototype` as well. - - @class String - @namespace Ember - @static -*/ -Ember.String = { - - /** - Apply formatting options to the string. This will look for occurrences - of "%@" in your string and substitute them with the arguments you pass into - this method. If you want to control the specific order of replacement, - you can add a number after the key as well to indicate which argument - you want to insert. - - Ordered insertions are most useful when building loc strings where values - you need to insert may appear in different orders. - - ```javascript - "Hello %@ %@".fmt('John', 'Doe'); // "Hello John Doe" - "Hello %@2, %@1".fmt('John', 'Doe'); // "Hello Doe, John" - ``` - - @method fmt - @param {Object...} [args] - @return {String} formatted string - */ - fmt: function(str, formats) { - // first, replace any ORDERED replacements. - var idx = 0; // the current index for non-numerical replacements - return str.replace(/%@([0-9]+)?/g, function(s, argIndex) { - argIndex = (argIndex) ? parseInt(argIndex,0) - 1 : idx++ ; - s = formats[argIndex]; - return ((s === null) ? '(null)' : (s === undefined) ? '' : s).toString(); - }) ; - }, - - /** - Formats the passed string, but first looks up the string in the localized - strings hash. This is a convenient way to localize text. See - `Ember.String.fmt()` for more information on formatting. - - Note that it is traditional but not required to prefix localized string - keys with an underscore or other character so you can easily identify - localized strings. - - ```javascript - Ember.STRINGS = { - '_Hello World': 'Bonjour le monde', - '_Hello %@ %@': 'Bonjour %@ %@' - }; - - Ember.String.loc("_Hello World"); // 'Bonjour le monde'; - Ember.String.loc("_Hello %@ %@", ["John", "Smith"]); // "Bonjour John Smith"; - ``` - - @method loc - @param {String} str The string to format - @param {Array} formats Optional array of parameters to interpolate into string. - @return {String} formatted string - */ - loc: function(str, formats) { - str = Ember.STRINGS[str] || str; - return Ember.String.fmt(str, formats) ; - }, - - /** - Splits a string into separate units separated by spaces, eliminating any - empty strings in the process. This is a convenience method for split that - is mostly useful when applied to the `String.prototype`. - - ```javascript - Ember.String.w("alpha beta gamma").forEach(function(key) { - console.log(key); - }); - - // > alpha - // > beta - // > gamma - ``` - - @method w - @param {String} str The string to split - @return {String} split string - */ - w: function(str) { return str.split(/\s+/); }, - - /** - Converts a camelized string into all lower case separated by underscores. - - ```javascript - 'innerHTML'.decamelize(); // 'inner_html' - 'action_name'.decamelize(); // 'action_name' - 'css-class-name'.decamelize(); // 'css-class-name' - 'my favorite items'.decamelize(); // 'my favorite items' - ``` - - @method decamelize - @param {String} str The string to decamelize. - @return {String} the decamelized string. - */ - decamelize: function(str) { - return str.replace(STRING_DECAMELIZE_REGEXP, '$1_$2').toLowerCase(); - }, - - /** - Replaces underscores or spaces with dashes. - - ```javascript - 'innerHTML'.dasherize(); // 'inner-html' - 'action_name'.dasherize(); // 'action-name' - 'css-class-name'.dasherize(); // 'css-class-name' - 'my favorite items'.dasherize(); // 'my-favorite-items' - ``` - - @method dasherize - @param {String} str The string to dasherize. - @return {String} the dasherized string. - */ - dasherize: function(str) { - var cache = STRING_DASHERIZE_CACHE, - hit = cache.hasOwnProperty(str), - ret; - - if (hit) { - return cache[str]; - } else { - ret = Ember.String.decamelize(str).replace(STRING_DASHERIZE_REGEXP,'-'); - cache[str] = ret; - } - - return ret; - }, - - /** - Returns the lowerCamelCase form of a string. - - ```javascript - 'innerHTML'.camelize(); // 'innerHTML' - 'action_name'.camelize(); // 'actionName' - 'css-class-name'.camelize(); // 'cssClassName' - 'my favorite items'.camelize(); // 'myFavoriteItems' - 'My Favorite Items'.camelize(); // 'myFavoriteItems' - ``` - - @method camelize - @param {String} str The string to camelize. - @return {String} the camelized string. - */ - camelize: function(str) { - return str.replace(STRING_CAMELIZE_REGEXP, function(match, separator, chr) { - return chr ? chr.toUpperCase() : ''; - }).replace(/^([A-Z])/, function(match, separator, chr) { - return match.toLowerCase(); - }); - }, - - /** - Returns the UpperCamelCase form of a string. - - ```javascript - 'innerHTML'.classify(); // 'InnerHTML' - 'action_name'.classify(); // 'ActionName' - 'css-class-name'.classify(); // 'CssClassName' - 'my favorite items'.classify(); // 'MyFavoriteItems' - ``` - - @method classify - @param {String} str the string to classify - @return {String} the classified string - */ - classify: function(str) { - var parts = str.split("."), - out = []; - - for (var i=0, l=parts.length; i1) args = a_slice.call(arguments, 1); - - this.forEach(function(x, idx) { - var method = x && x[methodName]; - if ('function' === typeof method) { - ret[idx] = args ? method.apply(x, args) : method.call(x); - } - }, this); - - return ret; - }, - - /** - Simply converts the enumerable into a genuine array. The order is not - guaranteed. Corresponds to the method implemented by Prototype. - - @method toArray - @return {Array} the enumerable as an array. - */ - toArray: function() { - var ret = Ember.A([]); - this.forEach(function(o, idx) { ret[idx] = o; }); - return ret ; - }, - - /** - Returns a copy of the array with all null and undefined elements removed. - - ```javascript - var arr = ["a", null, "c", undefined]; - arr.compact(); // ["a", "c"] - ``` - - @method compact - @return {Array} the array without null and undefined elements. - */ - compact: function() { - return this.filter(function(value) { return value != null; }); - }, - - /** - Returns a new enumerable that excludes the passed value. The default - implementation returns an array regardless of the receiver type unless - the receiver does not contain the value. - - ```javascript - var arr = ["a", "b", "a", "c"]; - arr.without("a"); // ["b", "c"] - ``` - - @method without - @param {Object} value - @return {Ember.Enumerable} - */ - without: function(value) { - if (!this.contains(value)) return this; // nothing to do - var ret = Ember.A([]); - this.forEach(function(k) { - if (k !== value) ret[ret.length] = k; - }) ; - return ret ; - }, - - /** - Returns a new enumerable that contains only unique values. The default - implementation returns an array regardless of the receiver type. - - ```javascript - var arr = ["a", "a", "b", "b"]; - arr.uniq(); // ["a", "b"] - ``` - - @method uniq - @return {Ember.Enumerable} - */ - uniq: function() { - var ret = Ember.A([]); - this.forEach(function(k){ - if (a_indexOf(ret, k)<0) ret.push(k); - }); - return ret; - }, - - /** - This property will trigger anytime the enumerable's content changes. - You can observe this property to be notified of changes to the enumerables - content. - - For plain enumerables, this property is read only. `Ember.Array` overrides - this method. - - @property [] - @type Ember.Array - @return this - */ - '[]': Ember.computed(function(key, value) { - return this; - }), - - // .......................................................... - // ENUMERABLE OBSERVERS - // - - /** - Registers an enumerable observer. Must implement `Ember.EnumerableObserver` - mixin. - - @method addEnumerableObserver - @param {Object} target - @param {Hash} [opts] - @return this - */ - addEnumerableObserver: function(target, opts) { - var willChange = (opts && opts.willChange) || 'enumerableWillChange', - didChange = (opts && opts.didChange) || 'enumerableDidChange'; - - var hasObservers = get(this, 'hasEnumerableObservers'); - if (!hasObservers) Ember.propertyWillChange(this, 'hasEnumerableObservers'); - Ember.addListener(this, '@enumerable:before', target, willChange); - Ember.addListener(this, '@enumerable:change', target, didChange); - if (!hasObservers) Ember.propertyDidChange(this, 'hasEnumerableObservers'); - return this; - }, - - /** - Removes a registered enumerable observer. - - @method removeEnumerableObserver - @param {Object} target - @param {Hash} [opts] - @return this - */ - removeEnumerableObserver: function(target, opts) { - var willChange = (opts && opts.willChange) || 'enumerableWillChange', - didChange = (opts && opts.didChange) || 'enumerableDidChange'; - - var hasObservers = get(this, 'hasEnumerableObservers'); - if (hasObservers) Ember.propertyWillChange(this, 'hasEnumerableObservers'); - Ember.removeListener(this, '@enumerable:before', target, willChange); - Ember.removeListener(this, '@enumerable:change', target, didChange); - if (hasObservers) Ember.propertyDidChange(this, 'hasEnumerableObservers'); - return this; - }, - - /** - Becomes true whenever the array currently has observers watching changes - on the array. - - @property hasEnumerableObservers - @type Boolean - */ - hasEnumerableObservers: Ember.computed(function() { - return Ember.hasListeners(this, '@enumerable:change') || Ember.hasListeners(this, '@enumerable:before'); - }), - - - /** - Invoke this method just before the contents of your enumerable will - change. You can either omit the parameters completely or pass the objects - to be removed or added if available or just a count. - - @method enumerableContentWillChange - @param {Ember.Enumerable|Number} removing An enumerable of the objects to - be removed or the number of items to be removed. - @param {Ember.Enumerable|Number} adding An enumerable of the objects to be - added or the number of items to be added. - @chainable - */ - enumerableContentWillChange: function(removing, adding) { - - var removeCnt, addCnt, hasDelta; - - if ('number' === typeof removing) removeCnt = removing; - else if (removing) removeCnt = get(removing, 'length'); - else removeCnt = removing = -1; - - if ('number' === typeof adding) addCnt = adding; - else if (adding) addCnt = get(adding,'length'); - else addCnt = adding = -1; - - hasDelta = addCnt<0 || removeCnt<0 || addCnt-removeCnt!==0; - - if (removing === -1) removing = null; - if (adding === -1) adding = null; - - Ember.propertyWillChange(this, '[]'); - if (hasDelta) Ember.propertyWillChange(this, 'length'); - Ember.sendEvent(this, '@enumerable:before', [this, removing, adding]); - - return this; - }, - - /** - Invoke this method when the contents of your enumerable has changed. - This will notify any observers watching for content changes. If your are - implementing an ordered enumerable (such as an array), also pass the - start and end values where the content changed so that it can be used to - notify range observers. - - @method enumerableContentDidChange - @param {Number} [start] optional start offset for the content change. - For unordered enumerables, you should always pass -1. - @param {Ember.Enumerable|Number} removing An enumerable of the objects to - be removed or the number of items to be removed. - @param {Ember.Enumerable|Number} adding An enumerable of the objects to - be added or the number of items to be added. - @chainable - */ - enumerableContentDidChange: function(removing, adding) { - var removeCnt, addCnt, hasDelta; - - if ('number' === typeof removing) removeCnt = removing; - else if (removing) removeCnt = get(removing, 'length'); - else removeCnt = removing = -1; - - if ('number' === typeof adding) addCnt = adding; - else if (adding) addCnt = get(adding, 'length'); - else addCnt = adding = -1; - - hasDelta = addCnt<0 || removeCnt<0 || addCnt-removeCnt!==0; - - if (removing === -1) removing = null; - if (adding === -1) adding = null; - - Ember.sendEvent(this, '@enumerable:change', [this, removing, adding]); - if (hasDelta) Ember.propertyDidChange(this, 'length'); - Ember.propertyDidChange(this, '[]'); - - return this ; - } - -}) ; - -})(); - - - -(function() { -/** -@module ember -@submodule ember-runtime -*/ - -// .......................................................... -// HELPERS -// - -var get = Ember.get, set = Ember.set, map = Ember.EnumerableUtils.map, cacheFor = Ember.cacheFor; - -function none(obj) { return obj===null || obj===undefined; } - -// .......................................................... -// ARRAY -// -/** - This module implements Observer-friendly Array-like behavior. This mixin is - picked up by the Array class as well as other controllers, etc. that want to - appear to be arrays. - - Unlike `Ember.Enumerable,` this mixin defines methods specifically for - collections that provide index-ordered access to their contents. When you - are designing code that needs to accept any kind of Array-like object, you - should use these methods instead of Array primitives because these will - properly notify observers of changes to the array. - - Although these methods are efficient, they do add a layer of indirection to - your application so it is a good idea to use them only when you need the - flexibility of using both true JavaScript arrays and "virtual" arrays such - as controllers and collections. - - You can use the methods defined in this module to access and modify array - contents in a KVO-friendly way. You can also be notified whenever the - membership if an array changes by changing the syntax of the property to - `.observes('*myProperty.[]')`. - - To support `Ember.Array` in your own class, you must override two - primitives to use it: `replace()` and `objectAt()`. - - Note that the Ember.Array mixin also incorporates the `Ember.Enumerable` - mixin. All `Ember.Array`-like objects are also enumerable. - - @class Array - @namespace Ember - @extends Ember.Mixin - @uses Ember.Enumerable - @since Ember 0.9.0 -*/ -Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.prototype */ { - - // compatibility - isSCArray: true, - - /** - Your array must support the `length` property. Your replace methods should - set this property whenever it changes. - - @property {Number} length - */ - length: Ember.required(), - - /** - Returns the object at the given `index`. If the given `index` is negative - or is greater or equal than the array length, returns `undefined`. - - This is one of the primitives you must implement to support `Ember.Array`. - If your object supports retrieving the value of an array item using `get()` - (i.e. `myArray.get(0)`), then you do not need to implement this method - yourself. - - ```javascript - var arr = ['a', 'b', 'c', 'd']; - arr.objectAt(0); // "a" - arr.objectAt(3); // "d" - arr.objectAt(-1); // undefined - arr.objectAt(4); // undefined - arr.objectAt(5); // undefined - ``` - - @method objectAt - @param {Number} idx The index of the item to return. - @return {any} item at index or undefined - */ - objectAt: function(idx) { - if ((idx < 0) || (idx>=get(this, 'length'))) return undefined ; - return get(this, idx); - }, - - /** - This returns the objects at the specified indexes, using `objectAt`. - - ```javascript - var arr = ['a', 'b', 'c', 'd']; - arr.objectsAt([0, 1, 2]); // ["a", "b", "c"] - arr.objectsAt([2, 3, 4]); // ["c", "d", undefined] - ``` - - @method objectsAt - @param {Array} indexes An array of indexes of items to return. - @return {Array} - */ - objectsAt: function(indexes) { - var self = this; - return map(indexes, function(idx){ return self.objectAt(idx); }); - }, - - // overrides Ember.Enumerable version - nextObject: function(idx) { - return this.objectAt(idx); - }, - - /** - This is the handler for the special array content property. If you get - this property, it will return this. If you set this property it a new - array, it will replace the current content. - - This property overrides the default property defined in `Ember.Enumerable`. - - @property [] - @return this - */ - '[]': Ember.computed(function(key, value) { - if (value !== undefined) this.replace(0, get(this, 'length'), value) ; - return this ; - }), - - firstObject: Ember.computed(function() { - return this.objectAt(0); - }), - - lastObject: Ember.computed(function() { - return this.objectAt(get(this, 'length')-1); - }), - - // optimized version from Enumerable - contains: function(obj){ - return this.indexOf(obj) >= 0; - }, - - // Add any extra methods to Ember.Array that are native to the built-in Array. - /** - Returns a new array that is a slice of the receiver. This implementation - uses the observable array methods to retrieve the objects for the new - slice. - - ```javascript - var arr = ['red', 'green', 'blue']; - arr.slice(0); // ['red', 'green', 'blue'] - arr.slice(0, 2); // ['red', 'green'] - arr.slice(1, 100); // ['green', 'blue'] - ``` - - @method slice - @param {Integer} beginIndex (Optional) index to begin slicing from. - @param {Integer} endIndex (Optional) index to end the slice at. - @return {Array} New array with specified slice - */ - slice: function(beginIndex, endIndex) { - var ret = Ember.A([]); - var length = get(this, 'length') ; - if (none(beginIndex)) beginIndex = 0 ; - if (none(endIndex) || (endIndex > length)) endIndex = length ; - - if (beginIndex < 0) beginIndex = length + beginIndex; - if (endIndex < 0) endIndex = length + endIndex; - - while(beginIndex < endIndex) { - ret[ret.length] = this.objectAt(beginIndex++) ; - } - return ret ; - }, - - /** - Returns the index of the given object's first occurrence. - If no `startAt` argument is given, the starting location to - search is 0. If it's negative, will count backward from - the end of the array. Returns -1 if no match is found. - - ```javascript - var arr = ["a", "b", "c", "d", "a"]; - arr.indexOf("a"); // 0 - arr.indexOf("z"); // -1 - arr.indexOf("a", 2); // 4 - arr.indexOf("a", -1); // 4 - arr.indexOf("b", 3); // -1 - arr.indexOf("a", 100); // -1 - ``` - - @method indexOf - @param {Object} object the item to search for - @param {Number} startAt optional starting location to search, default 0 - @return {Number} index or -1 if not found - */ - indexOf: function(object, startAt) { - var idx, len = get(this, 'length'); - - if (startAt === undefined) startAt = 0; - if (startAt < 0) startAt += len; - - for(idx=startAt;idx= len) startAt = len-1; - if (startAt < 0) startAt += len; - - for(idx=startAt;idx>=0;idx--) { - if (this.objectAt(idx) === object) return idx ; - } - return -1; - }, - - // .......................................................... - // ARRAY OBSERVERS - // - - /** - Adds an array observer to the receiving array. The array observer object - normally must implement two methods: - - * `arrayWillChange(start, removeCount, addCount)` - This method will be - called just before the array is modified. - * `arrayDidChange(start, removeCount, addCount)` - This method will be - called just after the array is modified. - - Both callbacks will be passed the starting index of the change as well a - a count of the items to be removed and added. You can use these callbacks - to optionally inspect the array during the change, clear caches, or do - any other bookkeeping necessary. - - In addition to passing a target, you can also include an options hash - which you can use to override the method names that will be invoked on the - target. - - @method addArrayObserver - @param {Object} target The observer object. - @param {Hash} opts Optional hash of configuration options including - `willChange` and `didChange` option. - @return {Ember.Array} receiver - */ - addArrayObserver: function(target, opts) { - var willChange = (opts && opts.willChange) || 'arrayWillChange', - didChange = (opts && opts.didChange) || 'arrayDidChange'; - - var hasObservers = get(this, 'hasArrayObservers'); - if (!hasObservers) Ember.propertyWillChange(this, 'hasArrayObservers'); - Ember.addListener(this, '@array:before', target, willChange); - Ember.addListener(this, '@array:change', target, didChange); - if (!hasObservers) Ember.propertyDidChange(this, 'hasArrayObservers'); - return this; - }, - - /** - Removes an array observer from the object if the observer is current - registered. Calling this method multiple times with the same object will - have no effect. - - @method removeArrayObserver - @param {Object} target The object observing the array. - @param {Hash} opts Optional hash of configuration options including - `willChange` and `didChange` option. - @return {Ember.Array} receiver - */ - removeArrayObserver: function(target, opts) { - var willChange = (opts && opts.willChange) || 'arrayWillChange', - didChange = (opts && opts.didChange) || 'arrayDidChange'; - - var hasObservers = get(this, 'hasArrayObservers'); - if (hasObservers) Ember.propertyWillChange(this, 'hasArrayObservers'); - Ember.removeListener(this, '@array:before', target, willChange); - Ember.removeListener(this, '@array:change', target, didChange); - if (hasObservers) Ember.propertyDidChange(this, 'hasArrayObservers'); - return this; - }, - - /** - Becomes true whenever the array currently has observers watching changes - on the array. - - @property Boolean - */ - hasArrayObservers: Ember.computed(function() { - return Ember.hasListeners(this, '@array:change') || Ember.hasListeners(this, '@array:before'); - }), - - /** - If you are implementing an object that supports `Ember.Array`, call this - method just before the array content changes to notify any observers and - invalidate any related properties. Pass the starting index of the change - as well as a delta of the amounts to change. - - @method arrayContentWillChange - @param {Number} startIdx The starting index in the array that will change. - @param {Number} removeAmt The number of items that will be removed. If you - pass `null` assumes 0 - @param {Number} addAmt The number of items that will be added If you - pass `null` assumes 0. - @return {Ember.Array} receiver - */ - arrayContentWillChange: function(startIdx, removeAmt, addAmt) { - - // if no args are passed assume everything changes - if (startIdx===undefined) { - startIdx = 0; - removeAmt = addAmt = -1; - } else { - if (removeAmt === undefined) removeAmt=-1; - if (addAmt === undefined) addAmt=-1; - } - - // Make sure the @each proxy is set up if anyone is observing @each - if (Ember.isWatching(this, '@each')) { get(this, '@each'); } - - Ember.sendEvent(this, '@array:before', [this, startIdx, removeAmt, addAmt]); - - var removing, lim; - if (startIdx>=0 && removeAmt>=0 && get(this, 'hasEnumerableObservers')) { - removing = []; - lim = startIdx+removeAmt; - for(var idx=startIdx;idx=0 && addAmt>=0 && get(this, 'hasEnumerableObservers')) { - adding = []; - lim = startIdx+addAmt; - for(var idx=startIdx;idx b` - - Default implementation raises an exception. - - @method compare - @param a {Object} the first object to compare - @param b {Object} the second object to compare - @return {Integer} the result of the comparison - */ - compare: Ember.required(Function) - -}); - - -})(); - - - -(function() { -/** -@module ember -@submodule ember-runtime -*/ - - - -var get = Ember.get, set = Ember.set; - -/** - Implements some standard methods for copying an object. Add this mixin to - any object you create that can create a copy of itself. This mixin is - added automatically to the built-in array. - - You should generally implement the `copy()` method to return a copy of the - receiver. - - Note that `frozenCopy()` will only work if you also implement - `Ember.Freezable`. - - @class Copyable - @namespace Ember - @extends Ember.Mixin - @since Ember 0.9 -*/ -Ember.Copyable = Ember.Mixin.create( -/** @scope Ember.Copyable.prototype */ { - - /** - Override to return a copy of the receiver. Default implementation raises - an exception. - - @method copy - @param {Boolean} deep if `true`, a deep copy of the object should be made - @return {Object} copy of receiver - */ - copy: Ember.required(Function), - - /** - If the object implements `Ember.Freezable`, then this will return a new - copy if the object is not frozen and the receiver if the object is frozen. - - Raises an exception if you try to call this method on a object that does - not support freezing. - - You should use this method whenever you want a copy of a freezable object - since a freezable object can simply return itself without actually - consuming more memory. - - @method frozenCopy - @return {Object} copy of receiver or receiver - */ - frozenCopy: function() { - if (Ember.Freezable && Ember.Freezable.detect(this)) { - return get(this, 'isFrozen') ? this : this.copy().freeze(); - } else { - throw new Error(Ember.String.fmt("%@ does not support freezing", [this])); - } - } -}); - -})(); - - - -(function() { -/** -@module ember -@submodule ember-runtime -*/ - - -var get = Ember.get, set = Ember.set; - -/** - The `Ember.Freezable` mixin implements some basic methods for marking an - object as frozen. Once an object is frozen it should be read only. No changes - may be made the internal state of the object. - - ## Enforcement - - To fully support freezing in your subclass, you must include this mixin and - override any method that might alter any property on the object to instead - raise an exception. You can check the state of an object by checking the - `isFrozen` property. - - Although future versions of JavaScript may support language-level freezing - object objects, that is not the case today. Even if an object is freezable, - it is still technically possible to modify the object, even though it could - break other parts of your application that do not expect a frozen object to - change. It is, therefore, very important that you always respect the - `isFrozen` property on all freezable objects. - - ## Example Usage - - The example below shows a simple object that implement the `Ember.Freezable` - protocol. - - ```javascript - Contact = Ember.Object.extend(Ember.Freezable, { - firstName: null, - lastName: null, - - // swaps the names - swapNames: function() { - if (this.get('isFrozen')) throw Ember.FROZEN_ERROR; - var tmp = this.get('firstName'); - this.set('firstName', this.get('lastName')); - this.set('lastName', tmp); - return this; - } - - }); - - c = Context.create({ firstName: "John", lastName: "Doe" }); - c.swapNames(); // returns c - c.freeze(); - c.swapNames(); // EXCEPTION - ``` - - ## Copying - - Usually the `Ember.Freezable` protocol is implemented in cooperation with the - `Ember.Copyable` protocol, which defines a `frozenCopy()` method that will - return a frozen object, if the object implements this method as well. - - @class Freezable - @namespace Ember - @extends Ember.Mixin - @since Ember 0.9 -*/ -Ember.Freezable = Ember.Mixin.create( -/** @scope Ember.Freezable.prototype */ { - - /** - Set to `true` when the object is frozen. Use this property to detect - whether your object is frozen or not. - - @property isFrozen - @type Boolean - */ - isFrozen: false, - - /** - Freezes the object. Once this method has been called the object should - no longer allow any properties to be edited. - - @method freeze - @return {Object} receiver - */ - freeze: function() { - if (get(this, 'isFrozen')) return this; - set(this, 'isFrozen', true); - return this; - } - -}); - -Ember.FROZEN_ERROR = "Frozen object cannot be modified."; - -})(); - - - -(function() { -/** -@module ember -@submodule ember-runtime -*/ - -var forEach = Ember.EnumerableUtils.forEach; - -/** - This mixin defines the API for modifying generic enumerables. These methods - can be applied to an object regardless of whether it is ordered or - unordered. - - Note that an Enumerable can change even if it does not implement this mixin. - For example, a MappedEnumerable cannot be directly modified but if its - underlying enumerable changes, it will change also. - - ## Adding Objects - - To add an object to an enumerable, use the `addObject()` method. This - method will only add the object to the enumerable if the object is not - already present and the object if of a type supported by the enumerable. - - ```javascript - set.addObject(contact); - ``` - - ## Removing Objects - - To remove an object form an enumerable, use the `removeObject()` method. This - will only remove the object if it is already in the enumerable, otherwise - this method has no effect. - - ```javascript - set.removeObject(contact); - ``` - - ## Implementing In Your Own Code - - If you are implementing an object and want to support this API, just include - this mixin in your class and implement the required methods. In your unit - tests, be sure to apply the Ember.MutableEnumerableTests to your object. - - @class MutableEnumerable - @namespace Ember - @extends Ember.Mixin - @uses Ember.Enumerable -*/ -Ember.MutableEnumerable = Ember.Mixin.create(Ember.Enumerable, { - - /** - __Required.__ You must implement this method to apply this mixin. - - Attempts to add the passed object to the receiver if the object is not - already present in the collection. If the object is present, this method - has no effect. - - If the passed object is of a type not supported by the receiver - then this method should raise an exception. - - @method addObject - @param {Object} object The object to add to the enumerable. - @return {Object} the passed object - */ - addObject: Ember.required(Function), - - /** - Adds each object in the passed enumerable to the receiver. - - @method addObjects - @param {Ember.Enumerable} objects the objects to add. - @return {Object} receiver - */ - addObjects: function(objects) { - Ember.beginPropertyChanges(this); - forEach(objects, function(obj) { this.addObject(obj); }, this); - Ember.endPropertyChanges(this); - return this; - }, - - /** - __Required.__ You must implement this method to apply this mixin. - - Attempts to remove the passed object from the receiver collection if the - object is in present in the collection. If the object is not present, - this method has no effect. - - If the passed object is of a type not supported by the receiver - then this method should raise an exception. - - @method removeObject - @param {Object} object The object to remove from the enumerable. - @return {Object} the passed object - */ - removeObject: Ember.required(Function), - - - /** - Removes each objects in the passed enumerable from the receiver. - - @method removeObjects - @param {Ember.Enumerable} objects the objects to remove - @return {Object} receiver - */ - removeObjects: function(objects) { - Ember.beginPropertyChanges(this); - forEach(objects, function(obj) { this.removeObject(obj); }, this); - Ember.endPropertyChanges(this); - return this; - } - -}); - -})(); - - - -(function() { -/** -@module ember -@submodule ember-runtime -*/ -// .......................................................... -// CONSTANTS -// - -var OUT_OF_RANGE_EXCEPTION = "Index out of range" ; -var EMPTY = []; - -// .......................................................... -// HELPERS -// - -var get = Ember.get, set = Ember.set; - -/** - This mixin defines the API for modifying array-like objects. These methods - can be applied only to a collection that keeps its items in an ordered set. - - Note that an Array can change even if it does not implement this mixin. - For example, one might implement a SparseArray that cannot be directly - modified, but if its underlying enumerable changes, it will change also. - - @class MutableArray - @namespace Ember - @extends Ember.Mixin - @uses Ember.Array - @uses Ember.MutableEnumerable -*/ -Ember.MutableArray = Ember.Mixin.create(Ember.Array, Ember.MutableEnumerable, - /** @scope Ember.MutableArray.prototype */ { - - /** - __Required.__ You must implement this method to apply this mixin. - - This is one of the primitives you must implement to support `Ember.Array`. - You should replace amt objects started at idx with the objects in the - passed array. You should also call `this.enumerableContentDidChange()` - - @method replace - @param {Number} idx Starting index in the array to replace. If - idx >= length, then append to the end of the array. - @param {Number} amt Number of elements that should be removed from - the array, starting at *idx*. - @param {Array} objects An array of zero or more objects that should be - inserted into the array at *idx* - */ - replace: Ember.required(), - - /** - Remove all elements from self. This is useful if you - want to reuse an existing array without having to recreate it. - - ```javascript - var colors = ["red", "green", "blue"]; - color.length(); // 3 - colors.clear(); // [] - colors.length(); // 0 - ``` - - @method clear - @return {Ember.Array} An empty Array. - */ - clear: function () { - var len = get(this, 'length'); - if (len === 0) return this; - this.replace(0, len, EMPTY); - return this; - }, - - /** - This will use the primitive `replace()` method to insert an object at the - specified index. - - ```javascript - var colors = ["red", "green", "blue"]; - colors.insertAt(2, "yellow"); // ["red", "green", "yellow", "blue"] - colors.insertAt(5, "orange"); // Error: Index out of range - ``` - - @method insertAt - @param {Number} idx index of insert the object at. - @param {Object} object object to insert - @return this - */ - insertAt: function(idx, object) { - if (idx > get(this, 'length')) throw new Error(OUT_OF_RANGE_EXCEPTION) ; - this.replace(idx, 0, [object]) ; - return this ; - }, - - /** - Remove an object at the specified index using the `replace()` primitive - method. You can pass either a single index, or a start and a length. - - If you pass a start and length that is beyond the - length this method will throw an `Ember.OUT_OF_RANGE_EXCEPTION` - - ```javascript - var colors = ["red", "green", "blue", "yellow", "orange"]; - colors.removeAt(0); // ["green", "blue", "yellow", "orange"] - colors.removeAt(2, 2); // ["green", "blue"] - colors.removeAt(4, 2); // Error: Index out of range - ``` - - @method removeAt - @param {Number} start index, start of range - @param {Number} len length of passing range - @return {Object} receiver - */ - removeAt: function(start, len) { - if ('number' === typeof start) { - - if ((start < 0) || (start >= get(this, 'length'))) { - throw new Error(OUT_OF_RANGE_EXCEPTION); - } - - // fast case - if (len === undefined) len = 1; - this.replace(start, len, EMPTY); - } - - return this ; - }, - - /** - Push the object onto the end of the array. Works just like `push()` but it - is KVO-compliant. - - ```javascript - var colors = ["red", "green", "blue"]; - colors.pushObject("black"); // ["red", "green", "blue", "black"] - colors.pushObject(["yellow", "orange"]); // ["red", "green", "blue", "black", ["yellow", "orange"]] - ``` - - @method pushObject - @param {anything} obj object to push - @return {any} the same obj passed as param - */ - pushObject: function(obj) { - this.insertAt(get(this, 'length'), obj) ; - return obj ; - }, - - /** - Add the objects in the passed numerable to the end of the array. Defers - notifying observers of the change until all objects are added. - - ```javascript - var colors = ["red", "green", "blue"]; - colors.pushObjects("black"); // ["red", "green", "blue", "black"] - colors.pushObjects(["yellow", "orange"]); // ["red", "green", "blue", "black", "yellow", "orange"] - ``` - - @method pushObjects - @param {Ember.Enumerable} objects the objects to add - @return {Ember.Array} receiver - */ - pushObjects: function(objects) { - this.replace(get(this, 'length'), 0, objects); - return this; - }, - - /** - Pop object from array or nil if none are left. Works just like `pop()` but - it is KVO-compliant. - - ```javascript - var colors = ["red", "green", "blue"]; - colors.popObject(); // "blue" - console.log(colors); // ["red", "green"] - ``` - - @method popObject - @return object - */ - popObject: function() { - var len = get(this, 'length') ; - if (len === 0) return null ; - - var ret = this.objectAt(len-1) ; - this.removeAt(len-1, 1) ; - return ret ; - }, - - /** - Shift an object from start of array or nil if none are left. Works just - like `shift()` but it is KVO-compliant. - - ```javascript - var colors = ["red", "green", "blue"]; - colors.shiftObject(); // "red" - console.log(colors); // ["green", "blue"] - ``` - - @method shiftObject - @return object - */ - shiftObject: function() { - if (get(this, 'length') === 0) return null ; - var ret = this.objectAt(0) ; - this.removeAt(0) ; - return ret ; - }, - - /** - Unshift an object to start of array. Works just like `unshift()` but it is - KVO-compliant. - - ```javascript - var colors = ["red", "green", "blue"]; - colors.unshiftObject("yellow"); // ["yellow", "red", "green", "blue"] - colors.unshiftObject(["black", "white"]); // [["black", "white"], "yellow", "red", "green", "blue"] - ``` - - @method unshiftObject - @param {anything} obj object to unshift - @return {any} the same obj passed as param - */ - unshiftObject: function(obj) { - this.insertAt(0, obj) ; - return obj ; - }, - - /** - Adds the named objects to the beginning of the array. Defers notifying - observers until all objects have been added. - - ```javascript - var colors = ["red", "green", "blue"]; - colors.unshiftObjects(["black", "white"]); // ["black", "white", "red", "green", "blue"] - colors.unshiftObjects("yellow"); // Type Error: 'undefined' is not a function - ``` - - @method unshiftObjects - @param {Ember.Enumerable} objects the objects to add - @return {Ember.Array} receiver - */ - unshiftObjects: function(objects) { - this.replace(0, 0, objects); - return this; - }, - - /** - Reverse objects in the array. Works just like `reverse()` but it is - KVO-compliant. - - @method reverseObjects - @return {Ember.Array} receiver - */ - reverseObjects: function() { - var len = get(this, 'length'); - if (len === 0) return this; - var objects = this.toArray().reverse(); - this.replace(0, len, objects); - return this; - }, - - /** - Replace all the the receiver's content with content of the argument. - If argument is an empty array receiver will be cleared. - - ```javascript - var colors = ["red", "green", "blue"]; - colors.setObjects(["black", "white"]); // ["black", "white"] - colors.setObjects([]); // [] - ``` - - @method setObjects - @param {Ember.Array} objects array whose content will be used for replacing - the content of the receiver - @return {Ember.Array} receiver with the new content - */ - setObjects: function(objects) { - if (objects.length === 0) return this.clear(); - - var len = get(this, 'length'); - this.replace(0, len, objects); - return this; - }, - - // .......................................................... - // IMPLEMENT Ember.MutableEnumerable - // - - removeObject: function(obj) { - var loc = get(this, 'length') || 0; - while(--loc >= 0) { - var curObject = this.objectAt(loc) ; - if (curObject === obj) this.removeAt(loc) ; - } - return this ; - }, - - addObject: function(obj) { - if (!this.contains(obj)) this.pushObject(obj); - return this ; - } - -}); - - -})(); - - - -(function() { -/** -@module ember -@submodule ember-runtime -*/ - -var get = Ember.get, set = Ember.set; - -/** - ## Overview - - This mixin provides properties and property observing functionality, core - features of the Ember object model. - - Properties and observers allow one object to observe changes to a - property on another object. This is one of the fundamental ways that - models, controllers and views communicate with each other in an Ember - application. - - Any object that has this mixin applied can be used in observer - operations. That includes `Ember.Object` and most objects you will - interact with as you write your Ember application. - - Note that you will not generally apply this mixin to classes yourself, - but you will use the features provided by this module frequently, so it - is important to understand how to use it. - - ## Using `get()` and `set()` - - Because of Ember's support for bindings and observers, you will always - access properties using the get method, and set properties using the - set method. This allows the observing objects to be notified and - computed properties to be handled properly. - - More documentation about `get` and `set` are below. - - ## Observing Property Changes - - You typically observe property changes simply by adding the `observes` - call to the end of your method declarations in classes that you write. - For example: - - ```javascript - Ember.Object.create({ - valueObserver: function() { - // Executes whenever the "value" property changes - }.observes('value') - }); - ``` - - Although this is the most common way to add an observer, this capability - is actually built into the `Ember.Object` class on top of two methods - defined in this mixin: `addObserver` and `removeObserver`. You can use - these two methods to add and remove observers yourself if you need to - do so at runtime. - - To add an observer for a property, call: - - ```javascript - object.addObserver('propertyKey', targetObject, targetAction) - ``` - - This will call the `targetAction` method on the `targetObject` to be called - whenever the value of the `propertyKey` changes. - - Note that if `propertyKey` is a computed property, the observer will be - called when any of the property dependencies are changed, even if the - resulting value of the computed property is unchanged. This is necessary - because computed properties are not computed until `get` is called. - - @class Observable - @namespace Ember - @extends Ember.Mixin -*/ -Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ { - - /** - Retrieves the value of a property from the object. - - This method is usually similar to using `object[keyName]` or `object.keyName`, - however it supports both computed properties and the unknownProperty - handler. - - Because `get` unifies the syntax for accessing all these kinds - of properties, it can make many refactorings easier, such as replacing a - simple property with a computed property, or vice versa. - - ### Computed Properties - - Computed properties are methods defined with the `property` modifier - declared at the end, such as: - - ```javascript - fullName: function() { - return this.getEach('firstName', 'lastName').compact().join(' '); - }.property('firstName', 'lastName') - ``` - - When you call `get` on a computed property, the function will be - called and the return value will be returned instead of the function - itself. - - ### Unknown Properties - - Likewise, if you try to call `get` on a property whose value is - `undefined`, the `unknownProperty()` method will be called on the object. - If this method returns any value other than `undefined`, it will be returned - instead. This allows you to implement "virtual" properties that are - not defined upfront. - - @method get - @param {String} keyName The property to retrieve - @return {Object} The property value or undefined. - */ - get: function(keyName) { - return get(this, keyName); - }, - - /** - To get multiple properties at once, call `getProperties` - with a list of strings or an array: - - ```javascript - record.getProperties('firstName', 'lastName', 'zipCode'); // { firstName: 'John', lastName: 'Doe', zipCode: '10011' } - ``` - - is equivalent to: - - ```javascript - record.getProperties(['firstName', 'lastName', 'zipCode']); // { firstName: 'John', lastName: 'Doe', zipCode: '10011' } - ``` - - @method getProperties - @param {String...|Array} list of keys to get - @return {Hash} - */ - getProperties: function() { - var ret = {}; - var propertyNames = arguments; - if (arguments.length === 1 && Ember.typeOf(arguments[0]) === 'array') { - propertyNames = arguments[0]; - } - for(var i = 0; i < propertyNames.length; i++) { - ret[propertyNames[i]] = get(this, propertyNames[i]); - } - return ret; - }, - - /** - Sets the provided key or path to the value. - - This method is generally very similar to calling `object[key] = value` or - `object.key = value`, except that it provides support for computed - properties, the `unknownProperty()` method and property observers. - - ### Computed Properties - - If you try to set a value on a key that has a computed property handler - defined (see the `get()` method for an example), then `set()` will call - that method, passing both the value and key instead of simply changing - the value itself. This is useful for those times when you need to - implement a property that is composed of one or more member - properties. - - ### Unknown Properties - - If you try to set a value on a key that is undefined in the target - object, then the `unknownProperty()` handler will be called instead. This - gives you an opportunity to implement complex "virtual" properties that - are not predefined on the object. If `unknownProperty()` returns - undefined, then `set()` will simply set the value on the object. - - ### Property Observers - - In addition to changing the property, `set()` will also register a property - change with the object. Unless you have placed this call inside of a - `beginPropertyChanges()` and `endPropertyChanges(),` any "local" observers - (i.e. observer methods declared on the same object), will be called - immediately. Any "remote" observers (i.e. observer methods declared on - another object) will be placed in a queue and called at a later time in a - coalesced manner. - - ### Chaining - - In addition to property changes, `set()` returns the value of the object - itself so you can do chaining like this: - - ```javascript - record.set('firstName', 'Charles').set('lastName', 'Jolley'); - ``` - - @method set - @param {String} keyName The property to set - @param {Object} value The value to set or `null`. - @return {Ember.Observable} - */ - set: function(keyName, value) { - set(this, keyName, value); - return this; - }, - - /** - To set multiple properties at once, call `setProperties` - with a Hash: - - ```javascript - record.setProperties({ firstName: 'Charles', lastName: 'Jolley' }); - ``` - - @method setProperties - @param {Hash} hash the hash of keys and values to set - @return {Ember.Observable} - */ - setProperties: function(hash) { - return Ember.setProperties(this, hash); - }, - - /** - Begins a grouping of property changes. - - You can use this method to group property changes so that notifications - will not be sent until the changes are finished. If you plan to make a - large number of changes to an object at one time, you should call this - method at the beginning of the changes to begin deferring change - notifications. When you are done making changes, call - `endPropertyChanges()` to deliver the deferred change notifications and end - deferring. - - @method beginPropertyChanges - @return {Ember.Observable} - */ - beginPropertyChanges: function() { - Ember.beginPropertyChanges(); - return this; - }, - - /** - Ends a grouping of property changes. - - You can use this method to group property changes so that notifications - will not be sent until the changes are finished. If you plan to make a - large number of changes to an object at one time, you should call - `beginPropertyChanges()` at the beginning of the changes to defer change - notifications. When you are done making changes, call this method to - deliver the deferred change notifications and end deferring. - - @method endPropertyChanges - @return {Ember.Observable} - */ - endPropertyChanges: function() { - Ember.endPropertyChanges(); - return this; - }, - - /** - Notify the observer system that a property is about to change. - - Sometimes you need to change a value directly or indirectly without - actually calling `get()` or `set()` on it. In this case, you can use this - method and `propertyDidChange()` instead. Calling these two methods - together will notify all observers that the property has potentially - changed value. - - Note that you must always call `propertyWillChange` and `propertyDidChange` - as a pair. If you do not, it may get the property change groups out of - order and cause notifications to be delivered more often than you would - like. - - @method propertyWillChange - @param {String} keyName The property key that is about to change. - @return {Ember.Observable} - */ - propertyWillChange: function(keyName){ - Ember.propertyWillChange(this, keyName); - return this; - }, - - /** - Notify the observer system that a property has just changed. - - Sometimes you need to change a value directly or indirectly without - actually calling `get()` or `set()` on it. In this case, you can use this - method and `propertyWillChange()` instead. Calling these two methods - together will notify all observers that the property has potentially - changed value. - - Note that you must always call `propertyWillChange` and `propertyDidChange` - as a pair. If you do not, it may get the property change groups out of - order and cause notifications to be delivered more often than you would - like. - - @method propertyDidChange - @param {String} keyName The property key that has just changed. - @return {Ember.Observable} - */ - propertyDidChange: function(keyName) { - Ember.propertyDidChange(this, keyName); - return this; - }, - - /** - Convenience method to call `propertyWillChange` and `propertyDidChange` in - succession. - - @method notifyPropertyChange - @param {String} keyName The property key to be notified about. - @return {Ember.Observable} - */ - notifyPropertyChange: function(keyName) { - this.propertyWillChange(keyName); - this.propertyDidChange(keyName); - return this; - }, - - addBeforeObserver: function(key, target, method) { - Ember.addBeforeObserver(this, key, target, method); - }, - - /** - Adds an observer on a property. - - This is the core method used to register an observer for a property. - - Once you call this method, anytime the key's value is set, your observer - will be notified. Note that the observers are triggered anytime the - value is set, regardless of whether it has actually changed. Your - observer should be prepared to handle that. - - You can also pass an optional context parameter to this method. The - context will be passed to your observer method whenever it is triggered. - Note that if you add the same target/method pair on a key multiple times - with different context parameters, your observer will only be called once - with the last context you passed. - - ### Observer Methods - - Observer methods you pass should generally have the following signature if - you do not pass a `context` parameter: - - ```javascript - fooDidChange: function(sender, key, value, rev) { }; - ``` - - The sender is the object that changed. The key is the property that - changes. The value property is currently reserved and unused. The rev - is the last property revision of the object when it changed, which you can - use to detect if the key value has really changed or not. - - If you pass a `context` parameter, the context will be passed before the - revision like so: - - ```javascript - fooDidChange: function(sender, key, value, context, rev) { }; - ``` - - Usually you will not need the value, context or revision parameters at - the end. In this case, it is common to write observer methods that take - only a sender and key value as parameters or, if you aren't interested in - any of these values, to write an observer that has no parameters at all. - - @method addObserver - @param {String} key The key to observer - @param {Object} target The target object to invoke - @param {String|Function} method The method to invoke. - @return {Ember.Object} self - */ - addObserver: function(key, target, method) { - Ember.addObserver(this, key, target, method); - }, - - /** - Remove an observer you have previously registered on this object. Pass - the same key, target, and method you passed to `addObserver()` and your - target will no longer receive notifications. - - @method removeObserver - @param {String} key The key to observer - @param {Object} target The target object to invoke - @param {String|Function} method The method to invoke. - @return {Ember.Observable} receiver - */ - removeObserver: function(key, target, method) { - Ember.removeObserver(this, key, target, method); - }, - - /** - Returns `true` if the object currently has observers registered for a - particular key. You can use this method to potentially defer performing - an expensive action until someone begins observing a particular property - on the object. - - @method hasObserverFor - @param {String} key Key to check - @return {Boolean} - */ - hasObserverFor: function(key) { - return Ember.hasListeners(this, key+':change'); - }, - - /** - @deprecated - @method getPath - @param {String} path The property path to retrieve - @return {Object} The property value or undefined. - */ - getPath: function(path) { - Ember.deprecate("getPath is deprecated since get now supports paths"); - return this.get(path); - }, - - /** - @deprecated - @method setPath - @param {String} path The path to the property that will be set - @param {Object} value The value to set or `null`. - @return {Ember.Observable} - */ - setPath: function(path, value) { - Ember.deprecate("setPath is deprecated since set now supports paths"); - return this.set(path, value); - }, - - /** - Retrieves the value of a property, or a default value in the case that the - property returns `undefined`. - - ```javascript - person.getWithDefault('lastName', 'Doe'); - ``` - - @method getWithDefault - @param {String} keyName The name of the property to retrieve - @param {Object} defaultValue The value to return if the property value is undefined - @return {Object} The property value or the defaultValue. - */ - getWithDefault: function(keyName, defaultValue) { - return Ember.getWithDefault(this, keyName, defaultValue); - }, - - /** - Set the value of a property to the current value plus some amount. - - ```javascript - person.incrementProperty('age'); - team.incrementProperty('score', 2); - ``` - - @method incrementProperty - @param {String} keyName The name of the property to increment - @param {Object} increment The amount to increment by. Defaults to 1 - @return {Object} The new property value - */ - incrementProperty: function(keyName, increment) { - if (!increment) { increment = 1; } - set(this, keyName, (get(this, keyName) || 0)+increment); - return get(this, keyName); - }, - - /** - Set the value of a property to the current value minus some amount. - - ```javascript - player.decrementProperty('lives'); - orc.decrementProperty('health', 5); - ``` - - @method decrementProperty - @param {String} keyName The name of the property to decrement - @param {Object} increment The amount to decrement by. Defaults to 1 - @return {Object} The new property value - */ - decrementProperty: function(keyName, increment) { - if (!increment) { increment = 1; } - set(this, keyName, (get(this, keyName) || 0)-increment); - return get(this, keyName); - }, - - /** - Set the value of a boolean property to the opposite of it's - current value. - - ```javascript - starship.toggleProperty('warpDriveEnaged'); - ``` - - @method toggleProperty - @param {String} keyName The name of the property to toggle - @return {Object} The new property value - */ - toggleProperty: function(keyName) { - set(this, keyName, !get(this, keyName)); - return get(this, keyName); - }, - - /** - Returns the cached value of a computed property, if it exists. - This allows you to inspect the value of a computed property - without accidentally invoking it if it is intended to be - generated lazily. - - @method cacheFor - @param {String} keyName - @return {Object} The cached value of the computed property, if any - */ - cacheFor: function(keyName) { - return Ember.cacheFor(this, keyName); - }, - - // intended for debugging purposes - observersForKey: function(keyName) { - return Ember.observersFor(this, keyName); - } -}); - - -})(); - - - -(function() { -/** -@module ember -@submodule ember-runtime -*/ - -var get = Ember.get, set = Ember.set; - -/** -@class TargetActionSupport -@namespace Ember -@extends Ember.Mixin -*/ -Ember.TargetActionSupport = Ember.Mixin.create({ - target: null, - action: null, - - targetObject: Ember.computed(function() { - var target = get(this, 'target'); - - if (Ember.typeOf(target) === "string") { - var value = get(this, target); - if (value === undefined) { value = get(Ember.lookup, target); } - return value; - } else { - return target; - } - }).property('target'), - - triggerAction: function() { - var action = get(this, 'action'), - target = get(this, 'targetObject'); - - if (target && action) { - var ret; - - if (typeof target.send === 'function') { - ret = target.send(action, this); - } else { - if (typeof action === 'string') { - action = target[action]; - } - ret = action.call(target, this); - } - if (ret !== false) ret = true; - - return ret; - } else { - return false; - } - } -}); - -})(); - - - -(function() { -/** -@module ember -@submodule ember-runtime -*/ - -/** - This mixin allows for Ember objects to subscribe to and emit events. - - ```javascript - App.Person = Ember.Object.extend(Ember.Evented, { - greet: function() { - // ... - this.trigger('greet'); - } - }); - - var person = App.Person.create(); - - person.on('greet', function() { - console.log('Our person has greeted'); - }); - - person.greet(); - - // outputs: 'Our person has greeted' - ``` - - You can also chain multiple event subscriptions: - - ```javascript - person.on('greet', function() { - console.log('Our person has greeted'); - }).one('greet', function() { - console.log('Offer one-time special'); - }).off('event', this, forgetThis); - ``` - - @class Evented - @namespace Ember - @extends Ember.Mixin - */ -Ember.Evented = Ember.Mixin.create({ - - /** - Subscribes to a named event with given function. - - ```javascript - person.on('didLoad', function() { - // fired once the person has loaded - }); - ``` - - An optional target can be passed in as the 2nd argument that will - be set as the "this" for the callback. This is a good way to give your - function access to the object triggering the event. When the target - parameter is used the callback becomes the third argument. - - @method on - @param {String} name The name of the event - @param {Object} [target] The "this" binding for the callback - @param {Function} method The callback to execute - @return this - */ - on: function(name, target, method) { - Ember.addListener(this, name, target, method); - return this; - }, - - /** - Subscribes a function to a named event and then cancels the subscription - after the first time the event is triggered. It is good to use ``one`` when - you only care about the first time an event has taken place. - - This function takes an optional 2nd argument that will become the "this" - value for the callback. If this argument is passed then the 3rd argument - becomes the function. - - @method one - @param {String} name The name of the event - @param {Object} [target] The "this" binding for the callback - @param {Function} method The callback to execute - @return this - */ - one: function(name, target, method) { - if (!method) { - method = target; - target = null; - } - - Ember.addListener(this, name, target, method, true); - return this; - }, - - /** - Triggers a named event for the object. Any additional arguments - will be passed as parameters to the functions that are subscribed to the - event. - - ```javascript - person.on('didEat', function(food) { - console.log('person ate some ' + food); - }); - - person.trigger('didEat', 'broccoli'); - - // outputs: person ate some broccoli - ``` - @method trigger - @param {String} name The name of the event - @param {Object...} args Optional arguments to pass on - */ - trigger: function(name) { - var args = [], i, l; - for (i = 1, l = arguments.length; i < l; i++) { - args.push(arguments[i]); - } - Ember.sendEvent(this, name, args); - }, - - fire: function(name) { - Ember.deprecate("Ember.Evented#fire() has been deprecated in favor of trigger() for compatibility with jQuery. It will be removed in 1.0. Please update your code to call trigger() instead."); - this.trigger.apply(this, arguments); - }, - - /** - Cancels subscription for give name, target, and method. - - @method off - @param {String} name The name of the event - @param {Object} target The target of the subscription - @param {Function} method The function of the subscription - @return this - */ - off: function(name, target, method) { - Ember.removeListener(this, name, target, method); - return this; - }, - - /** - Checks to see if object has any subscriptions for named event. - - @method has - @param {String} name The name of the event - @return {Boolean} does the object have a subscription for event - */ - has: function(name) { - return Ember.hasListeners(this, name); - } -}); - -})(); - - - -(function() { -var RSVP = requireModule("rsvp"); - -RSVP.async = function(callback, binding) { - Ember.run.schedule('actions', binding, callback); -}; - -/** -@module ember -@submodule ember-runtime -*/ - -var get = Ember.get; - -/** - @class Deferred - @namespace Ember - @extends Ember.Mixin - */ -Ember.DeferredMixin = Ember.Mixin.create({ - /** - Add handlers to be called when the Deferred object is resolved or rejected. - - @method then - @param {Function} doneCallback a callback function to be called when done - @param {Function} failCallback a callback function to be called when failed - */ - then: function(doneCallback, failCallback) { - var promise = get(this, 'promise'); - return promise.then.apply(promise, arguments); - }, - - /** - Resolve a Deferred object and call any `doneCallbacks` with the given args. - - @method resolve - */ - resolve: function(value) { - get(this, 'promise').resolve(value); - }, - - /** - Reject a Deferred object and call any `failCallbacks` with the given args. - - @method reject - */ - reject: function(value) { - get(this, 'promise').reject(value); - }, - - promise: Ember.computed(function() { - return new RSVP.Promise(); - }) -}); - - -})(); - - - -(function() { - -})(); - - - -(function() { -Ember.Container = requireModule('container'); -Ember.Container.set = Ember.set; - -})(); - - - -(function() { -/** -@module ember -@submodule ember-runtime -*/ - - -// NOTE: this object should never be included directly. Instead use Ember. -// Ember.Object. We only define this separately so that Ember.Set can depend on it - - -var set = Ember.set, get = Ember.get, - o_create = Ember.create, - o_defineProperty = Ember.platform.defineProperty, - GUID_KEY = Ember.GUID_KEY, - guidFor = Ember.guidFor, - generateGuid = Ember.generateGuid, - meta = Ember.meta, - rewatch = Ember.rewatch, - finishChains = Ember.finishChains, - destroy = Ember.destroy, - schedule = Ember.run.schedule, - Mixin = Ember.Mixin, - applyMixin = Mixin._apply, - finishPartial = Mixin.finishPartial, - reopen = Mixin.prototype.reopen, - MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER, - indexOf = Ember.EnumerableUtils.indexOf; - -var undefinedDescriptor = { - configurable: true, - writable: true, - enumerable: false, - value: undefined -}; - -function makeCtor() { - - // Note: avoid accessing any properties on the object since it makes the - // method a lot faster. This is glue code so we want it to be as fast as - // possible. - - var wasApplied = false, initMixins, initProperties; - - var Class = function() { - if (!wasApplied) { - Class.proto(); // prepare prototype... - } - o_defineProperty(this, GUID_KEY, undefinedDescriptor); - o_defineProperty(this, '_super', undefinedDescriptor); - var m = meta(this); - m.proto = this; - if (initMixins) { - // capture locally so we can clear the closed over variable - var mixins = initMixins; - initMixins = null; - this.reopen.apply(this, mixins); - } - if (initProperties) { - // capture locally so we can clear the closed over variable - var props = initProperties; - initProperties = null; - - var concatenatedProperties = this.concatenatedProperties; - - for (var i = 0, l = props.length; i < l; i++) { - var properties = props[i]; - for (var keyName in properties) { - if (!properties.hasOwnProperty(keyName)) { continue; } - - var value = properties[keyName], - IS_BINDING = Ember.IS_BINDING; - - if (IS_BINDING.test(keyName)) { - var bindings = m.bindings; - if (!bindings) { - bindings = m.bindings = {}; - } else if (!m.hasOwnProperty('bindings')) { - bindings = m.bindings = o_create(m.bindings); - } - bindings[keyName] = value; - } - - var desc = m.descs[keyName]; - - Ember.assert("Ember.Object.create no longer supports defining computed properties.", !(value instanceof Ember.ComputedProperty)); - Ember.assert("Ember.Object.create no longer supports defining methods that call _super.", !(typeof value === 'function' && value.toString().indexOf('._super') !== -1)); - - if (concatenatedProperties && indexOf(concatenatedProperties, keyName) >= 0) { - var baseValue = this[keyName]; - - if (baseValue) { - if ('function' === typeof baseValue.concat) { - value = baseValue.concat(value); - } else { - value = Ember.makeArray(baseValue).concat(value); - } - } else { - value = Ember.makeArray(value); - } - } - - if (desc) { - desc.set(this, keyName, value); - } else { - if (typeof this.setUnknownProperty === 'function' && !(keyName in this)) { - this.setUnknownProperty(keyName, value); - } else if (MANDATORY_SETTER) { - Ember.defineProperty(this, keyName, null, value); // setup mandatory setter - } else { - this[keyName] = value; - } - } - } - } - } - finishPartial(this, m); - delete m.proto; - finishChains(this); - this.init.apply(this, arguments); - }; - - Class.toString = Mixin.prototype.toString; - Class.willReopen = function() { - if (wasApplied) { - Class.PrototypeMixin = Mixin.create(Class.PrototypeMixin); - } - - wasApplied = false; - }; - Class._initMixins = function(args) { initMixins = args; }; - Class._initProperties = function(args) { initProperties = args; }; - - Class.proto = function() { - var superclass = Class.superclass; - if (superclass) { superclass.proto(); } - - if (!wasApplied) { - wasApplied = true; - Class.PrototypeMixin.applyPartial(Class.prototype); - rewatch(Class.prototype); - } - - return this.prototype; - }; - - return Class; - -} - -var CoreObject = makeCtor(); -CoreObject.toString = function() { return "Ember.CoreObject"; }; - -CoreObject.PrototypeMixin = Mixin.create({ - reopen: function() { - applyMixin(this, arguments, true); - return this; - }, - - isInstance: true, - - /** - An overridable method called when objects are instantiated. By default, - does nothing unless it is overridden during class definition. - - Example: - - ```javascript - App.Person = Ember.Object.extend({ - init: function() { - this._super(); - alert('Name is ' + this.get('name')); - } - }); - - var steve = App.Person.create({ - name: "Steve" - }); - - // alerts 'Name is Steve'. - ``` - - NOTE: If you do override `init` for a framework class like `Ember.View` or - `Ember.ArrayController`, be sure to call `this._super()` in your - `init` declaration! If you don't, Ember may not have an opportunity to - do important setup work, and you'll see strange behavior in your - application. - - ``` - - @method init - */ - init: function() {}, - - /** - Defines the properties that will be concatenated from the superclass - (instead of overridden). - - By default, when you extend an Ember class a property defined in - the subclass overrides a property with the same name that is defined - in the superclass. However, there are some cases where it is preferable - to build up a property's value by combining the superclass' property - value with the subclass' value. An example of this in use within Ember - is the `classNames` property of `Ember.View`. - - Here is some sample code showing the difference between a concatenated - property and a normal one: - - ```javascript - App.BarView = Ember.View.extend({ - someNonConcatenatedProperty: ['bar'], - classNames: ['bar'] - }); - - App.FooBarView = App.BarView.extend({ - someNonConcatenatedProperty: ['foo'], - classNames: ['foo'], - }); - - var fooBarView = App.FooBarView.create(); - fooBarView.get('someNonConcatenatedProperty'); // ['foo'] - fooBarView.get('classNames'); // ['ember-view', 'bar', 'foo'] - ``` - - This behavior extends to object creation as well. Continuing the - above example: - - ```javascript - var view = App.FooBarView.create({ - someNonConcatenatedProperty: ['baz'], - classNames: ['baz'] - }) - view.get('someNonConcatenatedProperty'); // ['baz'] - view.get('classNames'); // ['ember-view', 'bar', 'foo', 'baz'] - ``` - Adding a single property that is not an array will just add it in the array: - - ```javascript - var view = App.FooBarView.create({ - classNames: 'baz' - }) - view.get('classNames'); // ['ember-view', 'bar', 'foo', 'baz'] - ``` - - Using the `concatenatedProperties` property, we can tell to Ember that mix - the content of the properties. - - In `Ember.View` the `classNameBindings` and `attributeBindings` properties - are also concatenated, in addition to `classNames`. - - This feature is available for you to use throughout the Ember object model, - although typical app developers are likely to use it infrequently. - - @property concatenatedProperties - @type Array - @default null - */ - concatenatedProperties: null, - - /** - Destroyed object property flag. - - if this property is `true` the observers and bindings were already - removed by the effect of calling the `destroy()` method. - - @property isDestroyed - @default false - */ - isDestroyed: false, - - /** - Destruction scheduled flag. The `destroy()` method has been called. - - The object stays intact until the end of the run loop at which point - the `isDestroyed` flag is set. - - @property isDestroying - @default false - */ - isDestroying: false, - - /** - Destroys an object by setting the `isDestroyed` flag and removing its - metadata, which effectively destroys observers and bindings. - - If you try to set a property on a destroyed object, an exception will be - raised. - - Note that destruction is scheduled for the end of the run loop and does not - happen immediately. - - @method destroy - @return {Ember.Object} receiver - */ - destroy: function() { - if (this._didCallDestroy) { return; } - - this.isDestroying = true; - this._didCallDestroy = true; - - if (this.willDestroy) { this.willDestroy(); } - - schedule('destroy', this, this._scheduledDestroy); - return this; - }, - - /** - @private - - Invoked by the run loop to actually destroy the object. This is - scheduled for execution by the `destroy` method. - - @method _scheduledDestroy - */ - _scheduledDestroy: function() { - destroy(this); - set(this, 'isDestroyed', true); - - if (this.didDestroy) { this.didDestroy(); } - }, - - bind: function(to, from) { - if (!(from instanceof Ember.Binding)) { from = Ember.Binding.from(from); } - from.to(to).connect(this); - return from; - }, - - /** - Returns a string representation which attempts to provide more information - than Javascript's `toString` typically does, in a generic way for all Ember - objects. - - App.Person = Em.Object.extend() - person = App.Person.create() - person.toString() //=> "" - - If the object's class is not defined on an Ember namespace, it will - indicate it is a subclass of the registered superclass: - - Student = App.Person.extend() - student = Student.create() - student.toString() //=> "<(subclass of App.Person):ember1025>" - - If the method `toStringExtension` is defined, its return value will be - included in the output. - - App.Teacher = App.Person.extend({ - toStringExtension: function(){ - return this.get('fullName'); - } - }); - teacher = App.Teacher.create() - teacher.toString(); //=> "" - - @method toString - @return {String} string representation - */ - toString: function toString() { - var hasToStringExtension = typeof this.toStringExtension === 'function', - extension = hasToStringExtension ? ":" + this.toStringExtension() : ''; - var ret = '<'+this.constructor.toString()+':'+guidFor(this)+extension+'>'; - this.toString = makeToString(ret); - return ret; - } -}); - -CoreObject.PrototypeMixin.ownerConstructor = CoreObject; - -function makeToString(ret) { - return function() { return ret; }; -} - -if (Ember.config.overridePrototypeMixin) { - Ember.config.overridePrototypeMixin(CoreObject.PrototypeMixin); -} - -CoreObject.__super__ = null; - -var ClassMixin = Mixin.create({ - - ClassMixin: Ember.required(), - - PrototypeMixin: Ember.required(), - - isClass: true, - - isMethod: false, - - extend: function() { - var Class = makeCtor(), proto; - Class.ClassMixin = Mixin.create(this.ClassMixin); - Class.PrototypeMixin = Mixin.create(this.PrototypeMixin); - - Class.ClassMixin.ownerConstructor = Class; - Class.PrototypeMixin.ownerConstructor = Class; - - reopen.apply(Class.PrototypeMixin, arguments); - - Class.superclass = this; - Class.__super__ = this.prototype; - - proto = Class.prototype = o_create(this.prototype); - proto.constructor = Class; - generateGuid(proto, 'ember'); - meta(proto).proto = proto; // this will disable observers on prototype - - Class.ClassMixin.apply(Class); - return Class; - }, - - createWithMixins: function() { - var C = this; - if (arguments.length>0) { this._initMixins(arguments); } - return new C(); - }, - - create: function() { - var C = this; - if (arguments.length>0) { this._initProperties(arguments); } - return new C(); - }, - - reopen: function() { - this.willReopen(); - reopen.apply(this.PrototypeMixin, arguments); - return this; - }, - - reopenClass: function() { - reopen.apply(this.ClassMixin, arguments); - applyMixin(this, arguments, false); - return this; - }, - - detect: function(obj) { - if ('function' !== typeof obj) { return false; } - while(obj) { - if (obj===this) { return true; } - obj = obj.superclass; - } - return false; - }, - - detectInstance: function(obj) { - return obj instanceof this; - }, - - /** - In some cases, you may want to annotate computed properties with additional - metadata about how they function or what values they operate on. For - example, computed property functions may close over variables that are then - no longer available for introspection. - - You can pass a hash of these values to a computed property like this: - - ```javascript - person: function() { - var personId = this.get('personId'); - return App.Person.create({ id: personId }); - }.property().meta({ type: App.Person }) - ``` - - Once you've done this, you can retrieve the values saved to the computed - property from your class like this: - - ```javascript - MyClass.metaForProperty('person'); - ``` - - This will return the original hash that was passed to `meta()`. - - @method metaForProperty - @param key {String} property name - */ - metaForProperty: function(key) { - var desc = meta(this.proto(), false).descs[key]; - - Ember.assert("metaForProperty() could not find a computed property with key '"+key+"'.", !!desc && desc instanceof Ember.ComputedProperty); - return desc._meta || {}; - }, - - /** - Iterate over each computed property for the class, passing its name - and any associated metadata (see `metaForProperty`) to the callback. - - @method eachComputedProperty - @param {Function} callback - @param {Object} binding - */ - eachComputedProperty: function(callback, binding) { - var proto = this.proto(), - descs = meta(proto).descs, - empty = {}, - property; - - for (var name in descs) { - property = descs[name]; - - if (property instanceof Ember.ComputedProperty) { - callback.call(binding || this, name, property._meta || empty); - } - } - } - -}); - -ClassMixin.ownerConstructor = CoreObject; - -if (Ember.config.overrideClassMixin) { - Ember.config.overrideClassMixin(ClassMixin); -} - -CoreObject.ClassMixin = ClassMixin; -ClassMixin.apply(CoreObject); - -/** - @class CoreObject - @namespace Ember -*/ -Ember.CoreObject = CoreObject; - -})(); - - - -(function() { -/** -@module ember -@submodule ember-runtime -*/ - -/** - `Ember.Object` is the main base class for all Ember objects. It is a subclass - of `Ember.CoreObject` with the `Ember.Observable` mixin applied. For details, - see the documentation for each of these. - - @class Object - @namespace Ember - @extends Ember.CoreObject - @uses Ember.Observable -*/ -Ember.Object = Ember.CoreObject.extend(Ember.Observable); -Ember.Object.toString = function() { return "Ember.Object"; }; - -})(); - - - -(function() { -/** -@module ember -@submodule ember-runtime -*/ - -var get = Ember.get, indexOf = Ember.ArrayPolyfills.indexOf; - -/** - A Namespace is an object usually used to contain other objects or methods - such as an application or framework. Create a namespace anytime you want - to define one of these new containers. - - # Example Usage - - ```javascript - MyFramework = Ember.Namespace.create({ - VERSION: '1.0.0' - }); - ``` - - @class Namespace - @namespace Ember - @extends Ember.Object -*/ -var Namespace = Ember.Namespace = Ember.Object.extend({ - isNamespace: true, - - init: function() { - Ember.Namespace.NAMESPACES.push(this); - Ember.Namespace.PROCESSED = false; - }, - - toString: function() { - var name = get(this, 'name'); - if (name) { return name; } - - findNamespaces(); - return this[Ember.GUID_KEY+'_name']; - }, - - nameClasses: function() { - processNamespace([this.toString()], this, {}); - }, - - destroy: function() { - var namespaces = Ember.Namespace.NAMESPACES; - Ember.lookup[this.toString()] = undefined; - namespaces.splice(indexOf.call(namespaces, this), 1); - this._super(); - } -}); - -Namespace.reopenClass({ - NAMESPACES: [Ember], - NAMESPACES_BY_ID: {}, - PROCESSED: false, - processAll: processAllNamespaces, - byName: function(name) { - if (!Ember.BOOTED) { - processAllNamespaces(); - } - - return NAMESPACES_BY_ID[name]; - } -}); - -var NAMESPACES_BY_ID = Namespace.NAMESPACES_BY_ID; - -var hasOwnProp = ({}).hasOwnProperty, - guidFor = Ember.guidFor; - -function processNamespace(paths, root, seen) { - var idx = paths.length; - - NAMESPACES_BY_ID[paths.join('.')] = root; - - // Loop over all of the keys in the namespace, looking for classes - for(var key in root) { - if (!hasOwnProp.call(root, key)) { continue; } - var obj = root[key]; - - // If we are processing the `Ember` namespace, for example, the - // `paths` will start with `["Ember"]`. Every iteration through - // the loop will update the **second** element of this list with - // the key, so processing `Ember.View` will make the Array - // `['Ember', 'View']`. - paths[idx] = key; - - // If we have found an unprocessed class - if (obj && obj.toString === classToString) { - // Replace the class' `toString` with the dot-separated path - // and set its `NAME_KEY` - obj.toString = makeToString(paths.join('.')); - obj[NAME_KEY] = paths.join('.'); - - // Support nested namespaces - } else if (obj && obj.isNamespace) { - // Skip aliased namespaces - if (seen[guidFor(obj)]) { continue; } - seen[guidFor(obj)] = true; - - // Process the child namespace - processNamespace(paths, obj, seen); - } - } - - paths.length = idx; // cut out last item -} - -function findNamespaces() { - var Namespace = Ember.Namespace, lookup = Ember.lookup, obj, isNamespace; - - if (Namespace.PROCESSED) { return; } - - for (var prop in lookup) { - // These don't raise exceptions but can cause warnings - if (prop === "parent" || prop === "top" || prop === "frameElement") { continue; } - - // get(window.globalStorage, 'isNamespace') would try to read the storage for domain isNamespace and cause exception in Firefox. - // globalStorage is a storage obsoleted by the WhatWG storage specification. See https://developer.mozilla.org/en/DOM/Storage#globalStorage - if (prop === "globalStorage" && lookup.StorageList && lookup.globalStorage instanceof lookup.StorageList) { continue; } - // Unfortunately, some versions of IE don't support window.hasOwnProperty - if (lookup.hasOwnProperty && !lookup.hasOwnProperty(prop)) { continue; } - - // At times we are not allowed to access certain properties for security reasons. - // There are also times where even if we can access them, we are not allowed to access their properties. - try { - obj = Ember.lookup[prop]; - isNamespace = obj && obj.isNamespace; - } catch (e) { - continue; - } - - if (isNamespace) { - Ember.deprecate("Namespaces should not begin with lowercase.", /^[A-Z]/.test(prop)); - obj[NAME_KEY] = prop; - } - } -} - -var NAME_KEY = Ember.NAME_KEY = Ember.GUID_KEY + '_name'; - -function superClassString(mixin) { - var superclass = mixin.superclass; - if (superclass) { - if (superclass[NAME_KEY]) { return superclass[NAME_KEY]; } - else { return superClassString(superclass); } - } else { - return; - } -} - -function classToString() { - if (!Ember.BOOTED && !this[NAME_KEY]) { - processAllNamespaces(); - } - - var ret; - - if (this[NAME_KEY]) { - ret = this[NAME_KEY]; - } else { - var str = superClassString(this); - if (str) { - ret = "(subclass of " + str + ")"; - } else { - ret = "(unknown mixin)"; - } - this.toString = makeToString(ret); - } - - return ret; -} - -function processAllNamespaces() { - var unprocessedNamespaces = !Namespace.PROCESSED, - unprocessedMixins = Ember.anyUnprocessedMixins; - - if (unprocessedNamespaces) { - findNamespaces(); - Namespace.PROCESSED = true; - } - - if (unprocessedNamespaces || unprocessedMixins) { - var namespaces = Namespace.NAMESPACES, namespace; - for (var i=0, l=namespaces.length; i get(this, 'content.length')) throw new Error(OUT_OF_RANGE_EXCEPTION); - this._replace(idx, 0, [object]); - return this; - }, - - insertAt: function(idx, object) { - if (get(this, 'arrangedContent') === get(this, 'content')) { - return this._insertAt(idx, object); - } else { - throw new Ember.Error("Using insertAt on an arranged ArrayProxy is not allowed."); - } - }, - - removeAt: function(start, len) { - if ('number' === typeof start) { - var content = get(this, 'content'), - arrangedContent = get(this, 'arrangedContent'), - indices = [], i; - - if ((start < 0) || (start >= get(this, 'length'))) { - throw new Error(OUT_OF_RANGE_EXCEPTION); - } - - if (len === undefined) len = 1; - - // Get a list of indices in original content to remove - for (i=start; i=idx) { - var item = content.objectAt(loc); - if (item) { - Ember.addBeforeObserver(item, keyName, proxy, 'contentKeyWillChange'); - Ember.addObserver(item, keyName, proxy, 'contentKeyDidChange'); - - // keep track of the index each item was found at so we can map - // it back when the obj changes. - guid = guidFor(item); - if (!objects[guid]) objects[guid] = []; - objects[guid].push(loc); - } - } -} - -function removeObserverForContentKey(content, keyName, proxy, idx, loc) { - var objects = proxy._objects; - if (!objects) objects = proxy._objects = {}; - var indicies, guid; - - while(--loc>=idx) { - var item = content.objectAt(loc); - if (item) { - Ember.removeBeforeObserver(item, keyName, proxy, 'contentKeyWillChange'); - Ember.removeObserver(item, keyName, proxy, 'contentKeyDidChange'); - - guid = guidFor(item); - indicies = objects[guid]; - indicies[indicies.indexOf(loc)] = null; - } - } -} - -/** - This is the object instance returned when you get the `@each` property on an - array. It uses the unknownProperty handler to automatically create - EachArray instances for property names. - - @private - @class EachProxy - @namespace Ember - @extends Ember.Object -*/ -Ember.EachProxy = Ember.Object.extend({ - - init: function(content) { - this._super(); - this._content = content; - content.addArrayObserver(this); - - // in case someone is already observing some keys make sure they are - // added - forEach(Ember.watchedEvents(this), function(eventName) { - this.didAddListener(eventName); - }, this); - }, - - /** - You can directly access mapped properties by simply requesting them. - The `unknownProperty` handler will generate an EachArray of each item. - - @method unknownProperty - @param keyName {String} - @param value {anything} - */ - unknownProperty: function(keyName, value) { - var ret; - ret = new EachArray(this._content, keyName, this); - Ember.defineProperty(this, keyName, null, ret); - this.beginObservingContentKey(keyName); - return ret; - }, - - // .......................................................... - // ARRAY CHANGES - // Invokes whenever the content array itself changes. - - arrayWillChange: function(content, idx, removedCnt, addedCnt) { - var keys = this._keys, key, lim; - - lim = removedCnt>0 ? idx+removedCnt : -1; - Ember.beginPropertyChanges(this); - - for(key in keys) { - if (!keys.hasOwnProperty(key)) { continue; } - - if (lim>0) removeObserverForContentKey(content, key, this, idx, lim); - - Ember.propertyWillChange(this, key); - } - - Ember.propertyWillChange(this._content, '@each'); - Ember.endPropertyChanges(this); - }, - - arrayDidChange: function(content, idx, removedCnt, addedCnt) { - var keys = this._keys, key, lim; - - lim = addedCnt>0 ? idx+addedCnt : -1; - Ember.beginPropertyChanges(this); - - for(key in keys) { - if (!keys.hasOwnProperty(key)) { continue; } - - if (lim>0) addObserverForContentKey(content, key, this, idx, lim); - - Ember.propertyDidChange(this, key); - } - - Ember.propertyDidChange(this._content, '@each'); - Ember.endPropertyChanges(this); - }, - - // .......................................................... - // LISTEN FOR NEW OBSERVERS AND OTHER EVENT LISTENERS - // Start monitoring keys based on who is listening... - - didAddListener: function(eventName) { - if (IS_OBSERVER.test(eventName)) { - this.beginObservingContentKey(eventName.slice(0, -7)); - } - }, - - didRemoveListener: function(eventName) { - if (IS_OBSERVER.test(eventName)) { - this.stopObservingContentKey(eventName.slice(0, -7)); - } - }, - - // .......................................................... - // CONTENT KEY OBSERVING - // Actual watch keys on the source content. - - beginObservingContentKey: function(keyName) { - var keys = this._keys; - if (!keys) keys = this._keys = {}; - if (!keys[keyName]) { - keys[keyName] = 1; - var content = this._content, - len = get(content, 'length'); - addObserverForContentKey(content, keyName, this, 0, len); - } else { - keys[keyName]++; - } - }, - - stopObservingContentKey: function(keyName) { - var keys = this._keys; - if (keys && (keys[keyName]>0) && (--keys[keyName]<=0)) { - var content = this._content, - len = get(content, 'length'); - removeObserverForContentKey(content, keyName, this, 0, len); - } - }, - - contentKeyWillChange: function(obj, keyName) { - Ember.propertyWillChange(this, keyName); - }, - - contentKeyDidChange: function(obj, keyName) { - Ember.propertyDidChange(this, keyName); - } - -}); - - - -})(); - - - -(function() { -/** -@module ember -@submodule ember-runtime -*/ - - -var get = Ember.get, set = Ember.set; - -// Add Ember.Array to Array.prototype. Remove methods with native -// implementations and supply some more optimized versions of generic methods -// because they are so common. -var NativeArray = Ember.Mixin.create(Ember.MutableArray, Ember.Observable, Ember.Copyable, { - - // because length is a built-in property we need to know to just get the - // original property. - get: function(key) { - if (key==='length') return this.length; - else if ('number' === typeof key) return this[key]; - else return this._super(key); - }, - - objectAt: function(idx) { - return this[idx]; - }, - - // primitive for array support. - replace: function(idx, amt, objects) { - - if (this.isFrozen) throw Ember.FROZEN_ERROR ; - - // if we replaced exactly the same number of items, then pass only the - // replaced range. Otherwise, pass the full remaining array length - // since everything has shifted - var len = objects ? get(objects, 'length') : 0; - this.arrayContentWillChange(idx, amt, len); - - if (!objects || objects.length === 0) { - this.splice(idx, amt) ; - } else { - var args = [idx, amt].concat(objects) ; - this.splice.apply(this,args) ; - } - - this.arrayContentDidChange(idx, amt, len); - return this ; - }, - - // If you ask for an unknown property, then try to collect the value - // from member items. - unknownProperty: function(key, value) { - var ret;// = this.reducedProperty(key, value) ; - if ((value !== undefined) && ret === undefined) { - ret = this[key] = value; - } - return ret ; - }, - - // If browser did not implement indexOf natively, then override with - // specialized version - indexOf: function(object, startAt) { - var idx, len = this.length; - - if (startAt === undefined) startAt = 0; - else startAt = (startAt < 0) ? Math.ceil(startAt) : Math.floor(startAt); - if (startAt < 0) startAt += len; - - for(idx=startAt;idx=0;idx--) { - if (this[idx] === object) return idx ; - } - return -1; - }, - - copy: function(deep) { - if (deep) { - return this.map(function(item){ return Ember.copy(item, true); }); - } - - return this.slice(); - } -}); - -// Remove any methods implemented natively so we don't override them -var ignore = ['length']; -Ember.EnumerableUtils.forEach(NativeArray.keys(), function(methodName) { - if (Array.prototype[methodName]) ignore.push(methodName); -}); - -if (ignore.length>0) { - NativeArray = NativeArray.without.apply(NativeArray, ignore); -} - -/** - The NativeArray mixin contains the properties needed to to make the native - Array support Ember.MutableArray and all of its dependent APIs. Unless you - have `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Array` set to - false, this will be applied automatically. Otherwise you can apply the mixin - at anytime by calling `Ember.NativeArray.activate`. - - @class NativeArray - @namespace Ember - @extends Ember.Mixin - @uses Ember.MutableArray - @uses Ember.MutableEnumerable - @uses Ember.Copyable - @uses Ember.Freezable -*/ -Ember.NativeArray = NativeArray; - -/** - Creates an `Ember.NativeArray` from an Array like object. - Does not modify the original object. - - @method A - @for Ember - @return {Ember.NativeArray} -*/ -Ember.A = function(arr){ - if (arr === undefined) { arr = []; } - return Ember.Array.detect(arr) ? arr : Ember.NativeArray.apply(arr); -}; - -/** - Activates the mixin on the Array.prototype if not already applied. Calling - this method more than once is safe. - - @method activate - @for Ember.NativeArray - @static - @return {void} -*/ -Ember.NativeArray.activate = function() { - NativeArray.apply(Array.prototype); - - Ember.A = function(arr) { return arr || []; }; -}; - -if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Array) { - Ember.NativeArray.activate(); -} - - -})(); - - - -(function() { -/** -@module ember -@submodule ember-runtime -*/ - -var get = Ember.get, set = Ember.set, guidFor = Ember.guidFor, none = Ember.isNone, fmt = Ember.String.fmt; - -/** - An unordered collection of objects. - - A Set works a bit like an array except that its items are not ordered. You - can create a set to efficiently test for membership for an object. You can - also iterate through a set just like an array, even accessing objects by - index, however there is no guarantee as to their order. - - All Sets are observable via the Enumerable Observer API - which works - on any enumerable object including both Sets and Arrays. - - ## Creating a Set - - You can create a set like you would most objects using - `new Ember.Set()`. Most new sets you create will be empty, but you can - also initialize the set with some content by passing an array or other - enumerable of objects to the constructor. - - Finally, you can pass in an existing set and the set will be copied. You - can also create a copy of a set by calling `Ember.Set#copy()`. - - ```javascript - // creates a new empty set - var foundNames = new Ember.Set(); - - // creates a set with four names in it. - var names = new Ember.Set(["Charles", "Tom", "Juan", "Alex"]); // :P - - // creates a copy of the names set. - var namesCopy = new Ember.Set(names); - - // same as above. - var anotherNamesCopy = names.copy(); - ``` - - ## Adding/Removing Objects - - You generally add or remove objects from a set using `add()` or - `remove()`. You can add any type of object including primitives such as - numbers, strings, and booleans. - - Unlike arrays, objects can only exist one time in a set. If you call `add()` - on a set with the same object multiple times, the object will only be added - once. Likewise, calling `remove()` with the same object multiple times will - remove the object the first time and have no effect on future calls until - you add the object to the set again. - - NOTE: You cannot add/remove `null` or `undefined` to a set. Any attempt to do - so will be ignored. - - In addition to add/remove you can also call `push()`/`pop()`. Push behaves - just like `add()` but `pop()`, unlike `remove()` will pick an arbitrary - object, remove it and return it. This is a good way to use a set as a job - queue when you don't care which order the jobs are executed in. - - ## Testing for an Object - - To test for an object's presence in a set you simply call - `Ember.Set#contains()`. - - ## Observing changes - - When using `Ember.Set`, you can observe the `"[]"` property to be - alerted whenever the content changes. You can also add an enumerable - observer to the set to be notified of specific objects that are added and - removed from the set. See `Ember.Enumerable` for more information on - enumerables. - - This is often unhelpful. If you are filtering sets of objects, for instance, - it is very inefficient to re-filter all of the items each time the set - changes. It would be better if you could just adjust the filtered set based - on what was changed on the original set. The same issue applies to merging - sets, as well. - - ## Other Methods - - `Ember.Set` primary implements other mixin APIs. For a complete reference - on the methods you will use with `Ember.Set`, please consult these mixins. - The most useful ones will be `Ember.Enumerable` and - `Ember.MutableEnumerable` which implement most of the common iterator - methods you are used to on Array. - - Note that you can also use the `Ember.Copyable` and `Ember.Freezable` - APIs on `Ember.Set` as well. Once a set is frozen it can no longer be - modified. The benefit of this is that when you call `frozenCopy()` on it, - Ember will avoid making copies of the set. This allows you to write - code that can know with certainty when the underlying set data will or - will not be modified. - - @class Set - @namespace Ember - @extends Ember.CoreObject - @uses Ember.MutableEnumerable - @uses Ember.Copyable - @uses Ember.Freezable - @since Ember 0.9 -*/ -Ember.Set = Ember.CoreObject.extend(Ember.MutableEnumerable, Ember.Copyable, Ember.Freezable, - /** @scope Ember.Set.prototype */ { - - // .......................................................... - // IMPLEMENT ENUMERABLE APIS - // - - /** - This property will change as the number of objects in the set changes. - - @property length - @type number - @default 0 - */ - length: 0, - - /** - Clears the set. This is useful if you want to reuse an existing set - without having to recreate it. - - ```javascript - var colors = new Ember.Set(["red", "green", "blue"]); - colors.length; // 3 - colors.clear(); - colors.length; // 0 - ``` - - @method clear - @return {Ember.Set} An empty Set - */ - clear: function() { - if (this.isFrozen) { throw new Error(Ember.FROZEN_ERROR); } - - var len = get(this, 'length'); - if (len === 0) { return this; } - - var guid; - - this.enumerableContentWillChange(len, 0); - Ember.propertyWillChange(this, 'firstObject'); - Ember.propertyWillChange(this, 'lastObject'); - - for (var i=0; i < len; i++){ - guid = guidFor(this[i]); - delete this[guid]; - delete this[i]; - } - - set(this, 'length', 0); - - Ember.propertyDidChange(this, 'firstObject'); - Ember.propertyDidChange(this, 'lastObject'); - this.enumerableContentDidChange(len, 0); - - return this; - }, - - /** - Returns true if the passed object is also an enumerable that contains the - same objects as the receiver. - - ```javascript - var colors = ["red", "green", "blue"], - same_colors = new Ember.Set(colors); - - same_colors.isEqual(colors); // true - same_colors.isEqual(["purple", "brown"]); // false - ``` - - @method isEqual - @param {Ember.Set} obj the other object. - @return {Boolean} - */ - isEqual: function(obj) { - // fail fast - if (!Ember.Enumerable.detect(obj)) return false; - - var loc = get(this, 'length'); - if (get(obj, 'length') !== loc) return false; - - while(--loc >= 0) { - if (!obj.contains(this[loc])) return false; - } - - return true; - }, - - /** - Adds an object to the set. Only non-`null` objects can be added to a set - and those can only be added once. If the object is already in the set or - the passed value is null this method will have no effect. - - This is an alias for `Ember.MutableEnumerable.addObject()`. - - ```javascript - var colors = new Ember.Set(); - colors.add("blue"); // ["blue"] - colors.add("blue"); // ["blue"] - colors.add("red"); // ["blue", "red"] - colors.add(null); // ["blue", "red"] - colors.add(undefined); // ["blue", "red"] - ``` - - @method add - @param {Object} obj The object to add. - @return {Ember.Set} The set itself. - */ - add: Ember.aliasMethod('addObject'), - - /** - Removes the object from the set if it is found. If you pass a `null` value - or an object that is already not in the set, this method will have no - effect. This is an alias for `Ember.MutableEnumerable.removeObject()`. - - ```javascript - var colors = new Ember.Set(["red", "green", "blue"]); - colors.remove("red"); // ["blue", "green"] - colors.remove("purple"); // ["blue", "green"] - colors.remove(null); // ["blue", "green"] - ``` - - @method remove - @param {Object} obj The object to remove - @return {Ember.Set} The set itself. - */ - remove: Ember.aliasMethod('removeObject'), - - /** - Removes the last element from the set and returns it, or `null` if it's empty. - - ```javascript - var colors = new Ember.Set(["green", "blue"]); - colors.pop(); // "blue" - colors.pop(); // "green" - colors.pop(); // null - ``` - - @method pop - @return {Object} The removed object from the set or null. - */ - pop: function() { - if (get(this, 'isFrozen')) throw new Error(Ember.FROZEN_ERROR); - var obj = this.length > 0 ? this[this.length-1] : null; - this.remove(obj); - return obj; - }, - - /** - Inserts the given object on to the end of the set. It returns - the set itself. - - This is an alias for `Ember.MutableEnumerable.addObject()`. - - ```javascript - var colors = new Ember.Set(); - colors.push("red"); // ["red"] - colors.push("green"); // ["red", "green"] - colors.push("blue"); // ["red", "green", "blue"] - ``` - - @method push - @return {Ember.Set} The set itself. - */ - push: Ember.aliasMethod('addObject'), - - /** - Removes the last element from the set and returns it, or `null` if it's empty. - - This is an alias for `Ember.Set.pop()`. - - ```javascript - var colors = new Ember.Set(["green", "blue"]); - colors.shift(); // "blue" - colors.shift(); // "green" - colors.shift(); // null - ``` - - @method shift - @return {Object} The removed object from the set or null. - */ - shift: Ember.aliasMethod('pop'), - - /** - Inserts the given object on to the end of the set. It returns - the set itself. - - This is an alias of `Ember.Set.push()` - - ```javascript - var colors = new Ember.Set(); - colors.unshift("red"); // ["red"] - colors.unshift("green"); // ["red", "green"] - colors.unshift("blue"); // ["red", "green", "blue"] - ``` - - @method unshift - @return {Ember.Set} The set itself. - */ - unshift: Ember.aliasMethod('push'), - - /** - Adds each object in the passed enumerable to the set. - - This is an alias of `Ember.MutableEnumerable.addObjects()` - - ```javascript - var colors = new Ember.Set(); - colors.addEach(["red", "green", "blue"]); // ["red", "green", "blue"] - ``` - - @method addEach - @param {Ember.Enumerable} objects the objects to add. - @return {Ember.Set} The set itself. - */ - addEach: Ember.aliasMethod('addObjects'), - - /** - Removes each object in the passed enumerable to the set. - - This is an alias of `Ember.MutableEnumerable.removeObjects()` - - ```javascript - var colors = new Ember.Set(["red", "green", "blue"]); - colors.removeEach(["red", "blue"]); // ["green"] - ``` - - @method removeEach - @param {Ember.Enumerable} objects the objects to remove. - @return {Ember.Set} The set itself. - */ - removeEach: Ember.aliasMethod('removeObjects'), - - // .......................................................... - // PRIVATE ENUMERABLE SUPPORT - // - - init: function(items) { - this._super(); - if (items) this.addObjects(items); - }, - - // implement Ember.Enumerable - nextObject: function(idx) { - return this[idx]; - }, - - // more optimized version - firstObject: Ember.computed(function() { - return this.length > 0 ? this[0] : undefined; - }), - - // more optimized version - lastObject: Ember.computed(function() { - return this.length > 0 ? this[this.length-1] : undefined; - }), - - // implements Ember.MutableEnumerable - addObject: function(obj) { - if (get(this, 'isFrozen')) throw new Error(Ember.FROZEN_ERROR); - if (none(obj)) return this; // nothing to do - - var guid = guidFor(obj), - idx = this[guid], - len = get(this, 'length'), - added ; - - if (idx>=0 && idx=0 && idx=0; - }, - - copy: function() { - var C = this.constructor, ret = new C(), loc = get(this, 'length'); - set(ret, 'length', loc); - while(--loc>=0) { - ret[loc] = this[loc]; - ret[guidFor(this[loc])] = loc; - } - return ret; - }, - - toString: function() { - var len = this.length, idx, array = []; - for(idx = 0; idx < len; idx++) { - array[idx] = this[idx]; - } - return fmt("Ember.Set<%@>", [array.join(',')]); - } - -}); - -})(); - - - -(function() { -var DeferredMixin = Ember.DeferredMixin, // mixins/deferred - get = Ember.get; - -var Deferred = Ember.Object.extend(DeferredMixin); - -Deferred.reopenClass({ - promise: function(callback, binding) { - var deferred = Deferred.create(); - callback.call(binding, deferred); - return get(deferred, 'promise'); - } -}); - -Ember.Deferred = Deferred; - -})(); - - - -(function() { -/** -@module ember -@submodule ember-runtime -*/ - -var loadHooks = Ember.ENV.EMBER_LOAD_HOOKS || {}; -var loaded = {}; - -/** -@method onLoad -@for Ember -@param name {String} name of hook -@param callback {Function} callback to be called -*/ -Ember.onLoad = function(name, callback) { - var object; - - loadHooks[name] = loadHooks[name] || Ember.A(); - loadHooks[name].pushObject(callback); - - if (object = loaded[name]) { - callback(object); - } -}; - -/** -@method runLoadHooks -@for Ember -@param name {String} name of hook -@param object {Object} object to pass to callbacks -*/ -Ember.runLoadHooks = function(name, object) { - var hooks; - - loaded[name] = object; - - if (hooks = loadHooks[name]) { - loadHooks[name].forEach(function(callback) { - callback(object); - }); - } -}; - -})(); - - - -(function() { - -})(); - - - -(function() { -var get = Ember.get; - -/** -@module ember -@submodule ember-runtime -*/ - -/** - `Ember.ControllerMixin` provides a standard interface for all classes that - compose Ember's controller layer: `Ember.Controller`, - `Ember.ArrayController`, and `Ember.ObjectController`. - - Within an `Ember.Router`-managed application single shared instaces of every - Controller object in your application's namespace will be added to the - application's `Ember.Router` instance. See `Ember.Application#initialize` - for additional information. - - ## Views - - By default a controller instance will be the rendering context - for its associated `Ember.View.` This connection is made during calls to - `Ember.ControllerMixin#connectOutlet`. - - Within the view's template, the `Ember.View` instance can be accessed - through the controller with `{{view}}`. - - ## Target Forwarding - - By default a controller will target your application's `Ember.Router` - instance. Calls to `{{action}}` within the template of a controller's view - are forwarded to the router. See `Ember.Handlebars.helpers.action` for - additional information. - - @class ControllerMixin - @namespace Ember - @extends Ember.Mixin -*/ -Ember.ControllerMixin = Ember.Mixin.create({ - /* ducktype as a controller */ - isController: true, - - /** - The object to which events from the view should be sent. - - For example, when a Handlebars template uses the `{{action}}` helper, - it will attempt to send the event to the view's controller's `target`. - - By default, a controller's `target` is set to the router after it is - instantiated by `Ember.Application#initialize`. - - @property target - @default null - */ - target: null, - - container: null, - - store: null, - - model: Ember.computed.alias('content'), - - send: function(actionName) { - var args = [].slice.call(arguments, 1), target; - - if (this[actionName]) { - Ember.assert("The controller " + this + " does not have the action " + actionName, typeof this[actionName] === 'function'); - this[actionName].apply(this, args); - } else if(target = get(this, 'target')) { - Ember.assert("The target for controller " + this + " (" + target + ") did not define a `send` method", typeof target.send === 'function'); - target.send.apply(target, arguments); - } - } -}); - -/** - @class Controller - @namespace Ember - @extends Ember.Object - @uses Ember.ControllerMixin -*/ -Ember.Controller = Ember.Object.extend(Ember.ControllerMixin); - -})(); - - - -(function() { -/** -@module ember -@submodule ember-runtime -*/ - -var get = Ember.get, set = Ember.set, forEach = Ember.EnumerableUtils.forEach; - -/** - `Ember.SortableMixin` provides a standard interface for array proxies - to specify a sort order and maintain this sorting when objects are added, - removed, or updated without changing the implicit order of their underlying - content array: - - ```javascript - songs = [ - {trackNumber: 4, title: 'Ob-La-Di, Ob-La-Da'}, - {trackNumber: 2, title: 'Back in the U.S.S.R.'}, - {trackNumber: 3, title: 'Glass Onion'}, - ]; - - songsController = Ember.ArrayController.create({ - content: songs, - sortProperties: ['trackNumber'], - sortAscending: true - }); - - songsController.get('firstObject'); // {trackNumber: 2, title: 'Back in the U.S.S.R.'} - - songsController.addObject({trackNumber: 1, title: 'Dear Prudence'}); - songsController.get('firstObject'); // {trackNumber: 1, title: 'Dear Prudence'} - ``` - - @class SortableMixin - @namespace Ember - @extends Ember.Mixin - @uses Ember.MutableEnumerable -*/ -Ember.SortableMixin = Ember.Mixin.create(Ember.MutableEnumerable, { - - /** - Specifies which properties dictate the arrangedContent's sort order. - - @property {Array} sortProperties - */ - sortProperties: null, - - /** - Specifies the arrangedContent's sort direction - - @property {Boolean} sortAscending - */ - sortAscending: true, - - orderBy: function(item1, item2) { - var result = 0, - sortProperties = get(this, 'sortProperties'), - sortAscending = get(this, 'sortAscending'); - - Ember.assert("you need to define `sortProperties`", !!sortProperties); - - forEach(sortProperties, function(propertyName) { - if (result === 0) { - result = Ember.compare(get(item1, propertyName), get(item2, propertyName)); - if ((result !== 0) && !sortAscending) { - result = (-1) * result; - } - } - }); - - return result; - }, - - destroy: function() { - var content = get(this, 'content'), - sortProperties = get(this, 'sortProperties'); - - if (content && sortProperties) { - forEach(content, function(item) { - forEach(sortProperties, function(sortProperty) { - Ember.removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange'); - }, this); - }, this); - } - - return this._super(); - }, - - isSorted: Ember.computed.bool('sortProperties'), - - arrangedContent: Ember.computed('content', 'sortProperties.@each', function(key, value) { - var content = get(this, 'content'), - isSorted = get(this, 'isSorted'), - sortProperties = get(this, 'sortProperties'), - self = this; - - if (content && isSorted) { - content = content.slice(); - content.sort(function(item1, item2) { - return self.orderBy(item1, item2); - }); - forEach(content, function(item) { - forEach(sortProperties, function(sortProperty) { - Ember.addObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange'); - }, this); - }, this); - return Ember.A(content); - } - - return content; - }), - - _contentWillChange: Ember.beforeObserver(function() { - var content = get(this, 'content'), - sortProperties = get(this, 'sortProperties'); - - if (content && sortProperties) { - forEach(content, function(item) { - forEach(sortProperties, function(sortProperty) { - Ember.removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange'); - }, this); - }, this); - } - - this._super(); - }, 'content'), - - sortAscendingWillChange: Ember.beforeObserver(function() { - this._lastSortAscending = get(this, 'sortAscending'); - }, 'sortAscending'), - - sortAscendingDidChange: Ember.observer(function() { - if (get(this, 'sortAscending') !== this._lastSortAscending) { - var arrangedContent = get(this, 'arrangedContent'); - arrangedContent.reverseObjects(); - } - }, 'sortAscending'), - - contentArrayWillChange: function(array, idx, removedCount, addedCount) { - var isSorted = get(this, 'isSorted'); - - if (isSorted) { - var arrangedContent = get(this, 'arrangedContent'); - var removedObjects = array.slice(idx, idx+removedCount); - var sortProperties = get(this, 'sortProperties'); - - forEach(removedObjects, function(item) { - arrangedContent.removeObject(item); - - forEach(sortProperties, function(sortProperty) { - Ember.removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange'); - }, this); - }, this); - } - - return this._super(array, idx, removedCount, addedCount); - }, - - contentArrayDidChange: function(array, idx, removedCount, addedCount) { - var isSorted = get(this, 'isSorted'), - sortProperties = get(this, 'sortProperties'); - - if (isSorted) { - var addedObjects = array.slice(idx, idx+addedCount); - - forEach(addedObjects, function(item) { - this.insertItemSorted(item); - - forEach(sortProperties, function(sortProperty) { - Ember.addObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange'); - }, this); - }, this); - } - - return this._super(array, idx, removedCount, addedCount); - }, - - insertItemSorted: function(item) { - var arrangedContent = get(this, 'arrangedContent'); - var length = get(arrangedContent, 'length'); - - var idx = this._binarySearch(item, 0, length); - arrangedContent.insertAt(idx, item); - }, - - contentItemSortPropertyDidChange: function(item) { - var arrangedContent = get(this, 'arrangedContent'), - oldIndex = arrangedContent.indexOf(item), - leftItem = arrangedContent.objectAt(oldIndex - 1), - rightItem = arrangedContent.objectAt(oldIndex + 1), - leftResult = leftItem && this.orderBy(item, leftItem), - rightResult = rightItem && this.orderBy(item, rightItem); - - if (leftResult < 0 || rightResult > 0) { - arrangedContent.removeObject(item); - this.insertItemSorted(item); - } - }, - - _binarySearch: function(item, low, high) { - var mid, midItem, res, arrangedContent; - - if (low === high) { - return low; - } - - arrangedContent = get(this, 'arrangedContent'); - - mid = low + Math.floor((high - low) / 2); - midItem = arrangedContent.objectAt(mid); - - res = this.orderBy(midItem, item); - - if (res < 0) { - return this._binarySearch(item, mid+1, high); - } else if (res > 0) { - return this._binarySearch(item, low, mid); - } - - return mid; - } -}); - -})(); - - - -(function() { -/** -@module ember -@submodule ember-runtime -*/ - -var get = Ember.get, set = Ember.set, forEach = Ember.EnumerableUtils.forEach, - replace = Ember.EnumerableUtils.replace; - -/** - `Ember.ArrayController` provides a way for you to publish a collection of - objects so that you can easily bind to the collection from a Handlebars - `#each` helper, an `Ember.CollectionView`, or other controllers. - - The advantage of using an `ArrayController` is that you only have to set up - your view bindings once; to change what's displayed, simply swap out the - `content` property on the controller. - - For example, imagine you wanted to display a list of items fetched via an XHR - request. Create an `Ember.ArrayController` and set its `content` property: - - ```javascript - MyApp.listController = Ember.ArrayController.create(); - - $.get('people.json', function(data) { - MyApp.listController.set('content', data); - }); - ``` - - Then, create a view that binds to your new controller: - - ```handlebars - {{#each MyApp.listController}} - {{firstName}} {{lastName}} - {{/each}} - ``` - - Although you are binding to the controller, the behavior of this controller - is to pass through any methods or properties to the underlying array. This - capability comes from `Ember.ArrayProxy`, which this class inherits from. - - Sometimes you want to display computed properties within the body of an - `#each` helper that depend on the underlying items in `content`, but are not - present on those items. To do this, set `itemController` to the name of a - controller (probably an `ObjectController`) that will wrap each individual item. - - For example: - - ```handlebars - {{#each post in controller}} -
  • {{title}} ({{titleLength}} characters)
  • - {{/each}} - ``` - - ```javascript - App.PostsController = Ember.ArrayController.extend({ - itemController: 'post' - }); - - App.PostController = Ember.ObjectController.extend({ - // the `title` property will be proxied to the underlying post. - - titleLength: function() { - return this.get('title').length; - }.property('title') - }); - ``` - - In some cases it is helpful to return a different `itemController` depending - on the particular item. Subclasses can do this by overriding - `lookupItemController`. - - For example: - - ```javascript - App.MyArrayController = Ember.ArrayController.extend({ - lookupItemController: function( object ) { - if (object.get('isSpecial')) { - return "special"; // use App.SpecialController - } else { - return "regular"; // use App.RegularController - } - } - }); - ``` - - @class ArrayController - @namespace Ember - @extends Ember.ArrayProxy - @uses Ember.SortableMixin - @uses Ember.ControllerMixin -*/ - -Ember.ArrayController = Ember.ArrayProxy.extend(Ember.ControllerMixin, - Ember.SortableMixin, { - - /** - The controller used to wrap items, if any. - - @property itemController - @type String - @default null - */ - itemController: null, - - /** - Return the name of the controller to wrap items, or `null` if items should - be returned directly. The default implementation simply returns the - `itemController` property, but subclasses can override this method to return - different controllers for different objects. - - For example: - - ```javascript - App.MyArrayController = Ember.ArrayController.extend({ - lookupItemController: function( object ) { - if (object.get('isSpecial')) { - return "special"; // use App.SpecialController - } else { - return "regular"; // use App.RegularController - } - } - }); - ``` - - @method - @type String - @default null - */ - lookupItemController: function(object) { - return get(this, 'itemController'); - }, - - objectAtContent: function(idx) { - var length = get(this, 'length'), - arrangedContent = get(this,'arrangedContent'), - object = arrangedContent && arrangedContent.objectAt(idx); - - if (idx >= 0 && idx < length) { - var controllerClass = this.lookupItemController(object); - if (controllerClass) { - return this.controllerAt(idx, object, controllerClass); - } - } - - // When `controllerClass` is falsy, we have not opted in to using item - // controllers, so return the object directly. - - // When the index is out of range, we want to return the "out of range" - // value, whatever that might be. Rather than make assumptions - // (e.g. guessing `null` or `undefined`) we defer this to `arrangedContent`. - return object; - }, - - arrangedContentDidChange: function() { - this._super(); - this._resetSubControllers(); - }, - - arrayContentDidChange: function(idx, removedCnt, addedCnt) { - var subControllers = get(this, '_subControllers'), - subControllersToRemove = subControllers.slice(idx, idx+removedCnt); - - forEach(subControllersToRemove, function(subController) { - if (subController) { subController.destroy(); } - }); - - replace(subControllers, idx, removedCnt, new Array(addedCnt)); - - // The shadow array of subcontrollers must be updated before we trigger - // observers, otherwise observers will get the wrong subcontainer when - // calling `objectAt` - this._super(idx, removedCnt, addedCnt); - }, - - init: function() { - this._super(); - if (!this.get('content')) { Ember.defineProperty(this, 'content', undefined, Ember.A()); } - this.set('_subControllers', Ember.A()); - }, - - controllerAt: function(idx, object, controllerClass) { - var container = get(this, 'container'), - subControllers = get(this, '_subControllers'), - subController = subControllers[idx]; - - if (!subController) { - subController = container.lookup("controller:" + controllerClass, { singleton: false }); - subControllers[idx] = subController; - } - - if (!subController) { - throw new Error('Could not resolve itemController: "' + controllerClass + '"'); - } - - subController.set('target', this); - subController.set('content', object); - - return subController; - }, - - _subControllers: null, - - _resetSubControllers: function() { - var subControllers = get(this, '_subControllers'); - - forEach(subControllers, function(subController) { - if (subController) { subController.destroy(); } - }); - - this.set('_subControllers', Ember.A()); - } -}); - -})(); - - - -(function() { -/** -@module ember -@submodule ember-runtime -*/ - -/** - `Ember.ObjectController` is part of Ember's Controller layer. A single shared - instance of each `Ember.ObjectController` subclass in your application's - namespace will be created at application initialization and be stored on your - application's `Ember.Router` instance. - - `Ember.ObjectController` derives its functionality from its superclass - `Ember.ObjectProxy` and the `Ember.ControllerMixin` mixin. - - @class ObjectController - @namespace Ember - @extends Ember.ObjectProxy - @uses Ember.ControllerMixin -**/ -Ember.ObjectController = Ember.ObjectProxy.extend(Ember.ControllerMixin); - -})(); - - - -(function() { - -})(); - - - -(function() { -/** -Ember Runtime - -@module ember -@submodule ember-runtime -@requires ember-metal -*/ - -})(); - -(function() { -/** -@module ember -@submodule ember-views -*/ - -var jQuery = Ember.imports.jQuery; -Ember.assert("Ember Views require jQuery 1.8, 1.9 or 2.0", jQuery && (jQuery().jquery.match(/^((1\.(8|9))|2.0)(\.\d+)?(pre|rc\d?)?/) || Ember.ENV.FORCE_JQUERY)); - -/** - Alias for jQuery - - @method $ - @for Ember -*/ -Ember.$ = jQuery; - -})(); - - - -(function() { -/** -@module ember -@submodule ember-views -*/ -if (Ember.$) { - // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#dndevents - var dragEvents = Ember.String.w('dragstart drag dragenter dragleave dragover drop dragend'); - - // Copies the `dataTransfer` property from a browser event object onto the - // jQuery event object for the specified events - Ember.EnumerableUtils.forEach(dragEvents, function(eventName) { - Ember.$.event.fixHooks[eventName] = { props: ['dataTransfer'] }; - }); -} - -})(); - - - -(function() { -/** -@module ember -@submodule ember-views -*/ - -/*** BEGIN METAMORPH HELPERS ***/ - -// Internet Explorer prior to 9 does not allow setting innerHTML if the first element -// is a "zero-scope" element. This problem can be worked around by making -// the first node an invisible text node. We, like Modernizr, use ­ - -var needsShy = this.document && (function(){ - var testEl = document.createElement('div'); - testEl.innerHTML = "
    "; - var slash = '/'; - testEl.firstChild.innerHTML = "\n); - } - elsif (/GITHASH/) { - my $hash = &githash($index); - print " -- Source: $index, Githash: $hash\n"; - } - else { - print qq($_\n); - } -} - - - - -sub fetch { - my $file = shift; - open F, "<$file" or die "Could not open index: $file $!\n"; - my $hash = &githash($file); - if($file =~ /\.js/) { - my $js; - my $from = "/* js from $file ($hash) */\n"; - if ($type eq 'prod') { - $js = minify(input => *F); - # ember.js (and probably others) contain strings which contain - # which leads to rendering failures, those will be fixed here - $js =~ s/<\/script>/' + Slash + 'script>/g; - close F; - return $from . $js; - } - else { - return $from . join '', ; - close F; - } - } - else { - my $from = "/* css from $file ($hash) */\n"; - my $src = join "", ; - close F; - if ($prod) { - return $from . $src; - } - else { - return $from . css_compress($src); - } - } -} - -sub githash { - my $file = shift; - my $hash = `git hash-object $file`; - chomp $hash; - return $hash; -} diff --git a/samples/digiproof1.png b/samples/digiproof1.png deleted file mode 100644 index 4b4ccba..0000000 Binary files a/samples/digiproof1.png and /dev/null differ diff --git a/samples/digiproof10.png b/samples/digiproof10.png deleted file mode 100644 index 7bf068f..0000000 Binary files a/samples/digiproof10.png and /dev/null differ diff --git a/samples/digiproof2.png b/samples/digiproof2.png deleted file mode 100644 index 19d2a42..0000000 Binary files a/samples/digiproof2.png and /dev/null differ diff --git a/samples/digiproof3.png b/samples/digiproof3.png deleted file mode 100644 index 1036630..0000000 Binary files a/samples/digiproof3.png and /dev/null differ diff --git a/samples/digiproof4.png b/samples/digiproof4.png deleted file mode 100644 index eeb19d5..0000000 Binary files a/samples/digiproof4.png and /dev/null differ diff --git a/samples/digiproof5.png b/samples/digiproof5.png deleted file mode 100644 index 5a0b5ac..0000000 Binary files a/samples/digiproof5.png and /dev/null differ diff --git a/samples/digiproof6.png b/samples/digiproof6.png deleted file mode 100644 index 81f944e..0000000 Binary files a/samples/digiproof6.png and /dev/null differ diff --git a/samples/digiproof7.png b/samples/digiproof7.png deleted file mode 100644 index dd239f1..0000000 Binary files a/samples/digiproof7.png and /dev/null differ diff --git a/samples/digiproof8.png b/samples/digiproof8.png deleted file mode 100644 index a7afa0b..0000000 Binary files a/samples/digiproof8.png and /dev/null differ diff --git a/samples/digiproof9.png b/samples/digiproof9.png deleted file mode 100644 index ccef44e..0000000 Binary files a/samples/digiproof9.png and /dev/null differ diff --git a/samples/sample-testament.pdf b/samples/sample-testament.pdf deleted file mode 100644 index 65c7756..0000000 Binary files a/samples/sample-testament.pdf and /dev/null differ